簡體   English   中英

使用ADO.NET的批處理操作

[英]Batch operations using ADO.NET

我正在嘗試使用ADO.NET進行批量插入。 到目前為止,我發現使用SqlDataAdapter可能是一種方法。

我創建了具有1個表和3列的數據庫以及存儲過程,該過程將向該表中插入行。

PropertyTable表:

Name: VARCHAR(10)
Number: INT
IsActive: BIT

存儲過程InsertPropertyTable

CREATE PROCEDURE InsertPropertyTable
    @Par1 VARCHAR(10),
    @Par2 INT,
    @Par3 BIT
AS
BEGIN
    INSERT INTO dbo.PropertyTable
    VALUES (@Par1, @Par2, @Par3)
END
GO

C#代碼:

namespace InsertManyTest.Console
{
    using System;
    using System.Data;
    using System.Data.SqlClient;

    class Program
    {
        static void Main(string[] args)
        {
            var connString = "Server=.;Database=Test;Trusted_Connection=True;";
            using (var connection = new SqlConnection(connString))
            {
                var adapter = new SqlDataAdapter("", connection);

                var dataTable = new DataTable();
                dataTable.Columns.AddRange(new[]
                {
                    new DataColumn("Par1", typeof(string)),
                    new DataColumn("Par2", typeof(int)),
                    new DataColumn("Par3", typeof(bool))
                });

                adapter.InsertCommand = new SqlCommand("InsertPropertyTable", connection);
                adapter.InsertCommand.CommandType = CommandType.StoredProcedure;
                adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None;

                adapter.DeleteCommand = new SqlCommand();
                adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None;
                adapter.UpdateCommand = new SqlCommand();
                adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
                adapter.SelectCommand = new SqlCommand();
                adapter.SelectCommand.UpdatedRowSource = UpdateRowSource.None;

                adapter.InsertCommand.Parameters.Add("@Par1", SqlDbType.VarChar,10, "Par1");
                adapter.InsertCommand.Parameters.Add("@Par2", SqlDbType.Int, 1, "Par2");
                adapter.InsertCommand.Parameters.Add("@Par3", SqlDbType.Bit, 1, "Par3");

                CreateRow(dataTable);
                CreateRow(dataTable);
                CreateRow(dataTable);
                CreateRow(dataTable);

                adapter.UpdateBatchSize = 2;
                adapter.Update(dataTable);
            }
        }

        private static void CreateRow(DataTable dataTable)
        {
            var row = dataTable.NewRow();
            FillRow(row);
            dataTable.Rows.Add(row);
        }

        private static void FillRow(DataRow row)
        {
            row["Par1"] = "Asd";
            row["Par2"] = 1;
            row["Par3"] = true;
        }
    }
}

UpdateBatchSize設置為默認值( 1 )時,它可以工作,但每次插入都會往返。 我想避免這種情況,所以我將UpdateBatchSize設置為更大的值,但是隨后出現一些奇怪的異常:

System.ArgumentException:'指定的參數名稱'Parameter1'無效。

來自adaper.Update(...);

我期望此更新將生成如下內容:

sp_exec InsertPropertyTable 'Asd', 1;
sp_exec InsertPropertyTable 'Asd', 1;
sp_exec InsertPropertyTable 'Asd', 1;
sp_exec InsertPropertyTable 'Asd', 1;

將在單次往返數據庫中執行


更新:我在堆棧溢出時發現了這個問題,作者正在對我做類似的事情。 在他的情況下,它是有效的,並且他與其他批量插入方式進行了比較

使用SP批量插入

2008年的博客文章


更新:

我是啞巴啞巴 我在.net core 2.2而不是.net 4.6.1中進行了測試。 它不能在.net core 2.2上運行,但可以在.net 4.6.1上運行。

我沒有看到預期的結果,因為sql server profiler中有幾行。 每行包含一個exec ...

似乎您可以使用表值參數。

基本上,您在SQL Server端創建新的自定義類型,該類型反映了要發送到存儲過程的數據結構(一行)。 然后,使用該類型通知存儲過程接受的參數類型。 一旦在存儲過程中被接收,您就可以將該表值參數作為任何其他表進行查詢:例如,從中選擇所有內容並插入到實際表中。

ref1: https ://docs.microsoft.com/zh-CN/sql/relational-databases/tables/use-table-valued-parameters-database-engine view = sql-server-2017

ref2: https : //docs.microsoft.com/zh-CN/dotnet/framework/data/adonet/sql/table-valued-parameters

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM