相关疑难解决方法(0)

在SQL Server 2005上INSERT WHERE COUNT(*)= 0上违反UNIQUE KEY约束

我从多个进程插入一个SQL数据库.过程有时可能会尝试将重复数据插入表中.我试图以一种处理重复的方式编写查询,但我仍然得到:

System.Data.SqlClient.SqlException: Violation of UNIQUE KEY constraint 'UK1_MyTable'. Cannot insert duplicate key in object 'dbo.MyTable'.
The statement has been terminated.
Run Code Online (Sandbox Code Playgroud)

我的查询看起来像:

INSERT INTO MyTable (FieldA, FieldB, FieldC)
SELECT FieldA='AValue', FieldB='BValue', FieldC='CValue'
WHERE (SELECT COUNT(*) FROM MyTable WHERE FieldA='AValue' AND FieldB='BValue' AND FieldC='CValue' ) = 0
Run Code Online (Sandbox Code Playgroud)

约束'UK1_MyConstraint'表示在MyTable中,3个字段的组合应该是唯一的.

我的问题:

  1. 为什么这不起作用?
  2. 我需要进行哪些修改才能因违反约束而无法出现异常?

请注意,我知道还有其他方法可以解决"INSERT if not exists"的原始问题,例如(摘要):

  • 使用TRY CATCH
  • 如果不存在INSERT(在具有可序列化隔离的事务中)

我应该使用其中一种方法吗?

编辑1个 SQL用于创建表:

CREATE TABLE [dbo].[MyTable](
  [Id] [bigint] IDENTITY(1,1) NOT NULL,
  [FieldA] [bigint] NOT NULL,
  [FieldB] [int] NOT NULL,
  [FieldC] [char](3) NULL,
  [FieldD] [float] …
Run Code Online (Sandbox Code Playgroud)

sql-server sql-server-2005

21
推荐指数
2
解决办法
3万
查看次数

首先对EF代码进行悲观锁定

我想专门锁定我的表中的指定行,因此在实际事务完成之前不会读取任何更新.为此,我在数据库存储库中创建了一个辅助类:

public void PessimisticMyEntityHandler(Action<IEnumerable<MyEntity>> fieldUpdater, string sql, params object[] parameters)
{
    using (var scope = new System.Transactions.TransactionScope())
    {
        fieldUpdater(DbContext.Set<MyEntity>().SqlQuery(sql, parameters));
        scope.Complete();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的测试代码.基本上我只是开始两个任务,他们都尝试用Id'1'锁定行.我的猜测是第二个任务将无法读取(和更新)该行,直到第一个任务完成其作业,但输出窗口显示它实际上可以.

Task.Factory.StartNew(() =>
{
      var dbRepo = new DatabaseRepository();
      dbRepo.PessimisticMyEntityHandler(myEntities =>
      {
                Debug.WriteLine("entered into lock1");

                /* Modify some properties considering the current ones... */
                var myEntity = myEntities.First();
                Thread.Sleep(1500);
                myEntity.MyEntityCode = "abcdefgh";
                dbRepo.Update<MyEntity>(myEntity);

                Debug.WriteLine("leaving lock1");
     }, "SELECT * FROM MyEntities WITH (UPDLOCK, HOLDLOCK) WHERE Id = @param1", new SqlParameter("param1", 1));
});

Task.Factory.StartNew(() =>
{
      Thread.Sleep(500);
      var dbRepo …
Run Code Online (Sandbox Code Playgroud)

c# sql-server asp.net-mvc entity-framework locking

6
推荐指数
1
解决办法
7210
查看次数