在给定的时间,我将接收大约1000条记录,我必须确定它们是现有记录还是新记录。
如果它们存在,我必须更新记录,如果是新记录,则只需插入它们。我不知道它们是否会存在或全部存在。
我认为最好对数据库进行一次查询,然后尝试查找数据库中是否存在任何查询并将其存储在内存中,然后在内存中检查该集合并进行检查。
最初,我被告知我1个字段足以确定唯一性。所以我以为我可以对数据库中的1个字段执行1个大的子句,但现在我发现情况并非如此,我需要使用3个字段来确定记录是否存在。
这基本上是一个and子句
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次独立查询要好。
答案 0 :(得分:6)
我只能帮您编写查询请求
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 ";
}
答案 1 :(得分:1)
我写这个答案有点愚蠢,因为我认为您应该能够将其他文章的完整答案整理在一起-但这与我所想到的任何一个问题都不完全相同。
Stackoverflow中已经存在解决此问题的问题和答案-但是,在我的搜索中,我仅发现不是线程安全的答案,并且大多数答案都使用merge
。
我可以推荐您使用不同的问题和答案,例如 我对Adding multiple parameterized variables to a database in c# 的回答,在这里您可以看到如何在C#上使用表值参数,对Aaron Bertrand对Using a if condition in an insert 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();
}
}
现在,您可以使用表值参数进行完整而安全的更新,而在C#和sql server之间只有一次往返。