views:

329

answers:

1

Hi

I been following this tutorial on how to do a linq to sql batch insert.

http://www.codeproject.com/KB/linq/BulkOperations_LinqToSQL.aspx

However I have a datetime field in my database and I keep getting this error.

System.Data.SqlClient.SqlException was unhandled Message="Conversion failed when converting datetime from character string." Source=".Net SqlClient Data Provider"
ErrorCode=-2146232060 Class=16
LineNumber=7 Number=241
Procedure="spTEST_InsertXMLTEST_TEST" Server="" State=1 StackTrace: at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)

I am not sure why when I just take the datetime in the generated xml file and manually copy it into sql server 2005 it has no problem with it and converts it just fine.

This is my SP

CREATE PROCEDURE [dbo].[spTEST_InsertXMLTEST_TEST](@UpdatedProdData nText)
AS 
 DECLARE @hDoc int   

 exec sp_xml_preparedocument @hDoc OUTPUT,@UpdatedProdData 

 INSERT INTO UserTable(CreateDate)
 SELECT XMLProdTable.CreateDate
    FROM OPENXML(@hDoc, 'ArrayOfUserTable/UserTable', 2)   
       WITH (                
                CreateDate datetime
            ) XMLProdTable

EXEC sp_xml_removedocument @hDoc

C# code

using (TestDataContext db = new TestDataContext())
{
   UserTable[] testRecords = new UserTable[1];
   for (int count = 0; count < 1; count++)
   {
      UserTable testRecord = new UserTable()
      {
         CreateDate = DateTime.Now                     
      };

      testRecords[count] = testRecord;
   }

   StringBuilder sBuilder = new StringBuilder();
   System.IO.StringWriter sWriter = new System.IO.StringWriter(sBuilder);
   XmlSerializer serializer = new XmlSerializer(typeof(UserTable[]));
   serializer.Serialize(sWriter, testRecords);
   db.spTEST_InsertXMLTEST_TEST(sBuilder.ToString());
}

Rendered XML Doc

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfUserTable xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <UserTable>
    <CreateDate>2010-05-19T19:35:54.9339251-07:00</CreateDate>
  </UserTable>
</ArrayOfUserTable>
A: 

OK, couple of things:

First: if you're using the XML datatype, you must be on SQL Server 2005 or newer, right?

Hint: stop using NTEXT as a data type! NOW! So instead of (@UpdatedProdData nText) you should definitely use (@UpdatedProdData NVARCHAR(MAX))

Secondly - if you're already using SQL Server 2005 and XQuery, I would definitely rewrite that stored procedure to not use OPENXML and all those methods - those are deprecated and not really needed. Try this instead:

CREATE PROCEDURE [dbo].[spTEST_InsertXMLTEST_TEST](@UpdatedProdData NVARCHAR(MAX))
AS BEGIN
   DECLARE @InputData XML

   SET @InputData = CAST(@UpdatedProdData AS XML)

   INSERT INTO 
      dbo.UserTable(CreateDate)
      SELECT
         @InputData.value('(/ArrayOfUserTable/UserTable/CreateDate)[1]', 'DATETIME')   

You can make this even easier if you pass in a thing of datatype XML directly:

CREATE PROCEDURE [dbo].[spTEST_InsertXMLTEST_TEST](@UpdatedProdData XML)
AS 
   INSERT INTO 
      dbo.UserTable(CreateDate)
      SELECT
         @UpdatedProdData.value('(/ArrayOfUserTable/UserTable/CreateDate)[1]', 'DATETIME')   

Try it!

marc_s
Intresting.Can you please explain why these 2 ways are better and why you should not use "nText"? Also why do you have [1]? In this case I only have one record but this is just a test I will have many records. I am using SQL Server 2005 and I not sure if I am using XQuery.
chobo2
I tried to do your 2nd option but I keep getting. Line 3The value function requires 2 argument(s).
chobo2
Ah I see why I am getting that error. It was because I thought when doing varchars you needed a 3rd parameter for length but instead you just have it like 'varchar(50)'
chobo2
Hmm now I am getting unknown return type when I try to drag my SP from linq to sql to the designer view. I know it should be 'none'
chobo2
Also I see now I have to pass a System.Xml.Linq.XElement before I use to pass in a string builder. So how I change it to this new type?
chobo2
@chobo2: TEXT/NTEXT are deprecated as of SQL Server 2005 - they are not guaranteed to be around in the next SQL Server version. Also, using NVARCHAR(MAX) is better since you can use all the usual string manipulation functions on those variables - something you cannot do on NTEXT variables
marc_s