Warum ist es möglich, eine DbLinq Abfrage nach dem Aufruf von Dispose () auf der Datacontext aufzuzählen?

StackOverflow https://stackoverflow.com/questions/2851755

  •  27-09-2019
  •  | 
  •  

Frage

Aktualisieren - Die Antwort ist offensichtlich, dass DbLinq nicht Dispose() ordnungsgemäß nicht implementiert. D'oh!


Die unten ist alles irgendwie irreführend - Fazit: DbLinq ist (noch) nicht entspricht LinqToSql, wie ich annehmen, als ich ursprünglich diese Frage gestellt. Verwenden Sie es mit Vorsicht!

Ich verwende das Repository-Muster mit DbLinq. Meine Repositoryobjekte implementieren IDisposable und die Dispose() Methode funktioniert nur, was - Anrufe Dispose() auf der DataContext. Jedes Mal, wenn ich ein Repository verwenden, ich habe es in einem using Block wickeln, wie folgt aus:

public IEnumerable<Person> SelectPersons()
{
    using (var repository = _repositorySource.GetPersonRepository())
    {
        return repository.GetAll(); // returns DataContext.Person as an IQueryable<Person>
    }
}

Diese Methode gibt eine IEnumerable<Person>, also wenn mein Verständnis korrekt ist, keine Abfrage der Datenbank tatsächlich erfolgt bis Enumerable<Person> durchlaufen wird (zB indem sie sie in einer Liste oder ein Array konvertieren oder indem sie in einer foreach-Schleife), wie in diesem Beispiel:

var persons = gateway.SelectPersons();
// Dispose() is fired here
var personViewModels = (
    from b in persons
    select new PersonViewModel
    {
        Id = b.Id,
        Name = b.Name,
        Age = b.Age,
        OrdersCount = b.Order.Count()
    }).ToList(); // executes queries

In diesem Beispiel wird Dispose() genannt unmittelbar nach persons Einstellung, die ein IEnumerable<Person> ist, und das ist das einzige Mal, es aufgerufen wird.

So, drei Fragen:

  1. Wie funktionierts? Wie kann ein angeordnete DataContext noch die Datenbank für die Ergebnisse abfragen nach dem DataContext angeordnet wurde?
  2. Was bedeutet Dispose() eigentlich tun?
  3. Ich habe gehört, dass es nicht notwendig ist (siehe zB diese Frage ) ein DataContext zu entsorgen, aber mein Eindruck war, dass es keine schlechte Idee. Gibt es einen Grund nicht verfügen über eine DbLinq DataContext?
War es hilfreich?

Lösung

  

1 Wie funktionierts? Wie kann ein angeordnete Datacontext noch die Datenbank für die Ergebnisse abfragen, nachdem die Datacontext angeordnet wurde?

Es nicht Arbeit. Es gibt etwas, das Sie zeigt uns nicht. Ich vermute, dass entweder Ihre Repository-Klasse nicht die DataContext richtig / zur richtigen Zeit nicht verfügen, oder dass Sie perfunctorily ToList() am Ende jeder Abfrage schreiben, die vollständig die Abfrage Transformation negiert und verzögerte Ausführung Sie in der Regel erhalten.

Versuchen Sie, den folgenden Code in einer Test-App, I Garantie Sie, dass es eine ObjectDisposedException werfen:

// Bad code; do not use, will throw exception.
IEnumerable<Person> people;
using (var context = new TestDataContext())
{
    people = context.Person;
}
foreach (Person p in people)
{
    Console.WriteLine(p.ID);
}

Dies ist der einfachste mögliche reproduzierbare Fall und es wird immer werfen. Auf der anderen Seite, wenn Sie people = context.Person.ToList() stattdessen dann die Ergebnisse der Abfrage schreiben bereits aufgezählt innen den using Block, die ich wette, ist das, was in Ihrem Fall passiert.

  

2 Was bedeutet Dispose () eigentlich?

Unter anderem legt er einen Flag, das anzeigt, dass der DataContext angeordnet ist, die auf jeder nachfolgenden Abfrage überprüft wird und bewirkt, dass der DataContext eine ObjectDisposedException mit der Botschaft werfen Object name: 'DataContext accessed after Dispose.'.

Es schließt auch die Verbindung, wenn die DataContext öffnete sie und ließ sie offen.

  

3 Ich habe gehört, dass es nicht notwendig ist (siehe zum Beispiel dieser Frage) ein Datacontext zu entsorgen, aber mein Eindruck war, dass es keine schlechte Idee. Gibt es einen Grund, nicht zu verfügen über eine LinqToSql Datacontext?

Es ist erforderlich, die Dispose DataContext, da es notwendig ist, jede andere Dispose IDisposable. Sie könnten möglicherweise Verbindungen auslaufen, wenn Sie die DataContext entsorgen scheitern. Sie könnten auch aus dem DataContext abgerufen Speicher, wenn eine der Einheiten Leck am Leben gehalten werden, da der Kontext eine interne Identität Cache für das Mustereinheit-of-Arbeit hält es implementiert. Aber selbst wenn nichts davon der Fall, es ist nicht Ihre Sorge , was die Dispose Methode intern tut. Nehmen wir an, es tut etwas wichtig.

IDisposable ist ein Vertrag , die sagt: „Bereinigung nicht automatisch sein;. Sie brauchen mich zu entsorgen, wenn Sie fertig sind“ Sie haben keine Garantien, ob das Objekt eine eigene Finalizerthread hat, die nach der aufräumt, wenn Sie Dispose vergessen. Implementationen sind Änderungen vorbehalten, weshalb es ist keine gute Idee, auf dem beobachteten Verhalten verlassen, wie auf explizite Spezifikationen gegenüber.

Das Schlimmste, was passieren kann, wenn man eine IDisposable mit einem leeren Dispose Verfahren entsorgen ist, dass Sie ein paar CPU-Zyklen verschwenden. Das Schlimmste, was passieren kann, wenn man nicht ein IDisposable mit einer nicht-trivialen Implementierung entsorgen es ist, dass Sie Ressourcen auslaufen. Die Auswahl hier ist offensichtlich; wenn Sie einen IDisposable sehen, vergessen Sie nicht, es zu entsorgen.

Andere Tipps

"Personen" ist eine IEnumerable Sammlung, die Datacontext (Repository) ist nur erforderlich, um den .GetNew Anruf.

die von / select / etc Schlüsselwörter sind syntaktischer Zucker für Methoden Erweiterung im Namensraum System.Linq hinzugefügt. Diese Erweiterungsmethoden fügen Sie die IEnumerable Funktionalität Sie in Ihrer Abfrage verwenden, nicht die Datacontext. In der Tat können Sie all dies zu tun, ohne LINQ2SQL überhaupt zu verwenden, um programmatisch ein IEnumerable zu schaffen zu demonstrieren.

Wenn Sie versuchen, eine weitere Repository zu machen (Datacontext) nennt diese Objekte verwenden, das ist, wenn Sie einen Fehler erhalten werden.

Die IEnumerable Sammlung werden alle Datensätze aus Ihrem Repository enthalten, das ist, warum Sie nicht die Datacontext benötigen die Abfrage zu machen.

Erweiterungsmethoden: http://msdn.microsoft.com/en- us / library / bb383977.aspx

LINQ-Erweiterungsmethoden: http://msdn.microsoft.com/en-us/ Bibliothek / system.linq.enumerable_members.aspx

Tief im Inneren des API, werden Sie wahrscheinlich ein Verfahren sehen eine api wie diese verwenden:

http://msdn.microsoft. com / en-us / library / y6wy5a0f (v = VS.100) aspx

Wenn der Befehl ausgeführt wird, wird das zugehörige Verbindungsobjekt geschlossen wird, wenn das zugehörige Datareader-Objekt geschlossen ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top