【问题标题】:Why do Entity Framework Core calls in a loop throw InvalidOperationException?为什么 Entity Framework Core 循环调用会抛出 InvalidOperationException?
【发布时间】:2018-03-20 17:20:03
【问题描述】:

为什么以下使用 Entity Framework Core 1.1.1 会导致异常?

// Arrange.
using(var context = new BasicContext())
{
   Author[] authors = new[]
   {
      new Author { Name = "Bob"},
      new Author { Name = "Fred" }
   };
   context.Authors.AddRange(authors);

   Book[] books = new[]
   {
      new Book { Title = "Book 1" },
      new Book { Title = "Book 2" }
   };

   context.SaveChanges();            
}

// Act.
bool exception = false;

using(var context = new BasicContext())
{
   foreach(Author a in context.Authors)
   {
      try
      {
         string title = context.Books.First().Title;
      }
      catch(Exception)
      {
         exception = true;
      }
   }
}

// Assert.
Assert.False(exception);

使用 Postgress (Npgsql) 的实体连接器引发的异常是:

Npgsql.NpgsqlOperationInProgressException : A command is already in progress: SELECT "a"."AuthorId", "a"."Name"
FROM "Authors" AS "a"
Stack Trace:
   at Npgsql.NpgsqlConnector.StartUserAction(ConnectorState newState, NpgsqlCommand command)
   at Npgsql.NpgsqlCommand.<ExecuteDbDataReader>d__92.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
   at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, String execute
Method, IReadOnlyDictionary`2 parameterValues, Boolean closeConnection)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable.Enumerator.BufferlessMoveNext(Boolean buffer)
   at Microsoft.EntityFrameworkCore.Query.QueryMethodProvider.<_ShapedQuery>d__3`1.MoveNext()
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
   at lambda_method(Closure , QueryContext )
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass20_0`1.<CompileQueryCore>b__0(QueryContext qc
)
   at System.Linq.Queryable.First[TSource](IQueryable`1 source)
   at BasicTesting.BasicTests.TestEnumerate() in C:\_Home\Development\Workspaces\DotnetCoreTesting\EntityTesting3\BasicTesting\BasicTests.cs:line 147If 'foreach(Author a in context.Authors)' is replaced with 'foreach(Author a in context.Authors.ToArray())' no exception occurs.

这不是我所期望的。

当到达 foreach 循环时,应该评估 context.Authors。当子序列“Books.First”表达式导致另一个数据库操作时,不应存在正在进行的操作。

【问题讨论】:

标签: database postgresql entity-framework-core


【解决方案1】:

某些提供商不支持拥有多个开放式阅读器。避免这种情况的最好方法是在查询书籍之前完成所有作者的阅读。添加.ToList() 是最简单(但不一定是最好)的方法。

foreach (Author a in context.Authors.ToList())
{
    // ... context.Books ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多