3

次のように定義されたテーブルへの挿入、更新、および削除を処理するストアド プロシージャがあります。

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ユーザー定義のテーブル型パラメーターとして厳密に型指定されたものを使用する方法はありますか?

4

2 に答える 2

1

このようなことを試しましたか?

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

型指定された DataSet がまだ通常の DataSet および DataTable のサブクラスである場合、これでうまくいくと思います。

ETA: それはうまくいかないので、これはどうですか?

DataSet DS1 = new DataSet();
DS1.Merge(DT, false, MissingSchemaAction.Add);

// etc.

command.Parameters.AddWithValue("@Testing", DS1.Tables[0]);

それが機能すると仮定すると (そして、必要な結果を得るために Merge メソッドのオーバーロードをいじる必要がある場合があります)、DT のスキーマとデータを持つ DataTable が DataSet に取得されますDataSet1.TestDataTableが、型は になりDataTableます。

于 2012-11-20T12:08:58.820 に答える