c#同时调用sql db

c#同时调用sql db,c#,simultaneous-calls,C#,Simultaneous Calls,在我的C#项目中,我有一个方法询问数据库中是否存在对象,如果不存在,则创建它。现在,如果两个用户同时问同一个问题,他们都会得到null,因此流将保存到db,这对于两个重复的用户来说是不可能的,因此将引发sql异常。 请问我如何处理这个问题 这是我的密码: var date = DateTime.UtcNow.Date; var todayCelebPageView = _celebPageViewsRepo.GetAll().SingleOrDefault(d => d.iCelebI

在我的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();
}

这个问题没有简单的答案,这是一个常见的问题,有很多解决方案

有些选择可能是:

  • 捕获正确的SQL异常,并相应地重试
  • 为这些数据库调用创建一个队列,并一次处理一个
  • 锁定的一些实现,或者在数据库中(可能通过将其包装在事务中)或者在代码本身中
  • 另一个需要考虑的是,当两次尝试同时创建一个记录时,从业务的角度来看应该发生什么。

    创造纪录的人应该最后获胜吗?第一个人赢了,第二个人收到错误吗?或者您应该写入第一条记录,然后用第二条记录再次更新它


    这个问题的答案将完全取决于您在应用程序中尝试执行的操作的具体情况。

    将检查和创建的逻辑移动到过程级别,然后将使用事务隔离进行处理:

    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
    
    但您仍然必须根据以下属性包装方法并处理异常:

    使用(SqlConnection连接=新的SqlConnection(connectionString))
    {
    SqlCommand=newsqlcommand(queryString,connection);
    尝试
    {
    command.Connection.Open();
    command.ExecuteNonQuery();
    }
    catch(SqlException-ex)
    {
    对于(int i=0;i


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

    在这种情况下,我应该使用lock对象吗?
    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());
        }
    }