Istnieje już otwarty DataReader powiązany z tym poleceniem, który musi być najpierw zamknięty

Mam takie zapytanie i dostaję błąd w tej funkcji:

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

Błąd to:

Istnieje już otwarty czytnik danych powiązany z tym poleceniem, który musi być najpierw zamknięty.

Update:

Stack trace dodany:

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
Author: abatishchev, 2011-05-19

16 answers

Może się to zdarzyć, jeśli wykonasz zapytanie podczas iteracji wyników z innego zapytania. Z twojego przykładu nie jest jasne, gdzie to się dzieje, ponieważ przykład nie jest kompletny.

Jedną z rzeczy, która może to spowodować, jest leniwe Ładowanie wyzwalane podczas iteracji wyników jakiegoś zapytania.

Można to łatwo rozwiązać, zezwalając MARS w łańcuchu połączeń. Dodaj MultipleActiveResultSets=true do dostawcy części łańcucha połączeń (gdzie źródło danych, Katalog początkowy, itp. są określone).

 1057
Author: Ladislav Mrnka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-19 00:36:42

Możesz użyć metody ToList() przed wyrażeniem 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;
    }
 176
Author: kazem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-18 13:21:57

Oto działający łańcuch połączeń dla kogoś, kto potrzebuje referencji.

  <connectionStrings>
    <add name="IdentityConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\IdentityDb.mdf;Integrated Security=True;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient" />
  </connectionStrings>
 15
Author: Yang Zhang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-17 04:15:44

W moim przypadku użycie Include() rozwiązało ten błąd i w zależności od sytuacji może być o wiele bardziej wydajne niż wysyłanie wielu zapytań, gdy można je odpytywać jednocześnie za pomocą join.

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);
            }
        }
    }
}
 13
Author: Despertar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-15 07:05:08

Użyj składni .ToList(), Aby przekonwertować obiekt odczytany z db na listę, aby uniknąć ponownego odczytu.Mam nadzieję, że to zadziała. Dzięki.

 13
Author: Icemark Muturi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-18 08:23:04

Nie wiem, czy to duplikat, czy nie. Jeśli tak, to przepraszam. Chcę tylko poinformować potrzebujących, jak rozwiązałem mój problem za pomocą ToList().

W moim przypadku mam ten sam wyjątek dla poniższego zapytania.

int id = adjustmentContext.InformationRequestOrderLinks.Where(item => item.OrderNumber == irOrderLinkVO.OrderNumber && item.InformationRequestId == irOrderLinkVO.InformationRequestId).Max(item => item.Id);

Rozwiązałem jak poniżej

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
}
 6
Author: Ziggler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-25 18:55:37

Wygląda na to, że wywołujesz DateLastUpdated z aktywnego zapytania przy użyciu tego samego kontekstu EF, a DateLastUpdate wydaje polecenie do samego magazynu danych. Entity Framework obsługuje tylko jedno aktywne polecenie dla każdego kontekstu na raz.

Możesz przekształcić powyższe dwa zapytania w jedno w następujący sposób:

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

Zauważyłem również, że wywołujesz funkcje takie jak FormattedAccountNumber i FormattedRecordNumber w zapytaniach. Chyba, że są to przechowywane procs lub funkcje, które masz zaimportowane z bazy danych do modelu danych podmiotu i zmapowane poprawnie, będą również wyrzucać excepts, ponieważ EF nie będzie wiedział, jak przetłumaczyć te funkcje na instrukcje, które może wysłać do magazynu danych.

Zauważ również, że wywołanie liczby AsEnumerable nie wymusza wykonania zapytania. Dopóki wykonanie zapytania nie zostanie odroczone do momentu wyliczenia. Możesz wymusić wyliczenie z ToList lub ToArray, jeśli chcesz.

 4
Author: James Alexander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-19 18:22:51

Oprócz Ladislav Mrnka ' S Odpowiedź:

Jeśli publikujesz i nadpisujesz kontener na karcie Settings, możesz ustawić MultipleActiveResultSet na True. Możesz znaleźć tę opcję, klikając zaawansowane... i będzie Pod grupą zaawansowaną .

 2
Author: Alexander Troshchenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-17 16:45:38

Miałem ten sam błąd, gdy próbowałem zaktualizować niektóre rekordy w pętli odczytu. Wypróbowałem najczęściej głosowaną odpowiedź MultipleActiveResultSets=true i znalazłem, że to tylko obejście, aby uzyskać następny błąd

Nowa transakcja nie jest dozwolona, ponieważ działają inne wątki w sesji

Najlepszym podejściem, które sprawdzi się przy dużych wynikach jest użycie fragmentów i otwarcie osobnego kontekstu dla każdego fragmentu, zgodnie z opisem w  SqlException from Entity Framework-nowa transakcja jest niedozwolone, ponieważ w sesji działają inne wątki

 1
Author: Michael Freidgeim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:01

Rozwiązałem ten problem zmieniając wait _accountSessionDataModel.SaveChangesAsync(); na / Align = "center" bgcolor = "# e0ffe0 " / cesarz chin / / align = center / SaveChanges(); w mojej klasie.

 public async Task<Session> CreateSession()
    {
        var session = new Session();

        _accountSessionDataModel.Sessions.Add(session);
        await _accountSessionDataModel.SaveChangesAsync();
     }

Zmienił na:

 public Session CreateSession()
    {
        var session = new Session();

        _accountSessionDataModel.Sessions.Add(session);
        _accountSessionDataModel.SaveChanges();
     }

Problem polegał na tym, że zaktualizowałem sesje w interfejsie po utworzeniu sesji (w kodzie), ale ponieważ SaveChangesAsync dzieje się asynchronicznie, pobieranie sesji spowodowało ten błąd, ponieważ najwyraźniej operacja SaveChangesAsync nie była jeszcze gotowa.

 1
Author: woutercx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-21 14:01:06

Dla tych, którzy znajdują to przez Google;
Otrzymywałem ten błąd, ponieważ, zgodnie z sugestią błędu, nie udało mi się zamknąć SqlDataReader przed utworzeniem innego na tym samym poleceniu SQL, błędnie zakładając, że będą to śmieci zbierane podczas opuszczania metody, w której został utworzony.

Problem rozwiązałem wywołując sqlDataReader.Close(); przed utworzeniem drugiego czytnika.

 1
Author: timelmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-21 18:01:22

W moim przypadku otworzyłem zapytanie z kontekstu danych, jak

    Dim stores = DataContext.Stores _
        .Where(Function(d) filter.Contains(d.code)) _

... a potem zapytałem o to samo...

    Dim stores = DataContext.Stores _
        .Where(Function(d) filter.Contains(d.code)).ToList

Dodanie .ToList do pierwszego rozwiązało mój problem. Myślę, że to ma sens, aby zawinąć to w nieruchomości jak:

Public ReadOnly Property Stores As List(Of Store)
    Get
        If _stores Is Nothing Then
            _stores = DataContext.Stores _
                .Where(Function(d) Filters.Contains(d.code)).ToList
        End If
        Return _stores
    End Get
End Property

Gdzie _stores jest zmienną prywatną, a Filters jest również właściwością readonly, która odczytuje z AppSettings.

 1
Author: Adam Cox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-15 14:41:10

Używam web service w moim narzędziu, gdzie te usługi pobierają procedurę składowaną. podczas gdy większa liczba narzędzi klienckich pobiera usługę internetową, pojawia się ten problem. Naprawiłem, określając zsynchronizowany atrybut dla tych funkcji pobiera procedurę składowaną. teraz działa dobrze, błąd nigdy nie pojawił się w moim narzędziu.

 [MethodImpl(MethodImplOptions.Synchronized)]
 public static List<t> MyDBFunction(string parameter1)
  {
  }

Ten atrybut pozwala na przetwarzanie jednego żądania na raz. więc to rozwiązuje problem.

 0
Author: Pranesh Janarthanan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-28 04:10:36

Dla mnie to był mój własny błąd. Próbowałem uruchomić INSERT używając SqlCommand.executeReader(), Kiedy powinienem używać SqlCommand.ExecuteNonQuery(). Został otwarty i nigdy nie zamknięty, powodując błąd. Uważaj na to przeoczenie.

 0
Author: Andrew Taylor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-26 14:56:42

Jest to wyciągnięte ze scenariusza realnego świata:

  • kod działa dobrze w środowisku Stage z MultipleActiveResultSets jest ustawiony w łańcuchu połączeń
  • kod opublikowany w środowisku produkcyjnym bez MultipleActiveResultSets=true
  • tak wiele stron / wywołań działa, gdy jedna zawodzi
  • [[3]}patrząc bliżej na wezwanie, jest niepotrzebny telefon wykonane do db i wymaga usunięcia
  • Set MultipleActiveResultSets = true w produkcji i publikacji kodu wszystko działa dobrze i sprawnie

Podsumowując, nie zapominając o MultipleActiveResultSets, kod mógł działać przez długi czas, zanim odkrył redundantne wywołanie db, które może być bardzo kosztowne, i sugeruję Nie w pełni polegać na ustawieniu atrybutu MultipleActiveResultSets, ale także dowiedz się, dlaczego kod jest potrzebny tam, gdzie się nie powiódł.

 0
Author: usefulBee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-06 17:54:02

Najprawdopodobniej ten problem występuje z powodu "leniwego ładowania" funkcji Entity Framework. Zwykle, o ile nie jest to wyraźnie wymagane podczas wstępnego pobierania, wszystkie połączone DANE (wszystko, co jest przechowywane w innych tabelach bazy danych) są pobierane tylko wtedy, gdy są wymagane. W wielu przypadkach jest to dobra rzecz, ponieważ zapobiega pobieraniu niepotrzebnych danych, a tym samym poprawia wydajność zapytań (brak połączeń) i oszczędza przepustowość.

W sytuacji opisanej w pytaniu wykonuje się pobieranie wstępne, a podczas żądany jest brak fazy" select", wysyłane są dodatkowe zapytania, a następnie EF narzeka na "open DataReader".

Obejście zaproponowane w zaakceptowanej odpowiedzi pozwoli na wykonanie tych zapytań i rzeczywiście całe żądanie zakończy się sukcesem.

Jednakże, jeśli przeanalizujesz żądania wysłane do bazy danych, zauważysz wiele żądań - dodatkowe żądanie dla każdego brakującego (leniwie załadowanego) danych. To może być zabójcze.

A better podejście polega na tym, aby powiedzieć EF, aby wstępnie załadował wszystkie potrzebne leniwe załadowane dane podczas początkowego zapytania. Można to zrobić za pomocą instrukcji "Include":

using System.Data.Entity;

query = query.Include(a => a.LazyLoadedProperty);

W ten sposób zostaną wykonane wszystkie potrzebne połączenia i wszystkie potrzebne dane zostaną zwrócone jako jedno zapytanie. Problem opisany w pytaniu zostanie rozwiązany.

 0
Author: Illidan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-31 10:45:43