Bu komutla ilişkilendirilmiş, önce kapatılması gereken açık bir DataReader zaten var


640

Bu sorguyu var ve bu işlevde hata alıyorum:

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

Hata:

Bu komutla ilişkilendirilmiş, ilk önce kapatılması gereken açık bir DataReader zaten var.

Güncelleme:

yığın izlemesi eklendi:

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

Yanıtlar:


1287

Bu, başka bir sorgudan gelen sonuçlar üzerinden yineleme yaparken bir sorgu yürütürseniz oluşabilir. Örneğinizde bunun nerede olduğu açık değildir çünkü örnek tam değildir.

Buna neden olabilecek bir şey, bazı sorguların sonuçları üzerinde tekrarlanırken tetiklenen tembel yükleme.

Bu, bağlantı dizenizde MARS'a izin verilerek kolayca çözülebilir. Ekle MultipleActiveResultSets=true(vb Veri Kaynağı, Başlangıç Kataloğu, belirtilen) bağlantı dizesinin sağlayıcı kısmına.


34
Bu benim için çalıştı. Birden Çok Etkin Sonuç Kümesini Etkinleştirme (MARS) hakkında daha fazla bilgi edinmek için bkz. Msdn.microsoft.com/en-us/library/h32h3abf(v=vs.100).aspx .
MARS'nin

3
Performansı göz önünde bulundurarak, System.Data.Entity'yi ekleyerek ve ardından bu ikincil verilerin orijinal sorguya yüklendiğinden emin olmak için Include deyimlerini kullanarak bunu çözebilirsiniz. MARS'ı etkinleştirirseniz, bu tekrarlanan veri yüklerini kontrol etmek için kapatmak, gidiş-dönüşleri azaltarak veri işleme çağrılarınızı hızlandırmanıza yardımcı olabilir.
Chris Moschini

70
MARS'nin etkinleştirilmesi yalnızca çok küçük bir sorun / kullanım durumu alt kümesi için yapılmalıdır. Çoğu durumda, söz konusu hataya çağıran uygulamadaki KÖTÜ KOD neden olur. Daha fazla detay için: devproconnections.com/development/…
Michael K. Campbell

132
.Include () öğesinden sonra .ToList () eklenmesi. () Sorunu muhtemelen nerede çözecektir.
Serj Sagan

2
Genel bir SQL bağlantısı yapmak bir sorgu için geniş bir değişiklik saçma. Doğru cevap aşağıdaki ToList olmalıdır. Yerelleştirilmiş bir sorun için yerel bir düzeltme (yani yalnızca sorguyu değiştirin)!
bytedev

218

ToList()Yöntemi returnifadeden önce kullanabilirsiniz .

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

9
Bu hatayı şimdi defalarca yaşadım ... ve her unutuşumda! Sorunun cevabı her zaman ToList () kullanmaktır.
Cheesus Tost

1
Bunun bir dezavantajı var mı? 100 bin satırınız varsa bunun iyi olabileceğinden şüpheliyim.
Martin Dawson

2
@MartinMazzaDawson, Gerçekten bir kerede sorgu yürütme 100K kayıt gerekir ?? Ben sayfalandırma kullanmak bu durum için iyi bir fikir olduğunu düşünüyorum
kazem

eski bir konuyu yükseltmek için üzgünüm ama bir RepositoryPattern geliştirirken aynı hataya geldi ve ben deponun her yöntemine ".ToList () veya Single () veya Count ()" ekleyerek çözüldü. Başlangıçta sadece ".AsEnumerable ()" dönüyordu. Şimdi sorum şu: "ToList ()" i döndüren depo veya son tüketiciye talep edilecek bir şey mi (yani: hizmet / iş mantığı)
alessalessio

Benim için çalışıyor. .ToList eklenmesi JetEntityFrameworkProvider'da Ondalık destek sorunu sorununu çözer. Total = storeDb.OF_Carts.Where(x => x.CartId == ShoppingCartId).ToList().Sum(t => t.Quantity * t.Item.UnitPrice);
hubert17

39

.ToList()tekrar okunmasını önlemek için sözdizimini kullanarak db'den okunan nesneyi listeye dönüştürün. Teşekkürler.


22

İşte referans ihtiyacı olan biri için çalışan bir bağlantı dizesi.

  <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
MARS'yi etkinleştirmek, bir çözüm DEĞİL, bir çözümdür.
SandRock

5
MARS Belgeleri sayfasından: "MARS işlemleri iş parçacığı için güvenli değildir." Bu, eğer Bağlam'a erişen birden fazla iş parçacığından kaynaklanıyorsa, MARS (muhtemelen) çözüm değildir.
Marsop

20

Benim durumumda, Include()bu hatayı kullanarak ve duruma bağlı olarak çok daha verimli olabilir, daha sonra birleştirme ile aynı anda sorgulanabildiği zaman birden fazla sorgu yayınlayabilir.

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

Uygulamanız aksi takdirde MARS gerektirmiyorsa, bu en iyi çözümdür.
Fred Wilson

7

Bunun yinelenen cevap olup olmadığını bilmiyorum. Eğer öyleyse özür dilerim. Sadece ihtiyaç sahiplerinin ToList () kullanarak sorunumu nasıl çözdüğümü bilmesini istiyorum.

Benim durumumda aşağıdaki sorgu için aynı istisna var.

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

Aşağıdaki gibi çözdüm

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
}

5

Aynı EF bağlamını kullanarak etkin bir sorgudan DateLastUpdated'i çağırdığınız anlaşılıyor ve DateLastUpdate veri deposunun kendisine bir komut veriyor. Entity Framework her seferinde bağlam başına yalnızca bir etkin komutu destekler.

Yukarıdaki iki sorgunuzu aşağıdaki gibi yeniden düzenleyebilirsiniz:

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

Ayrıca, sorgularda FormattedAccountNumber ve FormattedRecordNumber gibi işlevleri çağırdığınızı fark ettim. Bunlar, veritabanınızdan varlık veri modeline içe aktardığınız proclar veya işlevler olmadıkça ve doğru eşlendikçe, EF de bu işlevleri veri deposuna gönderebileceği ifadelere nasıl çevireceğini bilemeyeceğinden istisnalar atar.

Ayrıca, AsEnumerable çağrıldığında sorguyu yürütmeye zorlamaz. Sorgu yürütme numaralandırılıncaya kadar ertelenene kadar. İsterseniz ToList veya ToArray ile numaralandırmayı zorlayabilirsiniz.


İsterseniz, DateLastUpdated'i doğrudan Hesap Raporu sorgusu için Select projeksiyonunuza almak ve hatasız olarak istediğiniz efekti elde etmek için gerçekleştirdiğiniz sorguyu yeniden düzenleyebilirsiniz.
James Alexander

Ana sorgu içinde fonksiyon kodu koyduktan sonra aynı hatayı alıyorum
DotnetSparrow 19:11

2

Ladislav Mrnka'nın cevabına ek olarak :

Kapsayıcıyı Ayarlar sekmesinde yayınlıyorsanız ve geçersiz kılıyorsanız , MultipleActiveResultSet öğesini True olarak ayarlayabilirsiniz . Bu seçeneği Gelişmiş ... öğesini tıklatarak bulabilirsiniz ve Gelişmiş grubu altında olacaktır .


2

Bunu Google üzerinden bulanlar için;
Hata tarafından önerildiği gibi, yanlışlıkla oluşturulduğu yöntemi terk ederken toplanan çöp olacağını varsayarak aynı SqlCommand üzerinde başka bir oluşturmadan önce bir SqlDataReader kapatmayı başaramadı çünkü bu hatayı alıyordum.

sqlDataReader.Close();İkinci okuyucu oluşturmadan önce arayarak sorunu çözdüm.


2

Benim durumumda, veri bağlamından bir sorgu açmıştım,

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

... ve sonra aynı şeyi sorguladı ...

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

İlkine eklemek .ToListsorunumu çözdü. Bunun gibi bir özellikte bunu sarmak mantıklı olduğunu düşünüyorum:

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

Burada _stores özel bir değişkendir ve Filtreler de AppSettings öğesinden okunan salt okunur bir özelliktir.


1

Okuma döngüsü içindeki bazı kayıtları güncellemeye çalıştığımda aynı hatayla karşılaştım. En çok oy verilen yanıtı denedim MultipleActiveResultSets=trueve bir sonraki hatayı almak için geçici bir çözüm olduğunu buldum 

Oturumda çalışan başka iş parçacıkları olduğundan yeni işleme izin verilmiyor

Büyük ResultSets için işe yarayacak en iyi yaklaşım, Varlık Çerçevesinden SqlException içinde açıklandığı gibi parçalar kullanmak ve her yığın için ayrı bağlam  açmaktır - Oturumda çalışan başka iş parçacıkları olduğundan yeni işleme izin verilmez


1

_AccountSessionDataModel.SaveChangesAsync () değiştirerek bu sorunu çözdüm; to _accountSessionDataModel.SaveChanges (); Havuz dersimde.

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

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

Bunu şu şekilde değiştirdi:

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

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

Sorun, bir oturum (kodda) oluşturduktan sonra ön uçtaki oturumları güncellememdi, ancak SaveChangesAsync zaman uyumsuz olarak gerçekleştiği için, görünüşte SaveChangesAsync işlemi henüz hazır olmadığı için oturumlar getirildi.


1

Benim için bu benim hatamdı. Bir çalıştırmak için çalışıyordu INSERTkullanarak SqlCommand.executeReader()kullanıyorum gerekirken SqlCommand.ExecuteNonQuery(). Açıldı ve asla kapatılmadı ve hataya neden oldu. Bu gözetime dikkat edin.


Benim açımdan da aynı meseleydi. Takılı satır kimliği alıyorum çünkü SqlCommand.executeReader () gerekli. Yani: SqlDataReader.Close () kullandım; Sql Command.Dispose (); Andrew Taylor
Fuat

1

Bu gerçek bir dünya senaryosundan çıkarılır:

  • Bağlantı dizesinde MultipleActiveResultSets ayarlandığında kod Sahne Alanı ortamında iyi çalışır
  • MultipleActiveResultSets olmadan Üretim ortamına yayınlanan kod = true
  • Tek bir sayfa başarısız olduğunda çok fazla sayfa / çağrı çalışıyor
  • Çağrıya daha yakından bakıldığında , db'ye yapılan gereksiz bir çağrı var ve kaldırılması gerekiyor
  • Üretim'de MultipleActiveResultSets = true değerini ayarlayın ve temizleme kodunu yayınlayın, her şey iyi ve verimli bir şekilde çalışır

Sonuç olarak, MultipleActiveResultSets unutmadan, kod çok maliyetli olabilecek bir gereksiz db çağrısı keşfetmeden önce uzun bir süre çalışmış olabilir ve ben tamamen MultipleActiveResultSets özniteliğini ayarlamaya bağlı değil, aynı zamanda kodun neden gerekli olduğunu bulmak öneririz başarısız oldu .


1

Büyük olasılıkla bu sorun, Entity Framework'ün "tembel yükleme" özelliği nedeniyle oluşur. Genellikle, ilk getirme sırasında açıkça gerekli olmadıkça, tüm birleştirilen veriler (diğer veritabanı tablolarında depolanan herhangi bir şey) yalnızca gerektiğinde getirilir. Birçok durumda, gereksiz verilerin alınmasını önlediği ve böylece sorgu performansını artırdığı (birleştirme olmadan) ve bant genişliğinden tasarruf sağladığı için bu iyi bir şeydir.

Soruda açıklanan durumda, ilk getirme yapılır ve "select" aşamasında eksik tembel yükleme verileri istenir, ek sorgular yayınlanır ve EF "açık DataReader" dan şikayet eder.

Kabul edilen cevapta önerilen geçici çözüm, bu sorguların yürütülmesine izin verecektir ve gerçekten de tüm istek başarılı olacaktır.

Ancak, veritabanına gönderilen istekleri inceleyecek olursanız, birden çok istek görürsünüz - her eksik (tembel yüklenen) veri için ek istek. Bu bir performans katili olabilir.

Daha iyi bir yaklaşım, EF'e ilk sorgu sırasında gerekli tüm tembel yüklü verileri önceden yüklemesini söylemektir. Bu "Include" ifadesi kullanılarak yapılabilir:

using System.Data.Entity;

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

Bu şekilde, gerekli tüm birleştirmeler yapılacak ve tüm gerekli veriler tek bir sorgu olarak döndürülecektir. Soruda açıklanan sorun çözülecektir.


Bu geçerli bir yanıttır, çünkü Include komutunu kullanmaktan EntityEntry.Collection (). Load () işlevini kullanmaya başladım ve çözümüm çalışmaktan bozuldu. Ne yazık ki, bir generic için "ThenInclude" başka bir genel olamaz dahil, bu yüzden hala EntityEntry.Collection (). Load () çalışması yapmaya çalışıyorum.
AndrewBenjamin

0

Bu hizmetin saklı yordamı getirdiği aracımda web hizmeti kullanıyorum. daha fazla sayıda istemci aracı web hizmetini alırken, bu sorun ortaya çıkar. Saklı yordam bu işlevler için Eşitlenmiş özniteliği belirterek sabit. şimdi iyi çalışıyor, hata asla aracımda görünmedi.

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

Bu öznitelik bir kerede bir isteğin işlenmesine izin verir. Böylece bu, Sorunu çözer.


0

Bir yan not olarak ... bu, SQL Objelerinden (dahili) veri eşlemeyle ilgili bir sorun olduğunda da olabilir.

Örneğin...

Ben yaratılmış SQL Scalar Functionolduğunu yanlışlıkla bir döndü VARCHAR... sonra ... ve bir bir sütun oluşturmak için kullandı VIEW. VIEWDoğru bir şekilde çizilmiştir DbContextyani ... Linq gayet onu çağırıyordu. Ancak, varlık beklenen DateTime? ve StringVIEW döndürüyordu .

Hangi tuhaf atar ...

"Bu Komutla ilişkili, önce kapatılması gereken açık bir DataReader zaten var"

Anlamak zordu ... ama dönüş parametrelerini düzelttikten sonra ... her şey yolundaydı


0

Benim durumumda, ben ayarlamak zorunda MultipleActiveResultSetsiçin Truebağlantı dizesinde.
Daha sonra aynı veri bağlamında 2 (SQL) komutunu aynı anda çalıştıramama konusunda başka bir hata (gerçek olan) ortaya çıktı! (EF Core, Önce kod)
Benim için çözüm, diğer eşzamansız komut yürütmelerini aramak ve bunları eşzamanlı hale getirmekti. , her iki komut için sadece bir DbContext'e sahip olduğum için, .

Umarım sana yardımcı olur

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.