Dapper插入,检查记录是否存在

11

所以我一直在使用这种方法将记录插入到我的数据库中:

TransactionBlock.Connection.Execute(
                            "INSERT Table(Item,Id)VALUES(@Item, @Id);
                            new {Item,Id = id }, TransactionBlock.Transaction);

我现在需要修改它,首先要检查Item/id是否已经在数据库中,使用以下语句:

const sql = "IF EXISTS (SELECT * FROM Table, where Item=@Item...etc etc

但我还没有找到任何如何实现这一点的示例。我可以通过创建存储过程来实现这一点,但我想尝试使用这种方法来完成。


1
这不是Dapper的问题,更多的是SQL的问题。你使用哪个后端数据库,SQL Server、MSSQL、Oracle等? - James
SQL Server。我可以通过从Dapper调用纯SP来实现我想要的内容,只是不确定如何使用dapper呈现内联检查。同意,这不是dapper的直接问题,而是如何: - CSharpNewBee
3个回答

9
假设您正在使用SQL Server,并且只想在记录不存在时插入记录,所需的SQL语句如下:
IF NOT EXISTS (SELECT * FROM Table WHERE Id = @Id) 
    INSERT INTO Table(Item, Id) VALUES(@Item, @Id)

4
个人而言,我会将其作为“WHERE”子句添加到“INSERT”中,而不是进行两个单独的操作。 - Marc Gravell
@MarcGravell,怎么做才能实现?对我来说,insert Table(Item, Id) VALUES(@Item, @Id) WHERE Id <> @Id 失败了,显示错误信息为“关键字'where'附近有语法错误”。 - user854301
1
@user854301 尝试使用 WHERE NOT EXISTS (SELECT Id FROM Table WHERE Id = @Id) - James
@user854301,如果你想一步完成它,请参考Matt的答案;然而,这里展示的SQL也是可以的。 - Marc Gravell
@MarcGravell,终于搞定了。我已经用select替换了values,非常感谢。 - user854301

5
INSERT INTO TableName (Item, ID)
SELECT @Item, @Id WHERE NOT EXISTS ( SELECT 1 FROM TableName WHERE Id=@Id )

这将只需要一条语句。

值得注意的是,取决于底层DBMS,仍可能存在争用 - 如果没有发出锁定并且同时发生许多插入,则可能会出现在执行选择时记录不存在但在尝试插入之前存在的情况。

如果你正在处理大量插入的情况,我建议你熟悉下面的内容:

http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx

祝你好运!


-2
不妨使用 try/catch 时钟来执行插入操作,并捕获 DuplicateKeyException(不确定是否存在)以确定重复项,而不是在插入之前检查其是否存在。

4
下投票。如果可以预防异常,为什么还要捕获它们?这样做不太“对劲”。 - avb
4
@avb1994,因为如果您要在表中插入100,000个项目,并且可能有10%是重复的,那么系统化地插入并检测重复项异常是有意义的。否则,您需要为每次插入执行100,000次读取。这就是我的推理。 - Raj
4
异常处理很耗费资源,不应用于控制逻辑流程。 - Ashley Lee
7
每次抛出异常,就会烧毁一个小村庄。 - Bagzli
1
@Raj,你不能避免那个读取操作。服务器必须读取索引值以确定是否存在违规情况。异常和错误的代价更高,因为它们不应该经常发生。 - Panagiotis Kanavos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接