如何创建一个存储过程,它接受XML并使用该xml作为Update +使用ado.net调用此存储过程?

时间:2010-05-21 04:36:26

标签: sql xml sql-server-2005 ado.net

我正在使用ms sql server 2005,我想进行大规模更新。我想我可以将xml文档发送到存储过程。

所以我看到很多关于如何插入

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

但我不确定更新会是什么样子。

我也不确定如何通过ado.net传递xml?我是通过参数传递它作为字符串还是什么?

我知道sqlDataApater有一个批量更新方法,但我使用linq来实现sql。所以我宁愿继续使用它。所以,如果这有效,我将能够使用linq获取所有记录到sql并将它们作为对象。然后操纵对象并使用xml seralization。

最后我可以使用ado.net simple将xml发送到服务器。这可能比sqlDataAdapter慢,但如果我可以继续使用对象,我愿意接受这个命中。

修改

好的我到目前为止

这是我的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>

第一个问题出现了两个问题

  

XML解析:第1行,第39个字符,   无法切换编码

第二个问题是日期。

  

转换时转换失败   来自字符串的日期时间。

这是我的C#代码。

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();
      }
   }
}

因此,为了解决这两个问题,我只是手工编写了一个小的xml文件,该文件没有xml标签,只有MM / DD / YYYY才能让所有日期都满意。

但它仍然不起作用

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')

这甚至不更新任何记录。此外,我仍然认为这只能处理一条记录,所以我不知道如何更改它以更新许多记录。

3 个答案:

答案 0 :(得分:0)

要从直接的ADO.NET调用存储过程,你可以使用标准的ADO.NET内容作为任何关于.NET数据访问的编程书籍或ADO.NET教程(只有谷歌那样!)将教你:< / p>

using(SqlConnection con = new SqlConnection(your-connection-string-here))
{
     string sprocName = "spTEST_InsertXMLTEST_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 = YourXmlValueHere;
         cmd.Parameters.Add(param1);

         con.Open();
         int result = cmd.ExecuteNonQuery();
         con.Close();
     }    
}

当然,您可能希望将其包装到try ... catch块中以进行异常处理等等 - 但这基本上是您需要使用直接ADO.NET调用该存储过程的代码。

UPDATE:为了从XML更新您的表,您应该查看XQuery中的.nodes()函数并编写更新语句,如下所示:

UPDATE 
   dbo.UserTable
SET 
   CreateDate =  tbl.UPD.value('(CreateDate)[1]', 'DATETIME')
FROM
    @UpdatedProdData.nodes('/ArrayOfUserTable/UserTable') AS tbl(UPD)
WHERE 
    AnotherField =  tbl.UPD.value('(AnotherField)[1]', 'bit')

基本上,您将XML分解为名为tbl(UPD)的“虚拟”表 - <UserTable>标记的每个条目现在都是该虚拟表中的“行”(因此您可以处理许多()行,并从该虚拟行中获取数据以更新基表。

为了在SQL Server 2005及更高版本中对SQL-XML XQuery进行非常好的介绍,请查看此article on 15 Seconds - 这对于了解XQuery的可能性以及如何在SQL Server的XQuery实现。

答案 1 :(得分:0)

我认为您可以将XML放入临时表中,然后将其用于更新存储过程的一部分。不确定是否能回答问题!

答案 2 :(得分:0)

为此传递XMLDOC1作为过程中的参数。 在.net代码中写入数据集.Writexml 这将赋予字符串变量并将该字符串作为参数传递给过程。 下面是如何在程序中获取数据的示例。 @ XMLDoc1 as text

DECLARE @ idoc1 as int

EXEC sp_xml_preparedocument @ idoc1 OUTPUT,@ XMLDoc1

选择*进入#TableName
   FROM OPENXML(@ idoc1,'/ NewDataSet / Tablename',2)
   WITH(表格结构如下) (PrefDetailID int
   ,PrefID int)

- 从#TableName

中选择*

EXEC sp_xml_removedocument @ idoc1
现在你在#TableName中获得了所有数据,并在程序中随意操作插入或更新任何东西 或者查看以下链接我自己的博客 http://sqlmca.wordpress.com/2009/07/29/how-to-get-data-from-dataset-into-sqlserver-table-by-using-openxml-method/