0

在我的 C# 项目中,我有一个方法询问数据库中是否存在对象,如果不存在则创建它。现在,如果两个用户同时提出相同的问题,他们都会得到 null,因此流程将保存到 db,这对于两个重复项来说是不可能的,因此会引发 sql 异常。请问我该如何处理这个问题?

这是我的代码:

var date = DateTime.UtcNow.Date;


var todayCelebPageView = _celebPageViewsRepo.GetAll().SingleOrDefault(d => d.iCelebId == celebId && d.dDate == date);

if (todayCelebPageView != null)
{
    todayCelebPageView.iScore++;

    _celebPageViewsRepo.Save();
}
else
{
    todayCelebPageView = new MovliCelebPageView() {dDate = date, iCelebId = celebId, iScore = 1};
    _celebPageViewsRepo.Add(todayCelebPageView);
    _movliRepository.DbContext.Entry(todayCelebPageView).State = System.Data.EntityState.Added;
    _celebPageViewsRepo.Save();
}
4

3 回答 3

2

确实没有简单的答案,这是许多解决方案的常见问题。

一些选项可能是:

  1. 捕获正确的 SQL 异常,并相应地重试
  2. 为这些数据库调用创建一个队列,并一次处理一个
  3. 锁定的一些实现,或者在数据库中(可能通过将其包装在事务中)或在代码本身中。

其他需要考虑的事情是,从业务角度来看,当同时进行两次创建记录的尝试时会发生什么。

最后创造纪录的人应该赢吗?第一个人应该赢,第二个人会收到错误吗?还是应该写第一条记录并用第二条再次更新?

对此的答案将完全取决于您在应用程序中尝试执行的具体操作。

于 2015-04-14T08:36:23.710 回答
0

把check和create的逻辑移到procedure级别,然后用事务隔离处理:

IF NOT EXISTS (SELECT 'non-empty' FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.TABLE_NAME') AND type in (N'U'))
    CREATE TABLE dbo.TABLE_NAME

但是您仍然必须根据以下Number属性包装您的方法并处理异常SqlException

using (SqlConnection connection = new SqlConnection(connectionString))
{
    SqlCommand command = new SqlCommand(queryString, connection);
    try
    {
        command.Connection.Open();
        command.ExecuteNonQuery();
    }
    catch (SqlException ex)
    {
        for (int i = 0; i < ex.Errors.Count; i++)
        {
            errorMessages.Append("Index #" + i + "\n" +
                "Message: " + ex.Errors[i].Message + "\n" +
                "LineNumber: " + ex.Errors[i].LineNumber + "\n" +
                "Source: " + ex.Errors[i].Source + "\n" +
                "Procedure: " + ex.Errors[i].Procedure + "\n");
        }
        Console.WriteLine(errorMessages.ToString());
    }
}

系统错误消息
数据库引擎错误的原因和解决方法

于 2015-04-14T08:36:27.300 回答
0

您应该将测试的存在和插入包装在事务中。这样,第二个检查存在的调用将在第一个调用完成时阻塞。

于 2015-04-14T08:36:36.100 回答