我目前得到这个错误:

sqlclient . sqlexception:不允许创建新的事务,因为会话中还有其他线程在运行。

运行这段代码时:

public class ProductManager : IProductManager
{
    #region Declare Models
    private RivWorks.Model.Negotiation.RIV_Entities _dbRiv = RivWorks.Model.Stores.RivEntities(AppSettings.RivWorkEntities_connString);
    private RivWorks.Model.NegotiationAutos.RivFeedsEntities _dbFeed = RivWorks.Model.Stores.FeedEntities(AppSettings.FeedAutosEntities_connString);
    #endregion

    public IProduct GetProductById(Guid productId)
    {
        // Do a quick sync of the feeds...
        SyncFeeds();
        ...
        // get a product...
        ...
        return product;
    }

    private void SyncFeeds()
    {
        bool found = false;
        string feedSource = "AUTO";
        switch (feedSource) // companyFeedDetail.FeedSourceTable.ToUpper())
        {
            case "AUTO":
                var clientList = from a in _dbFeed.Client.Include("Auto") select a;
                foreach (RivWorks.Model.NegotiationAutos.Client client in clientList)
                {
                    var companyFeedDetailList = from a in _dbRiv.AutoNegotiationDetails where a.ClientID == client.ClientID select a;
                    foreach (RivWorks.Model.Negotiation.AutoNegotiationDetails companyFeedDetail in companyFeedDetailList)
                    {
                        if (companyFeedDetail.FeedSourceTable.ToUpper() == "AUTO")
                        {
                            var company = (from a in _dbRiv.Company.Include("Product") where a.CompanyId == companyFeedDetail.CompanyId select a).First();
                            foreach (RivWorks.Model.NegotiationAutos.Auto sourceProduct in client.Auto)
                            {
                                foreach (RivWorks.Model.Negotiation.Product targetProduct in company.Product)
                                {
                                    if (targetProduct.alternateProductID == sourceProduct.AutoID)
                                    {
                                        found = true;
                                        break;
                                    }
                                }
                                if (!found)
                                {
                                    var newProduct = new RivWorks.Model.Negotiation.Product();
                                    newProduct.alternateProductID = sourceProduct.AutoID;
                                    newProduct.isFromFeed = true;
                                    newProduct.isDeleted = false;
                                    newProduct.SKU = sourceProduct.StockNumber;
                                    company.Product.Add(newProduct);
                                }
                            }
                            _dbRiv.SaveChanges();  // ### THIS BREAKS ### //
                        }
                    }
                }
                break;
        }
    }
}

模型#1——这个模型位于我们的开发服务器的数据库中。 模型1 http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/bdb2b000-6e60-4af0-a7a1-2bb6b05d8bc1/Model1.png

模型#2 -这个模型位于我们的Prod服务器的数据库中,每天通过自动馈送进行更新。alt文本http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/4260259f-bce6-43d5-9d2a-017bd9a980d4/Model2.png

注意-模型#1中红圈的项目是我用来“映射”到模型#2的字段。请忽略模型2中的红圈:这是我的另一个问题,现在已经回答了。

注意:我仍然需要放入一个isDeleted检查,这样我就可以从DB1中删除它,如果它已经离开了我们客户的库存。

对于这个特定的代码,我所要做的就是将DB1中的公司与DB2中的客户机连接起来,从DB2中获取他们的产品列表,并在DB1中插入(如果还没有)。第一次通过应该是充分拉库存。每次在那里运行之后都不会发生任何事情,除非新的库存在夜间进入馈送。

所以最大的问题是,我如何解决我得到的事务错误?我是否需要每次通过循环删除并重新创建我的上下文(对我来说没有意义)?


当前回答

从EF5迁移到EF6后,我们开始看到这个错误“新事务不允许,因为会话中有其他线程正在运行”。

谷歌将我们带到这里,但我们没有在循环中调用SaveChanges()。在使用ObjectContext执行存储过程时引发错误。从DB读取foreach循环中的ExecuteFunction。

任何对ObjectContext的调用。ExecuteFunction将函数包装在事务中。在已经打开读取器的情况下开始事务会导致错误。

可以通过设置以下选项禁用在事务中包装SP。

_context.Configuration.EnsureTransactionsForFunctionsAndCommands = false;

EnsureTransactionsForFunctionsAndCommands选项允许SP在不创建自己的事务的情况下运行,并且不再引发错误。

DbContextConfiguration。EnsureTransactionsForFunctionsAndCommands财产

其他回答

大部分答案与循环有关。但我的问题不同。当我试图在同一范围内使用多个dbcontext.Savechanges()命令时,我多次得到错误。

在我的案例中使用ef core 3.1

dbcontext.Database.BeginTransaction () 而且 dbcontext.Database.CommitTransaction ();

已经解决了问题。以下是我的全部代码:

 public IActionResult ApplyForCourse()
    {

        var master = _userService.GetMasterFromCurrentUser();

            var trainee = new Trainee
            {
                CourseId = courseId,
                JobStatus = model.JobStatus,
                Gender = model.Gender,
                Name = model.Name,
                Surname = model.Surname,
                Telephone = model.Telephone,
                Email = model.Email,
                BirthDate = model.BirthDate,
                Description = model.Description,
                EducationStatus = EducationStatus.AppliedForEducation,
                TraineeType = TraineeType.SiteFirst

            };


            dbcontext.Trainees.Add(trainee);
            dbcontext.SaveChanges();

         
            dbcontext.Database.BeginTransaction();
            var user = userManager.GetUserAsync(User).Result;
            master.TraineeId = trainee.Id;
            master.DateOfBirth = model.BirthDate;
            master.EducationStatus = trainee.EducationStatus;
            user.Gender = model.Gender;
            user.Email = model.Email;
            dbcontext.Database.CommitTransaction();
            dbcontext.SaveChanges();
 
            return RedirectToAction("Index", "Home");

        }


    }

所以在项目中,我有这个完全相同的问题,问题不是在foreach或。tolist(),它实际上是在我们使用的AutoFac配置。 这造成了一些奇怪的情况,上面的错误被抛出,但也抛出了一堆其他等效的错误。

这是我们的解决方案: 改变:

container.RegisterType<DataContext>().As<DbContext>().InstancePerLifetimeScope();
container.RegisterType<DbFactory>().As<IDbFactory>().SingleInstance();
container.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest();

To:

container.RegisterType<DataContext>().As<DbContext>().As<DbContext>();
container.RegisterType<DbFactory>().As<IDbFactory>().As<IDbFactory>().InstancePerLifetimeScope();
container.RegisterType<UnitOfWork>().As<IUnitOfWork>().As<IUnitOfWork>();//.InstancePerRequest();

供你参考:来自一本书,一些行调整,因为它仍然有效:

调用SaveChanges()方法将启动一个事务,如果在迭代完成之前发生异常,该事务将自动回滚持久化到数据库的所有更改;否则事务将提交。您可能倾向于在每次实体更新或删除之后应用该方法,而不是在迭代完成之后,特别是当您更新或删除大量实体时。

如果在处理完所有数据之前尝试调用SaveChanges(),则会引发“不允许新事务,因为会话中正在运行其他线程”异常。出现异常是因为SQL Server不允许在一个打开了SqlDataReader的连接上启动一个新事务,即使连接字符串启用了多个活动记录集(MARS) (EF的默认连接字符串启用了MARS)。

有时候理解事情为什么会发生会更好;-)

总是使用你的选择作为列表

Eg:

var tempGroupOfFiles = Entities.Submited_Files.Where(r => r.FileStatusID == 10 && r.EventID == EventId).ToList();

然后在保存更改时遍历集合

 foreach (var item in tempGroupOfFiles)
             {
                 var itemToUpdate = item;
                 if (itemToUpdate != null)
                 {
                     itemToUpdate.FileStatusID = 8;
                     itemToUpdate.LastModifiedDate = DateTime.Now;
                 }
                 Entities.SaveChanges();

             }

I was getting this same issue but in a different situation. I had a list of items in a list box. The user can click an item and select delete but I am using a stored proc to delete the item because there is a lot of logic involved in deleting the item. When I call the stored proc the delete works fine but any future call to SaveChanges will cause the error. My solution was to call the stored proc outside of EF and this worked fine. For some reason when I call the stored proc using the EF way of doing things it leaves something open.