【问题标题】:The transaction associated with the current connection has completed but has not been disposed与当前连接关联的事务已完成但尚未处置
【发布时间】:2017-08-10 18:55:04
【问题描述】:

我正在关注Fastest Way of Inserting in Entity Framework的代码

我在运行此代码时收到此错误消息,但我不知道我做错了什么,因为我完全从页面上复制了它。关于我做错了什么有什么想法吗?

错误信息:与当前连接关联的事务已完成但尚未处理。必须先释放事务,然后才能使用连接执行 SQL 语句。

代码似乎运行了一段时间,但它几乎同时在我在下面标记的行处停止。我不确定发生了什么。

堆栈跟踪:

在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update() 在 System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.b__2(UpdateTranslator ut) 在 System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update[T](T noChangesResult, Func`2 updateFunction) 在 System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update() 在 System.Data.Entity.Core.Objects.ObjectContext.b__35() 在 System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) 在 System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions 选项,IDbExecutionStrategy executionStrategy,布尔 startLocalTransaction) 在 System.Data.Entity.Core.Objects.ObjectContext.c__DisplayClass2a.b__27() 在 System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 操作) 在 System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions 选项,布尔型 executeInExistingTransaction) 在 System.Data.Entity.Core.Objects.ObjectContext.SaveChanges(SaveOptions 选项) 在 System.Data.Entity.Internal.InternalContext.SaveChanges()

public static async Task startInitialMarketSymbolsDownload(string market)
        {
            try
            {
                List<string> symbolList = new List<string>();
                symbolList = getStockSymbols(market);

                var historicalGroups = symbolList.Select((x, i) => new { x, i })
                          .GroupBy(x => x.i / 50)
                          .Select(g => g.Select(x => x.x).ToArray());

                List<DailyAmexData>[] amexListArray = await Task.WhenAll(historicalGroups.Select(g => Task.Run(() => getLocalHistoricalStockData(g, market))));


                using (TransactionScope scope = new TransactionScope())
                {
                    ooplesfinanceEntities context = null;
                    List<DailyAmexData> amexList = null;

                    try
                    {
                        amexList = new List<DailyAmexData>();

                        foreach (List<DailyAmexData> singleList in amexListArray)
                        {
                            amexList.AddRange(singleList);
                        }

                        context = new financeEntities();
                        context.Configuration.AutoDetectChangesEnabled = false;

                        int count = 0;
                        foreach (var amexData in amexList)
                        {
                            ++count;
                            context = AddToContext(context, amexData, count, 100, true);
                        }

                        context.SaveChanges();
                        Console.WriteLine("Everything is finished!");
                    }
                    finally
                    {
                        if (context != null)
                            context.Dispose();
                    }

                    scope.Complete();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.InnerException.Message);
            }
        }

        private static financeEntities AddToContext(financeEntities context, DailyAmexData entity, int count, int commitCount, bool recreateContext)
        {
            context.Set<DailyAmexData>().Add(entity);

            if (count % commitCount == 0)
            {
                context.SaveChanges(); **// seems to happen at this line**
                Console.WriteLine("100 items saved");
                if (recreateContext)
                {
                    context.Dispose();
                    context = new financeEntities();
                    context.Configuration.AutoDetectChangesEnabled = false;
                }
            }

            return context;
        }

【问题讨论】:

  • 请发布完整的异常堆栈。
  • 您引用的答案可以追溯到 6 年前。我确信从那以后发生了很多变化。你到底想做什么?您设置代码的方式是将交易包装在交易中。
  • @Juan 我有超过一百万行要插入数据库,所以我试图找到一种快速的方法来完成它。我还发布了完整的异常堆栈
  • 您现在已经意识到,EF 并不是专门为批量操作而构建的。您是否关心数据是否以块的形式提交?或者您是否需要同时提交数百万条记录?
  • @Juan 我不在乎它是否分块提交,只要它快速完成即可

标签: c# sql multithreading entity-framework linq


【解决方案1】:

如果您需要插入一百万行,那么您应该使用批量插入。我写了一个通用的批量插入类,并在这里发布了代码。

Bulk Insert of Generic List C# into SQL Server

希望对你有帮助。

胡安

【讨论】:

  • 你使用了那个代码吗? C# 中的通用 Bulk Insert 帮助器有用还是仅是大容量插入概念?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-09
  • 1970-01-01
  • 1970-01-01
  • 2014-10-13
  • 1970-01-01
  • 1970-01-01
  • 2017-02-05
相关资源
最近更新 更多