繁体   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