Ik heb deze query en ik krijg de fout in deze functie:
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();
}
Fout is:
Er is al een open DataReader geassocieerd met deze opdracht die eerst gesloten moet worden.
Update:
stack trace toegevoegd:
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
Dit kan gebeuren als je een query uitvoert terwijl je itereert over de resultaten van een andere query. Het is niet duidelijk uit je voorbeeld waar dit gebeurt omdat het voorbeeld niet volledig is.
Een van de dingen die dit kan veroorzaken is lazy loading dat optreedt bij het itereren over de resultaten van een bepaalde query.
Dit kan eenvoudig worden opgelost door MARS toe te staan in je connection string. Voeg MultipleActiveResultSets=true
toe aan het provider gedeelte van je connectie string (waar Data Source, Initial Catalog, etc. zijn gespecificeerd).
Je kunt de ToList()
methode gebruiken voor het return
statement.
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;
}
Het lijkt erop dat je DateLastUpdated aanroept vanuit een actieve query met dezelfde EF-context en DateLastUpdate geeft een opdracht aan de data store zelf. Entity Framework ondersteunt slechts één actieve opdracht per context tegelijk.
U kunt uw bovenstaande twee query's als volgt in één refactoren:
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);
Het viel me ook op dat je functies als FormattedAccountNumber en FormattedRecordNumber aanroept in de queries. Tenzij dit opgeslagen procs of functies zijn die je vanuit je database in het entiteitsgegevensmodel hebt geïmporteerd en correct in kaart hebt gebracht, zullen deze ook excepts gooien omdat EF niet weet hoe het die functies moet vertalen naar verklaringen die het naar de gegevensopslag kan sturen.
Merk ook op dat het aanroepen van AsEnumerable de query niet dwingt om uit te voeren. De uitvoering van de query wordt uitgesteld tot de opsomming. Je kunt opsomming forceren met ToList of ToArray als je dat wenst.