已经有一个与此命令关联的打开DataReader,必须先关闭它

Dot*_*row 592 c# entity-framework entity-framework-4

我有这个查询,我在这个函数中得到错误:

var accounts = from account in context.Accounts
               from guranteer in account.Gurantors
               select new AccountsReport
               {
                   CreditRegistryId = account.CreditRegistryId,
                   AccountNumber = account.AccountNo,
                   DateOpened = account.DateOpened,
               };

 return accounts.AsEnumerable()
                .Select((account, index) => new AccountsReport()
                    {
                        RecordNumber = FormattedRowNumber(account, index + 1),
                        CreditRegistryId = account.CreditRegistryId,
                        DateLastUpdated = DateLastUpdated(account.CreditRegistryId, account.AccountNumber),
                        AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)
                    })
                .OrderBy(c=>c.FormattedRecordNumber)
                .ThenByDescending(c => c.StateChangeDate);


public DateTime DateLastUpdated(long creditorRegistryId, string accountNo)
{
    return (from h in context.AccountHistory
            where h.CreditorRegistryId == creditorRegistryId && h.AccountNo == accountNo
            select h.LastUpdated).Max();
}
Run Code Online (Sandbox Code Playgroud)

错误是:

已经有一个与此命令关联的打开DataReader,必须先关闭它.

更新:

堆栈跟踪添加:

InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.]
   System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) +5008639
   System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command) +23
   System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async) +144
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +87
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32
   System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +141
   System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +12
   System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) +10
   System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) +443

[EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details.]
   System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) +479
   System.Data.Objects.Internal.ObjectQueryExecutionPlan.Execute(ObjectContext context, ObjectParameterCollection parameterValues) +683
   System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) +119
   System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() +38
   System.Linq.Enumerable.Single(IEnumerable`1 source) +114
   System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__3(IEnumerable`1 sequence) +4
   System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle(IEnumerable`1 query, Expression queryRoot) +29
   System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute(Expression expression) +91
   System.Data.Entity.Internal.Linq.DbQueryProvider.Execute(Expression expression) +69
   System.Linq.Queryable.Max(IQueryable`1 source) +216
   CreditRegistry.Repositories.CreditRegistryRepository.DateLastUpdated(Int64 creditorRegistryId, String accountNo) in D:\Freelance Work\SuperExpert\CreditRegistry\CreditRegistry\Repositories\CreditRegistryRepository.cs:1497
   CreditRegistry.Repositories.CreditRegistryRepository.<AccountDetails>b__88(AccountsReport account, Int32 index) in D:\Freelance Work\SuperExpert\CreditRegistry\CreditRegistry\Repositories\CreditRegistryRepository.cs:1250
   System.Linq.<SelectIterator>d__7`2.MoveNext() +198
   System.Linq.Buffer`1..ctor(IEnumerable`1 source) +217
   System.Linq.<GetEnumerator>d__0.MoveNext() +96
Run Code Online (Sandbox Code Playgroud)

Lad*_*nka 1207

如果在迭代另一个查询的结果时执行查询,则会发生这种情况.从您的示例中发现这种情况并不清楚,因为示例未完成.

导致这种情况的一件事是在迭代某些查询的结果时触发了延迟加载.

通过在连接字符串中允许MARS可以轻松解决这个问题.添加MultipleActiveResultSets=true到连接字符串的提供程序部分(指定数据源,初始目录等).

  • 在.Include()之后添加.ToList().Where()可能会解决问题. (124认同)
  • 启用MARS只应针对一小部分问题/用例进行.在大多数情况下,有问题的错误是由调用应用程序中的BAD CODE引起的.更多细节:http://devproconnections.com/development/solving-net-scalability-problem (68认同)
  • 这对我有用.如果您想了解有关启用多个活动结果集(MARS)的更多信息,请参阅http://msdn.microsoft.com/en-us/library/h32h3abf(v=vs.100).aspx.考虑阅读MARS的缺点http://stackoverflow.com/questions/374444/disadvantages-of-mars-multiple-active-result-sets (34认同)
  • 一个黑客的气味...但它确实在一个紧张的工作. (8认同)
  • 对一个查询进行全局 SQL 连接范围的更改是荒谬的。正确答案应该是下面的 ToList 之一。本地化问题的本地修复(即只更改查询)! (3认同)
  • 考虑到性能,您还可以通过包含System.Data.Entity然后使用Include语句来解决此问题,以确保在原始查询中加载此辅助数据.如果启用MARS,将其关闭以检查这些重复数据加载可以通过减少往返来帮助加速数据处理呼叫. (2认同)
  • 由 Gareth 和 Michael 链接的 devproconnections 文章已移至 https://www.itprotoday.com/microsoft-visual-studio/solving-common-net-scalability-problem , archive.org 也有。 (2认同)

kaz*_*zem 208

您可以ToList()return语句之前使用该方法.

var accounts =
from account in context.Accounts
from guranteer in account.Gurantors

 select new AccountsReport
{
    CreditRegistryId = account.CreditRegistryId,
    AccountNumber = account.AccountNo,
    DateOpened = account.DateOpened,
};

 return accounts.AsEnumerable()
               .Select((account, index) => new AccountsReport()
                       {
                           RecordNumber = FormattedRowNumber(account, index + 1),
                           CreditRegistryId = account.CreditRegistryId,
                              DateLastUpdated = DateLastUpdated(account.CreditRegistryId, account.AccountNumber),
                           AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)}).OrderBy(c=>c.FormattedRecordNumber).ThenByDescending(c => c.StateChangeDate).ToList();


 public DateTime DateLastUpdated(long creditorRegistryId, string accountNo)
    {
        var dateReported = (from h in context.AccountHistory
                            where h.CreditorRegistryId == creditorRegistryId && h.AccountNo == accountNo
                            select h.LastUpdated).Max();
        return dateReported;
    }
Run Code Online (Sandbox Code Playgroud)

  • 我现在已经多次犯过这个错误......每次我都忘记了!问题的答案总是使用ToList(). (8认同)
  • 这有什么缺点吗?如果你有 100k 行,我怀疑这会很好。 (5认同)
  • @MartinMazzaDawson,你真的需要一次查询执行100K记录吗?我认为,对于这种情况,使用分页是一个好主意 (2认同)
  • 因为 .ToList() 导致 iEnumerable 实际上从数据库中填充自身,它迭代整个记录集,并且(我相信)关闭它。由于未在连接字符串中设置 MARS,因此一次只能“打开”1 个记录集。意思是,“获取数据并将其存储在我的对象中,然后关闭,以便我的代码的其他部分可以在必要时访问数据库。” 这显然是一个非常高水平的描述,并且可能在语义上有缺陷。但就人类友好的定义而言,它是准确的。 (2认同)

Ice*_*uri 32

使用语法.ToList()将对象读取从db转换为list以避免再次重新读取.希望这对它有用.谢谢.


Yan*_*ang 22

这是一个需要引用的人的工作连接字符串.

  <connectionStrings>
    <add name="IdentityConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\IdentityDb.mdf;Integrated Security=True;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient" />
  </connectionStrings>
Run Code Online (Sandbox Code Playgroud)

  • 启用MARS是一种解决方法,而不是解决问题的方法. (15认同)
  • 从MARS文档页面:"MARS操作不是线程安全的".这意味着,如果问题是由多个线程访问Context而产生的,那么MARS(可能)不是解决方案. (4认同)

Des*_*tar 18

在我的情况下,使用Include()解决此错误并根据情况可以更高效,然后发出多个查询时,可以通过连接一次查询.

IEnumerable<User> users = db.Users.Include("Projects.Tasks.Messages");

foreach (User user in users)
{
    Console.WriteLine(user.Name);
    foreach (Project project in user.Projects)
    {
        Console.WriteLine("\t"+project.Name);
        foreach (Task task in project.Tasks)
        {
            Console.WriteLine("\t\t" + task.Subject);
            foreach (Message message in task.Messages)
            {
                Console.WriteLine("\t\t\t" + message.Text);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Zig*_*ler 7

我不知道这是否是重复的答案.如果是,我很抱歉.我只想让有需要的人知道我是如何使用ToList()解决我的问题的.

在我的情况下,我得到以下查询相同的例外.

int id = adjustmentContext.InformationRequestOrderLinks.Where(item => item.OrderNumber == irOrderLinkVO.OrderNumber && item.InformationRequestId == irOrderLinkVO.InformationRequestId).Max(item => item.Id);
Run Code Online (Sandbox Code Playgroud)

我解决了如下

List<Entities.InformationRequestOrderLink> links = adjustmentContext.InformationRequestOrderLinks
.Where(item => item.OrderNumber == irOrderLinkVO.OrderNumber && item.InformationRequestId == irOrderLinkVO.InformationRequestId).ToList();

int id = 0;

if (links.Any())
{
  id = links.Max(x => x.Id);
 }
if (id == 0)
{
//do something here
}
Run Code Online (Sandbox Code Playgroud)


Jam*_*der 5

看来您正在使用相同的EF上下文从活动查询中调用DateLastUpdated,并且DateLastUpdate向数据存储本身发出命令。实体框架一次仅在每个上下文中支持一个活动命令。

您可以将上述两个查询重构为一个这样的查询:

return accounts.AsEnumerable()
        .Select((account, index) => new AccountsReport()
        {
          RecordNumber = FormattedRowNumber(account, index + 1),
          CreditRegistryId = account.CreditRegistryId,
          DateLastUpdated = (
                                                from h in context.AccountHistory 
                                                where h.CreditorRegistryId == creditorRegistryId 
                              && h.AccountNo == accountNo 
                                                select h.LastUpdated).Max(),
          AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)
        })
        .OrderBy(c=>c.FormattedRecordNumber)
        .ThenByDescending(c => c.StateChangeDate);
Run Code Online (Sandbox Code Playgroud)

我还注意到您在查询中调用了诸如FormattedAccountNumber和FormattedRecordNumber之类的函数。除非这些已存储的proc或函数已从数据库导入到实体数据模型并正确映射,否则它们也会抛出异常,因为EF不知道如何将这些函数转换为可发送到数据存储的语句。

另请注意,调用AsEnumerable不会强制执行查询。直到查询执行推迟到枚举为止。如果需要,可以使用ToList或ToArray强制进行枚举。


归档时间:

查看次数:

405886 次

最近记录:

6 年,6 月 前