views:

84

answers:

1

Hello,

I have an application that converts one database to another and one of the functions I use is insert_Note below. This application has multipule threads all inserting diffrent data into the new database. The code below works for a number of inserts ranging between 24 and 120 but then fails with the error:

There are fewer columns in the INSERT statement than values specified in the VALUES clause. The number of values in the VALUES clause must match the number of columns specified in the INSERT statement.

I you look at the code you will see that this cannot be the problem as the code works for some inserts but not all. What else can cause this error in a multithread application? Any ideas would be welcome as I have spent three days on this and got no where!

*Public sub insert_Note
    Dim sql As String
    Dim cmd As New SqlClient.SqlCommand
    sql = "INSERT INTO notes ("
    sql &= "RefID,"
    sql &= "TypeID,"
    sql &= "DateEntered,"
    sql &= "Username,"
    sql &= "Subject,"
    sql &= "Body,"
    sql &= "DoNotSendToWeb,"
    sql &= "Deleted,"
    sql &= "SubTypeID"
    sql &= ")  VALUES ("
    sql &= "@RefID,"
    sql &= "@TypeID,"
    sql &= "@DateEntered,"
    sql &= "@Username,"
    sql &= "@Subject,"
    sql &= "@Body,"
    sql &= "@DoNotSendToWeb,"
    sql &= "@Deleted,"
    sql &= "@SubTypeID"
    sql &= ")"
    cmd.CommandText = sql
    cmd.Parameters.AddWithValue("@RefID", 0)
    cmd.Parameters.AddWithValue("@TypeID", 0)
    cmd.Parameters.AddWithValue("@DateEntered", DBNull.Value)
    cmd.Parameters.AddWithValue("@Username", DBNull.Value)
    cmd.Parameters.AddWithValue("@Subject", DBNull.Value)
    cmd.Parameters.AddWithValue("@Body", DBNull.Value)
    cmd.Parameters.AddWithValue("@DoNotSendToWeb", DBNull.Value)
    cmd.Parameters.AddWithValue("@Deleted", DBNull.Value)
    cmd.Parameters.AddWithValue("@SubTypeID", DBNull.Value)
    Using DotNetdatabase As New DBAccessLayer.DBAccessLayer(VBDotNetConn)
        Try
            Dim ds As DataSet
            ds = DotNetdatabase.OpenDataSetWithoutErrorMsg(cmd)
            Return (0)
        Catch ex As Exception
         AddToErrorLog(ex.Message, "Adding Note")
            Throw ex
        End Try
    End Using
End Function

public class DBAccessLayer
    private myConnection as SqlConnection
    Public Sub New(ByVal strConnectionString As String)
          myConnection = New SqlConnection(strConnectionString)
    End Sub
     Public Function OpenDataSetWithoutErrorMsg(ByVal myCommand As SqlCommand) As DataSet
            Dim MyDataSet As New DataSet
            Dim myDataAdapter As SqlDataAdapter
            Try
                Dim blnInitiallyOpen As Boolean = True

                    myConnection.Open()
                    Do Until myConnection.State = ConnectionState.Open
                            Threading.Thread.Sleep(100)
                    Loop

                    myCommand.CommandTimeout = 0
                    myCommand.Connection = myConnection
                    myDataAdapter = New SqlDataAdapter(myCommand)
                    myDataAdapter.Fill(MyDataSet)

                    myConnection.Close()

                    Return MyDataSet
            Catch e As Exception
                    If myConnection.State = ConnectionState.Open Then
                        myConnection.Close()
                    End If
                    Throw e
                   Return Nothing
               End Try
    End Function
end class*

Thanks,

Hugh If knowlege can create problems it is not through ignorance that we will solve them.

Isaac Asimov

+3  A: 

Hugh:

How I might go about solving this problem:

1) in your catch, specifically catch the error concerning fewer columns in the insert. Then log the command text and parameter values / or manually investigate. If you don't see your problem there, then post the results of that logging to your question. If you do see the problem, then choose my answer :) --> I wonder, what if a parameter such as @Body were to be an empty string, instead of null? What would the insert statement look like?

2) I'm a db programmer. This code belongs in a stored procedure. Much easier to debug.

3) Have you been able to narrow the occurrence down to a set of data?

4) Go with Yellowfog's logic - is there a trigger, or just as importantly - some other piece of code being fired along the connection - happening in sequence that you might be generating the error, but once bubbled up to where ever you are seeing it makes it appear to be this code? I know that often when I'm sure that a piece of code couldn't cause a particular exception, I'm right, I've just been looking at the wrong code.

5) Use a sql server profiler to see what statements are actually being executed. The events I would add are: TSQL-SQL:StmtCompleted & SQL:StmtStarting, Errors and Warnings: All of them. It will be easiest to do this on a box with as little traffic as possible. This page might help you get started.

MaasSql
+1 For the comment that this belongs in a stored procedure.
Josaph
Thanks for the response. I eventualy resolved this issue. It was a missing comma in an unrelated sql statement.I think the error handler was getting mixed up becuase the application was multithreaded and was therefore throwing the error in the wrong place, which is why it took me three days to track down the bug.
Hugh Leslie
@hugh again - another important comment - this looks like a prime candidate for the strategy (a) Create an attached/linked table in one database pointing to the table in the other; (b) In the db that can see both tables, use the syntax INSERT INTO NewTable ... SELECT ... from OldTable. List the column names. The DBMS will optimize the index creation, data transfer, etc. Especially if you have a large amount of data, you'll think you'd died and gone to heaven.
FastAl
@hugh - If this answer didn't help you, Add your comments in an answer and mark it solved, I believe that's the way to tell people looking to solve questions on SOF that they shouldn't spend time reading this. But it sounds like it could have helped. I almost added a solution because I almost missed your comment. **ALSO** - you may have figured it out by now but you didn't mention it. First thing to do when debugging a wierd error in multiple threads is shut off all but one. If that's a hard thing to do, then I can't imagine how nasty the threading infrastructure might be ;-)
FastAl