【问题标题】:Strongly typed dataset as user defined table type parameter强类型数据集作为用户定义的表类型参数
【发布时间】:2012-11-21 17:33:44
【问题描述】:

我有一个存储过程来处理定义为

的表的插入、更新和删除
CREATE TABLE [dbo].[TestTable](
    [Id] [int] PRIMARY KEY NOT NULL,
    [Data] [nvarchar](50) NOT NULL,
    [ChangeDate] [datetime] NULL)

存储过程

CREATE PROCEDURE MergeTest
    @Testing TestTableType readonly
AS
BEGIN
    MERGE INTO Testing as Target
    USING (SELECT * FROM @Testing) AS SOURCE
        ON (Target.Id = Source.Id)
    WHEN MATCHED THEN
        UPDATE SET 
            Target.Data = Source.Data,
            Target.ChangeDate = Source.ChangeDate
    WHEN NOT MATCHED BY TARGET THEN
        INSERT (Data, ChangeDate)
        VALUES (Source.Data, Source.ChangeDate)
    WHEN NOT MATCHED BY SOURCE THEN
        DELETE;

    RETURN 0;
END

UDT 类型为

CREATE TYPE TestTableType AS TABLE(
    [Id] [int] PRIMARY KEY NOT NULL,
    [Data] [nvarchar](50) NOT NULL,
    [ChangeDate] [datetime] NULL)

我正在尝试使用此结构从 C# 进行批量插入等。使用以下代码即可:

using (SqlConnection connection = new SqlConnection(@"..."))
{
    connection.Open();

    DataTable DT = new DataTable();
    DT.Columns.Add("Id", typeof(int));
    DT.Columns.Add("Data", typeof(string));
    DT.Columns.Add("ChangeDate", typeof(DateTime));

    for (int i = 0; i < 100000; i++)
    {
        DT.AddTestRow((i + 1), (i + 1).ToString(), DateTime.Now);
    }

    using (SqlCommand command = new SqlCommand("MergeTest", connection))
    {
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.AddWithValue("@Testing", DT);
        command.ExecuteNonQuery();
    }
}

但是,当我换行时

DataTable DT = new DataTable();
DT.Columns.Add("Id", typeof(int));
DT.Columns.Add("Data", typeof(string));
DT.Columns.Add("ChangeDate", typeof(DateTime));

DataSet1.TestDataTable DT = new DataSet1.TestDataTable();

这是同一 DataTable 结构的强类型版本,我得到 Argument Exception 错误

不存在从对象类型 TestBulkInsertDataset.DataSet1+TestDataTable 到已知托管提供程序本机类型的映射。

有没有办法使用强类型的DataTable 作为用户定义的表类型参数?

【问题讨论】:

    标签: c# sql-server-2008 strongly-typed-dataset


    【解决方案1】:

    找到答案。使用强类型数据表时,您必须指定参数的类型。参数行变为:

    var testingparam = command.Parameters.AddWithValue("@Testing", DT);
    testingparam.SqlDbType = SqlDbType.Structured;
    

    然后一切正常。

    【讨论】:

      【解决方案2】:

      你尝试过这样的事情吗?

      DataSet1.TestDataTable DT = new DataSet1.TestDataTable();
      
      // Fill data table
      
      DataTable DT1 = DT;  // DataSet1.TestDataTable should be a subclass of DataTable
      
      using (SqlCommand command = new SqlCommand("MergeTest", connection))
      {
          command.CommandType = CommandType.StoredProcedure;
          command.Parameters.AddWithValue("@Testing", DT1);
          command.ExecuteNonQuery();
      }
      

      如果类型化数据集仍然是常规数据集和数据表的子类,我认为这会起作用。

      ETA:既然那行不通,那这个怎么样?

      DataSet DS1 = new DataSet();
      DS1.Merge(DT, false, MissingSchemaAction.Add);
      
      // etc.
      
      command.Parameters.AddWithValue("@Testing", DS1.Tables[0]);
      

      假设可行(并且您可能不得不摆弄 Merge 方法的重载以获得所需的结果),您将在 DataSet 中获得一个 DataTable,其中包含 DT 的架构和数据,DataSet1.TestDataTable,但会只是类型为DataTable

      【讨论】:

      • 我已经试过了,也试过command.Parameters.AddWithValue("@Testing", (DataTable)DT1);,但添加参数似乎取消了变量的装箱
      • 感谢您的回复。我添加了另一个建议。它不是那么整洁,但它可能是一种解决方法。
      • 感谢您的建议。我现在似乎可以正常工作了(我已经发布了我的解决方案作为答案)
      猜你喜欢
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 2011-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      • 1970-01-01
      相关资源
      最近更新 更多