簡體   English   中英

在Ado.net C中動態構建Where子句#

[英]Build Where Clause Dynamically in Ado.net C#

我將在給定時間內收集大約1000條記錄,我必須確定它們是現有記錄還是新記錄。

如果它們存在,我必須更新記錄,如果是新的,則只需插入它們。 我不知道他們中的任何一個是否存在,或者它們是否都存在。

我認為最好對數據庫進行一次查詢並嘗試查找數據庫中是否存在任何查詢並將其存儲在內存中並檢查該內存中的集合並檢查它。

最初我被告知我1場將足以確定唯一性。 所以我想我可以在數據庫中對1個字段做一個大的子句,但現在我發現情況並非如此,我需要使用3個字段來確定記錄是存在還是現在。

這基本上是一個和條款

select * from where columnA = "1" and ColumnB = "2" and ColumnC = "3"

我怎樣才能在C#ado.net中正確地理解這一點?

我猜我需要有一些超級where子句?

select * from where (columnA = "1" and ColumnB = "2" and ColumnC = "3") or  (columnA = "4" and ColumnB = "5" and ColumnC = "6") or [....998 more conditional clauses)

如果可能的話,我願意接受更好的想法。 我仍然認為一次性完成它比做1000次單獨查詢更好。

我只能幫助您為您的請求編寫查詢

        var recordCount = 1000;
        var query = "SELECT * FROM TableName WHERE";
        for (var i = 1; i < recordCount - 2; i += 3)
        {
            query += " (columnA = " + i + " and ColumnB = " + (i + 1) + " and ColumnC = " + (i + 2) + ") or ";
        }

我覺得寫這個答案有點傻,因為我認為你應該能夠把這些文章從其他帖子中完整地回答 - 但這並不是我想到的任何一個問題的完全重復。

Stackoverflow中已經有問題和答案處理這個問題 - 但是在我的搜索中我只找到了非線程安全的答案,而且大多數答案都是使用merge

我可以向您推薦不同的問題和答案,例如我在c#向數據庫添加多個參數化變量的答案,您可以在c#中查看如何使用表值參數,以及Aaron Bertrand對使用if條件的回答插入SQL Server ,你可以看到如何創建一個安全的upsert - 但是我沒有找到任何完全覆蓋這個的答案 - 所以你去:

首先,您需要在數據庫中創建用戶定義的表類型:

CERATE TYPE MyTableType AS TABLE
(
     Column1 int NOT NULL,
     Column2 int NOT NULL,
     Column3 int NOT NULL,
     -- rest of the columns in your table goes here
     PRIMARY KEY (Column1, Column2, Column3)
)

然后,您創建存儲過程:

CREATE stp_UpsertMyTable
(
    @MyTableType dbo.MyTableType readonly -- table valued parameters must be readonly
)
AS

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

BEGIN TRANSACTION;

UPDATE t 
SET t.column4 = tvp.column4,
    t.column5 = tvp.column5 -- and so on for all columns that are not part of the key
FROM dbo.MyTable AS t
INNER JOIN @MyTableType AS tvp
    ON t.Column1 = tvp.Column1
    AND t.Column2 = tvp.Column2
    AND t.Column3 = tvp.Column3;

 -- Note: <ColumnsList> should be replaced with the actual columns in the table
INSERT dbo.MyTable(<ColumnsList>)
  SELECT <ColumnsList>
  FROM @MyTableType AS tvp
  WHERE NOT EXISTS
  (
    SELECT 1 FROM dbo.MyTable t
    WHERE t.Column1 = tvp.Column1
    AND t.Column2 = tvp.Column2
    AND t.Column3 = tvp.Column3
  );

COMMIT TRANSACTION;

GO

然后,c#部分很簡單:

DataTable dt = new DataTable();
dt.Columns.Add("Column1", typeof(int));
dt.Columns.Add("Column2", typeof(int));
dt.Columns.Add("Column3", typeof(int));
dt.Columns.Add("Column4", typeof(string));
dt.Columns.Add("Column5", typeof(string));

// Fill your data table here

using (var con = new SqlConnection("ConnectionString"))
{
    using(var cmd = new SqlCommand("stp_UpsertMyTable", con))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add("@MyTable", SqlDbType.Structured).Value = dt;
        con.Open();
        cmd.ExecuteNonQuery();
    }
}

現在,您可以使用表值參數進行完整且安全的upsert,在c#和sql server之間只進行一次往返。

暫無
暫無

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

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