2017-07-04 2 views
2

Ich habe diese Klasse:C# Entity Framework mit virtuellem Eigentum Abfrage

public class Message 
    { 
     public Message() 
     { 
      Contacts = new List<Contact>(); 
     } 

     public Message(string Sub_Message, string Body_Message, string Date_Send_Message) 
     { 
      Contacts = new List<Contact>(); 

      Subject = Sub_Message; 
      Body = Body_Message; 
      Date = Date_Send_Message; 
     } 

     public int MessageId { get; set; } 
     public string Subject { get; set; } 

     public string Date { get; set; } 

     public string Body { get; set; } 

     public virtual IList<Contact> Contacts { get; set; } 
    } 

Ich mag die Tabelle des Kontakts zu bekommen, weil diese Nachrichten sind virtuell und all verzögertes Laden Sachen,

Dieses Anruf nicht mir arbeiten und habe diesen Fehler:

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. in Reference Table

Syntax:

public ObservableCollection<Model.Message> LoadMessages() 
    { 
     using (db) { 
     var x = from qr in db.Messages 
          order by qr.Subject 
          select qr; 
      } 
    } 

Während dies funktioniert:

public ObservableCollection<Model.Message> LoadMessages() 
{ 
    using (db) 
    { 
     var Messages = db.Messages.Include(z => z.Contacts).ToList(); 

     return new ObservableCollection<Model.Message>(Messages); 
    } 
} 

Also habe ich die Abfragen in einem Dienst namens MessageService, Jedesmal bin mit möchte ich die DbContext verwende ich eine Funktion dafür erstellen und legte es in Verwendung (db)

Like this:

 public class MessageService 
     { 
      ReadingFromData db = new ReadingFromData(); 
      public ObservableCollection<Model.Message> LoadMessages() 
      { 
       using (db) 
       { 
        //Do something with db 
       } 
      } 
} 

auch kann mir jemand erklären, wie das funktioniert, und wie mit Entity Framework Abfragen korrekt

arbeiten

Dank

+0

Bitte geben Sie einen Code ein, um zu zeigen, wie Sie den Kontext verwenden. Wenn die Verbindung geschlossen ist, funktioniert das verzögerte Laden nicht. – Harsh

+0

bearbeitet den Beitrag @Harsh – Zakk

Antwort

3

Zunächst einmal sollten Sie verstehen, dass dieser Code nicht Datenbank nicht abfragen:

var x = from qr in db.Messages 
     orderby qr.Subject 
     select qr; 

es ist nur eine Abfragedefinition (Ausdruck), die in SQL und an den Datenbankserver übersetzt werden sollen wenn Sie es ausführen werden. Die Ausführung führt die Enumeration von Abfrageergebnissen oder die Verwendung eines LINQ-Operators mit sofortiger Ausführung (siehe Classification of Standard Query Operators by Manner of Execution). I.e. Wenn Sie später im Code x aufzählen oder versuchen, Abfrageergebnisse in einer Liste zu speichern, ist es möglich, dass der Datenbankkontext db bereits entsorgt wird. Und natürlich erhalten Sie einen Fehler

var x = db.Messages; // query is not executed 
db.Dispose(); // context disposed 
foreach(var m in x) // exception here, you try to execute query which uses disposed context 
    ... 

Jetzt über Lazy-Laden. Es funktioniert durch Speichern des Datenbankkontexts in den Proxy-Entities, die von Ihren Entities erben. Also tatsächlich db.Messages wird Einheiten eines Typs MessageWithDbContext mit db Wert intern gespeichert. Es ist erforderlich, um zusätzliche "faule" Datenbankabfragen später zu machen. Wenn der Datenbankkontext zu diesem Zeitpunkt wieder entfernt wird, erhalten Sie eine Ausnahme:

var x = db.Messages.ToList(); // query is executed, messages are loaded 
db.Dispose(); // context disposed 
foreach(var m in x) 
    m.Contacts.Count(); // exception - you try to execute contacts query with disposed db 

So lösen Sie dieses Problem? Stellen Sie entweder sicher, dass der Datenbankkontext nicht entfernt wird, während Sie mit der Abfrage arbeiten, und zusätzliche "faule" Aufrufe durchführen. Oder verwenden Sie eifrig laden, wie Sie im zweiten Beispiel tun. Eager Laden können Sie kontrollierte Unternehmen laden, wenn Sie die Abfrage ausführen:

// both messages and contacts are loaded from database when you execute the query 
var x = db.Message.Include(m => m.Contacts).ToList(); 
db.Dispose(); 
foreach(var m in x) 
    m.Contacts.Count(); 

In diesem Fall werden keine zusätzlichen ‚faul‘ Anrufe benötigt werden, so können Sie Datenbankkontext verfügen und mit Abfrageergebnissen arbeiten.

+0

So eifrig laden das Ergebnis sofort, anstatt bis zur Ausführung zu warten? – Zakk

+0

@Zakk eifrig laden wird verwandte Entitäten erhalten, ohne zu warten, bis Sie sie brauchen. Die Abfrage selbst kann zurückgestellt werden, wenn Sie sie nicht z. mit 'ToList()' call (siehe erstes Beispiel) –

1

Lazy loading funktioniert nur, wenn auf die Eigenschaft zugegriffen wird, während die Verbindung zum Kontext offen ist (oder nicht entsorgt wird).

  using (db) 
      { 
       //If you try to load the data here, lazy loading will work. 
      } 

Nun, wenn Sie Include verwenden, EF lädt eifrig und erhält die zugehörigen Daten für Sie. Aus diesem Grund sind Ihre Daten verfügbar, wenn Sie include verwenden.

var Messages = db.Messages.Include(z => z.Contacts).ToList();