我有这个查询,我得到了这个函数的错误:

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();
}

错误:

已经有一个打开的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

当前回答

在我的例子中,使用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);
            }
        }
    }
}

其他回答

看起来您正在使用相同的EF上下文从活动查询中调用DateLastUpdate,并且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);

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

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

可以在return语句之前使用ToList()方法。

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;
}

这是从一个真实的场景中提取出来的:

代码在连接字符串中设置MultipleActiveResultSets的Stage环境中工作良好 发布到生产环境的代码没有MultipleActiveResultSets=true 如此多的页面/呼叫工作,而一个是失败的 仔细查看调用,有一个对db的不必要调用,需要删除 在Production中设置MultipleActiveResultSets=true,并发布清理过的代码,一切都能正常有效地工作

总之,不要忘记MultipleActiveResultSets,在发现冗余的db调用之前,代码可能已经运行了很长一段时间,这可能是非常昂贵的,我建议不要完全依赖于设置MultipleActiveResultSets属性,但也要找出为什么代码需要它失败的地方。

在我的例子中,使用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);
            }
        }
    }
}

使用. tolist()语法将从db读取的对象转换为list以避免再次读取。