C# LINQ到实体事务性能问题 公共无效寄存器(十进制groupId、十进制deptId、十进制employeeId) { 使用(EmployeeEntities db=new EmployeeEntities()) { 使用(TransactionScope作用域=新TransactionScope(TransactionScopeOption.Required,新TransactionOptions{IsolationLevel=IsolationLevel.Snapshot})) { var course=db.Courses.Where(s=>s.GroupId==GroupId&&s.DepartmentId==deptId.ToList(); foreach(过程中的var项目) { var filledSeats=db.courserregistrations.Count(c=>c.CourseId==item.CourseId&&c.DepartmentId==deptId&(c.canceleredfl==null | | c.canceleredfl==false)); 如果(item.allocatedSeats s.GroupId==item.GroupId)。选择(s=>s.GroupName.FirstOrDefault()); } 如果(!db.CourseRegistrations.Any(s=>s.EmployeeId==EmployeeId&&s.CourseId==item.CourseId&&s.CancelledFl==false | | s.CancelledFl==null))) { var courseRegister=新courseregistation(); db.CourseRegistrations.Add(courseRegister); courseRegister.CourseId=item.CourseId; courseRegister.EmployeeId=员工ID; courseRegister.CreatedBy=1; courseRegister.CreatedDt=DateTime.Now; courseRegister.RecordVa=1; item.Filled座椅=item.Filled座椅+1; } } db.SaveChanges(); scope.Complete(); } } }

C# LINQ到实体事务性能问题 公共无效寄存器(十进制groupId、十进制deptId、十进制employeeId) { 使用(EmployeeEntities db=new EmployeeEntities()) { 使用(TransactionScope作用域=新TransactionScope(TransactionScopeOption.Required,新TransactionOptions{IsolationLevel=IsolationLevel.Snapshot})) { var course=db.Courses.Where(s=>s.GroupId==GroupId&&s.DepartmentId==deptId.ToList(); foreach(过程中的var项目) { var filledSeats=db.courserregistrations.Count(c=>c.CourseId==item.CourseId&&c.DepartmentId==deptId&(c.canceleredfl==null | | c.canceleredfl==false)); 如果(item.allocatedSeats s.GroupId==item.GroupId)。选择(s=>s.GroupName.FirstOrDefault()); } 如果(!db.CourseRegistrations.Any(s=>s.EmployeeId==EmployeeId&&s.CourseId==item.CourseId&&s.CancelledFl==false | | s.CancelledFl==null))) { var courseRegister=新courseregistation(); db.CourseRegistrations.Add(courseRegister); courseRegister.CourseId=item.CourseId; courseRegister.EmployeeId=员工ID; courseRegister.CreatedBy=1; courseRegister.CreatedDt=DateTime.Now; courseRegister.RecordVa=1; item.Filled座椅=item.Filled座椅+1; } } db.SaveChanges(); scope.Complete(); } } },c#,sql-server,performance,entity-framework,asp.net-web-api,C#,Sql Server,Performance,Entity Framework,Asp.net Web Api,考虑上面的代码。当请求被发送到ASP.NET WebAPI控制器时,它是一个最终被调用的函数 该函数只需在检查座位可用性后将员工注册到课程。大约200名员工将同时注册课程 我正在为每个事务使用快照隔离 我的问题在于性能。它是慢的。有时它会超时 我的问题是为什么?我的代码哪一部分出错了?在所有这些交易中到底发生了什么?什么等待还是什么锁定?在for循环中有多个对数据库的调用,这意味着您将消耗db请求延迟2倍于course.length时间的总成本,而您只需要消耗一次,可能两次。查看是否可以将db.

考虑上面的代码。当请求被发送到
ASP.NET WebAPI
控制器时,它是一个最终被调用的函数

该函数只需在检查座位可用性后将员工注册到课程。大约200名员工将同时注册课程

我正在为每个事务使用
快照隔离

我的问题在于性能。它是慢的。有时它会超时


我的问题是为什么?我的代码哪一部分出错了?在所有这些交易中到底发生了什么?什么等待还是什么锁定?

在for循环中有多个对数据库的调用,这意味着您将消耗db请求延迟2倍于course.length时间的总成本,而您只需要消耗一次,可能两次。查看是否可以将
db.courserregistrations
中的必要数据带到循环之外,这可能是与课程数据关联的同一查询的一部分。然后,您可以在内存中的循环中执行操作,这将快几个数量级。

如果您正在执行许多更新/插入,EF默认情况下会自动跟踪这些更改,如果您正在更新许多记录,这将严重影响性能。为了帮助实现这一点,您可以在批量更新之前关闭该功能,然后在完成更新后再次打开该功能

public void Register(decimal groupId, decimal deptId, decimal employeeId)
{
    using (EmployeeEntities db = new EmployeeEntities())
    {
       using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.Snapshot }))
       {
          var course = db.Courses.Where(s => s.GroupId == groupId && s.DepartmentId == deptId).ToList();                  

          foreach (var item in course)
          {
             var filledSeats = db.CourseRegistrations.Count(c => c.CourseId == item.CourseId && c.DepartmentId == deptId && (c.CancelledFl == null || c.CancelledFl == false));

             if (item.AllotedSeats <= filledSeats)
             {
                throw new Exception("Sorry! Seats are not available for " + db.Groups.Where(s => s.GroupId == item.GroupId).Select(s => s.GroupName).FirstOrDefault());
             }
             if (!db.CourseRegistrations.Any(s => s.EmployeeId == employeeId && s.CourseId == item.CourseId && (s.CancelledFl == false || s.CancelledFl == null)))
             {
                 var courseRegister = new CourseRegistration();
                 db.CourseRegistrations.Add(courseRegister);
                 courseRegister.CourseId = item.CourseId;
                 courseRegister.EmployeeId = employeeId;
                 courseRegister.CreatedBy = 1;
                 courseRegister.CreatedDt = DateTime.Now;
                 courseRegister.RecordVa = 1;

                 item.FilledSeats = item.FilledSeats + 1;
             }
          }
          db.SaveChanges();
          scope.Complete();
       }    
    }  
}
        try
        {
            db.Configuration.AutoDetectChangesEnabled = false;
            //loop through your updates here
        }
        finally
        {
            db.Configuration.AutoDetectChangesEnabled = true;
        }

        db.SaveChanges();