I am using ms sql server 2005 and I want to do a mass update. I am thinking that I might be able to do it with sending an xml document to a stored procedure.
So I seen many examples on how to do it for insert
CREATE PROCEDURE [dbo].[spTEST_InsertXMLTEST_TEST](@UpdatedProdData XML)
AS
INSERT INTO
dbo.UserTable(CreateDate)
SELECT
@UpdatedProdData.value('(/ArrayOfUserTable/UserTable/CreateDate)[1]', 'DATETIME')
But I am not sure how it would look like for an update.
I am also unsure how do I pass in the xml through ado.net? Do I pass it as a string through a parameter or what?
I know sqlDataApater has a batch update method but I am using linq to sql. So I rather keep using it. So if this works I would be able to grab all records with linq to sql and have them as objects. Then manipulate the objects and use xml seralization.
Finally I could just use ado.net simple to send the xml to the server. This might be slower then the sqlDataAdapter but I am willing to take that hit if I can keep using objects.
Edit
Ok I have this so far
This is my XML
<?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">
<UserTable>
<CreateDate>2011-05-21T11:04:55.0584669-07:00</CreateDate>
<id>0</id>
<AnotherField>false</AnotherField>
</UserTable>
<UserTable>
<CreateDate>2015-05-21T11:04:55.061467-07:00</CreateDate>
<id>0</id>
<AnotherField>true</AnotherField>
</UserTable>
</ArrayOfUserTable>
Two problems occurs with this the first one is
XML parsing: line 1, character 39,
unable to switch the encoding
Second problem is with dates.
Conversion failed when converting
datetime from character string.
Here is my C# code.
using (TestDataContext db = new TestDataContext())
{
UserTable[] testRecords = new UserTable[2];
for (int count = 0; count < 2; count++)
{
UserTable testRecord = new UserTable();
if (count == 1)
{
testRecord.CreateDate = DateTime.Now.AddYears(5);
testRecord.AnotherField = true;
}
else
{
testRecord.CreateDate = DateTime.Now.AddYears(1);
testRecord.AnotherField = false;
}
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);
using (SqlConnection con = new SqlConnection(connectionString))
{
string sprocName = "spTEST_UpdateTEST_TEST";
using (SqlCommand cmd = new SqlCommand(sprocName, con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlParameter param1 = new SqlParameter("@UpdatedProdData", SqlDbType.VarChar, int.MaxValue);
param1.Value = sBuilder.ToString();
cmd.Parameters.Add(param1);
con.Open();
int result = cmd.ExecuteNonQuery();
con.Close();
}
}
}
So to get around those 2 issues I just hand coded a small xml file that did not have the xml tag on top of it and only had MM/DD/YYYY for all dates to make that happy.
But it still does not work
USE [Test]
GO
/****** Object: StoredProcedure [dbo].[spTEST_UpdateTEST_TEST] Script Date: 05/21/2010 11:10:20 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[spTEST_UpdateTEST_TEST](@UpdatedProdData XML)
AS
UPDATE dbo.UserTable
SET CreateDate = @UpdatedProdData.value('(/ArrayOfUserTable/UserTable/CreateDate)[1]', 'DATETIME')
WHERE AnotherField = @UpdatedProdData.value('(/ArrayOfUserTable/UserTable/AnotherField)[1]', 'bit')
This does not even update any records. Also I still think this can only handle one record so I am not sure how to alter it to update many records.
To call the stored proc from straight ADO.NET, you’d use the standard ADO.NET stuff as any programming book on .NET data access or ADO.NET tutorial (just Google for that!) will teach you:
Of course, you might want to wrap this into a try…catch block for exception handling and so forth – but that’s basically the code you’d need to call that stored proc using straight ADO.NET.
UPDATE: in order to update your table from the XML, you should check out the
.nodes()function in XQuery and write your update statement something like this:Basically, you’re shredding your XML into a “virtual” table called
tbl(UPD)– each entry of an<UserTable>tag now is a “row” in that virtual table (thus you can handle many rows), and you grab data from that virtual row to update your base table.For a really good introduction to SQL-XML XQuery in SQL Server 2005 and up, check out this article on 15 Seconds – it’s helped me tremendously to get a grasp on what is possible with XQuery, and how to do it in SQL Server’s XQuery implementation.