ForEach 中的 db.SaveChanges 导致“不允许新事务,因为会话中还有其他线程正在运行”

问题描述 投票:0回答:4

我有一个大约有21000行的Excel文件。我将其导入到数据库中的临时表中。

现在我想对我的数据进行一些转换,然后将它们放入我的主表中。

当我在

SaveChanges()
中执行
foreach
时,出现以下错误:

Microsoft.Data.SqlClient.SqlException: 'New transaction is not allowed because there are other threads running in the session

当我在

foreach
之后使用它时,没有发生错误,并且该表只插入了 4 条记录,而不是我预期的所有 21000 条记录。

    public ActionResult FeedTempdataToMainDB()
    {
        var L = new Leave();
        //  var leaves = new List<Leave>();
        foreach (var item in db.TempLeaves)
        {
            L.Pcode = Int32.Parse(item.Cod);
            var z = int.Parse(item.LT) - 1;
            if (z == 0) L.LT = Leave.LeaveType.Saati;
            else L.LT = Leave.LeaveType.Roozane;
            var o = int.Parse(item.DLT) - 1;
            if (o == 0) L.DLT = Leave.DLType.Estehghaghi;
            if (o == 1) L.DLT = Leave.DLType.Estelaji;
            else L.DLT = Leave.DLType.Bihoghoogh;
            L.LeaveDayStart = item.LeaveDayStart.Old6digToMiladi();
            L.LeaveDayEnd = item.LeaveDayEnd.Old6digToMiladi();
            L.LeaveTimeStart = StringToHour(item.LeaveTimeStart);
            L.LeaveTimeEnd = StringToHour(item.LeaveTimeEnd);
            L.LeaveDays = int.Parse(item.LeaveDays);
            L.LeaveMinuts = SaatiLengh(item.LeaveMinuts);
            L.RegDate = StringToHour(item.RegTime);
            L.RegDate = item.RegDate.Old6digToMiladi().Date;
            L.RegistrarCode = Int32.Parse(item.RegistrarCode);
            L.HijriYear = L.LeaveDayStart.GetHijriYear();
            var t = IsOk(item.RegTime);
            if (L.DLT == 0 && t == false || L.LT == 0)
            {
                L.Calculate = false;

                L.IsActive = false;
            }
            else { L.Calculate = true; L.IsActive = true; }
            db.Leaves.Add(L);
            db.SaveChangesAsync();
        }
        //db.SaveChanges();
        return RedirectToAction("index");
     }
c# asp.net asp.net-mvc entity-framework model-view-controller
4个回答
1
投票

您的代码中有错误。您在循环外部声明并创建了 L。每次添加相同的 L ,只是使用不同的数据。最后,您将获得在最后一个 foreach 循环 cicle 期间创建的相同数据的列表。

试试这个:

        foreach (var item in db.TempLeaves)
        {
          var z = int.Parse(item.LT) - 1; 
           var L = new Leave{
            Pcode = Int32.Parse(item.Cod),
            LeaveTimeStart = StringToHour(item.LeaveTimeStart),
            LeaveTimeEnd = StringToHour(item.LeaveTimeEnd),
            LeaveDays = int.Parse(item.LeaveDays),
            LT = z == 0? Leave.LeaveType.Saati : Leave.LeaveType.Roozane
            };     
           db.Leaves.Add(L);
        }

或者这个

  var leaves= new List<Leave>();
 foreach (var item in db.TempLeaves)
        {
            var z = int.Parse(item.LT) - 1; 
           var L = new Leave{
            Pcode = Int32.Parse(item.Cod),
            LeaveTimeStart = StringToHour(item.LeaveTimeStart),
            LeaveTimeEnd = StringToHour(item.LeaveTimeEnd),
            LeaveDays = int.Parse(item.LeaveDays),
            LT = z == 0? Leave.LeaveType.Saati : Leave.LeaveType.Roozane
             };     
           leaves.Add(L);
        }
   if(leaves.Count>0)
{
   db.Leaves.AddRange(leaves);
  db.SaveChanges();
}

如果你想使用异步保存,你必须首先进行异步操作。


1
投票

每次 foreach 执行 savechnages 时,都会有一个您无法控制的线程。由于实体框架正在管理 savechanges 功能。您必须在 foreach 之后执行 savechnages 或使用异步函数。


1
投票

这是异步的示例:

private static async Task<Student> GetStudent()

{ 学生学生=空;

using (var context = new SchoolDBEntities())
{
    Console.WriteLine("Start GetStudent...");
          
    student = await (context.Students.Where(s => s.StudentID == 1).FirstOrDefaultAsync<Student>());
        
    Console.WriteLine("Finished GetStudent...");
}

return student;

}


0
投票

*这段代码终于起作用了:

public ActionResult FeedTempdataToMainDB()
{
    var leaves = new List<Leave>();
    foreach (var item in db.TempLeaves)
    {
        var L = new Leave();
        L.Pcode = Int32.Parse(item.Cod);
        var z = int.Parse(item.LT) - 1;
        if (z == 0) L.LT = Leave.LeaveType.Saati;
        else L.LT = Leave.LeaveType.Roozane;
        var o = int.Parse(item.DLT);
        if (o == 0) L.DLT = Leave.DLType.Estehghaghi;
        if (o == 1) L.DLT = Leave.DLType.Estelaji;
        else L.DLT = Leave.DLType.Bihoghoogh;
        L.LeaveDayStart = item.LeaveDayStart.Old6digToMiladi();
        L.LeaveDayEnd = item.LeaveDayEnd.Old6digToMiladi();
        L.LeaveTimeStart = StringToHour(item.LeaveTimeStart);
        L.LeaveTimeEnd = StringToHour(item.LeaveTimeEnd);
        L.LeaveDays = int.Parse(item.LeaveDays);
        L.LeaveMinuts = SaatiLengh(item.LeaveMinuts);
        L.RegDate = StringToHour(item.RegTime);
        L.RegDate = item.RegDate.Old6digToMiladi().Date;
        L.RegistrarCode = Int32.Parse(item.RegistrarCode);
        L.HijriYear = L.LeaveDayStart.GetHijriYear();
        var t = IsOk(item.RegTime);
        if (L.DLT == 0 && t == false || L.LT == 0 && t == false)
        {
            L.Calculate = false;

            L.IsActive = false;
        }
        else { L.Calculate = true; L.IsActive = true; }
        leaves.Add(L);
    }

    if (leaves.Count > 0)
    {
        db.Leaves.AddRange(leaves);
        db.SaveChanges();
    }

    return RedirectToAction("index");
}
© www.soinside.com 2019 - 2024. All rights reserved.