Entity Framework中的SqlException-不允许新事务,因为会话中正在运行其他线程

烂漫一生 提交于 2020-01-07 17:58:46

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

我目前收到此错误:

System.Data.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 Server上的数据库中,并且每天通过自动Feed进行更新。 替代文字http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/4260259f-bce6-43d5-9d2a-017bd9a980d4/Model2.png

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

注意:我仍然需要进行isDeleted支票,以便在DB1超出我们客户的库存范围时可以将其从DB1中软删除。

我要做的就是用这个特定的代码将DB1中的一家公司与DB2中的一个客户连接起来,从DB2中获取他们的产品列表,如果还没有,请在DB1中插入它。 第一次应该是充分利用库存。 每次在此运行时,除非夜间通入饲料中的新库存,否则什么都不会发生。

因此,最大的问题-如何解决我遇到的交易错误? 每次循环时都需要删除并重新创建上下文(对我来说没有意义)吗?


#1楼

仅供参考:从一本书和一些经调整的行开始,因为其有效期仍然有效:

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

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

有时最好了解为什么事情会发生;-)


#2楼

多拔头发出来后,我发现foreach循环是罪犯。 需要发生的是调用EF,但将其返回到该目标类型的IList<T>中,然后在IList<T>上循环。

例:

IList<Client> 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;
    // ...
}

#3楼

以下代码对我有用:

private pricecheckEntities _context = new pricecheckEntities();

...

private void resetpcheckedtoFalse()
{
    try
    {
        foreach (var product in _context.products)
        {
            product.pchecked = false;
            _context.products.Attach(product);
            _context.Entry(product).State = EntityState.Modified;
        }
        _context.SaveChanges();
    }
    catch (Exception extofException)
    {
        MessageBox.Show(extofException.ToString());

    }
    productsDataGrid.Items.Refresh();
}

#4楼

因此,在项目中,我遇到了完全相同的问题,问题出在foreach.toList() ,而实际上.toList()我们使用的AutoFac配置中。 这引发了一些奇怪的情况,不仅引发了上述错误,而且引发了一堆其他等效的错误。

这是我们的解决方法:更改了此内容:

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

至:

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

#5楼

就我而言,当我通过EF调用存储过程,然后稍后SaveChanges抛出此异常时,出现了问题。 问题出在调用程序时,没有处理枚举器。 我按照以下方式修复了代码:

public bool IsUserInRole(string username, string roleName, DataContext context)
{          
   var result = context.aspnet_UsersInRoles_IsUserInRoleEF("/", username, roleName);

   //using here solved the issue
   using (var en = result.GetEnumerator()) 
   {
     if (!en.MoveNext())
       throw new Exception("emty result of aspnet_UsersInRoles_IsUserInRoleEF");
     int? resultData = en.Current;

     return resultData == 1;//1 = success, see T-SQL for return codes
   }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!