2010-04-27 14 views
13

Ich lerne jetzt EF und habe eine Frage in Bezug auf die Object:Entity Framework Object Verwertungen

Sollte ich Instanz von Object für jede Abfrage (Funktion), wenn ich auf die Datenbank zugreifen?

Oder ist es besser, es einmal (Singleton) zu erstellen und es wieder zu verwenden?

Bevor EF I Enterprise Library Datenzugriff Block wurde mit und erstellten Instanz von dataacess für Data Access-Funktion ...

+0

IMO - Verwendung DI die Instanz des EF Objektkontextes zu lösen und mit dem Lebensdauern spielen, um zu prüfen, welche Option Ihnen die besten Ergebnisse liefert ... – Sunny

Antwort

14

Auf jeden Fall für jede Abfrage. Es ist ein leichtes Objekt, so dass es nicht viel kostet, jedes Mal, wenn Sie es brauchen, eines zu erstellen.

Außerdem, je länger Sie einen ObjectContext am Leben erhalten, desto mehr Objekte im Cache wird es enthalten, während Sie Abfragen dagegen ausführen. Dies kann zu Speicherproblemen führen. Daher ist die Verwendung des ObjectContext als Singleton eine besonders schlechte Idee. Während Ihre Anwendung verwendet wird, laden Sie mehr und mehr Entitäten in den Singleton ObjectContext, bis Sie schließlich die gesamte Datenbank im Speicher haben (es sei denn, Sie trennen Entitäten, wenn Sie sie nicht mehr benötigen).

Und dann gibt es ein Problem der Wartbarkeit. Eines Tages versucht man, einen Fehler zu finden, kann aber nicht herausfinden, wo die Daten geladen wurden, die ihn verursacht haben.

+3

Ich würde mit dieser Antwort zustimmen, wenn nur die Wahl war Singleton und On-Access. Aber es gibt ein ganzes Spektrum von Lebensdauern, von denen einige je nach Anwendung eine bessere Leistung erbringen können. Der Kontext speichert aus einem Grund :) Pro-Anfrage ist die "sicherste" der Gruppe neben On-Access. –

1

Verwenden Sie kein Singleton .. jeder, der Ihre App verwendet, teilt das und alle möglichen verrückten Dinge passieren, wenn dieser Objektkontext Entitäten verfolgt.

Ich würde es als privates Mitglied hinzufügen

+0

Ich meine Singleton pro Sitzung (jeder Benutzer bekommt seine eigene), und ich plane, die Verfolgung zu deaktivieren – verror

+0

Ich stimme mit rwwilden erste Antwort. –

15

ich denke, die häufigste Art und Weise sie pro Anfrage zu bedienen ist. Erstellen Sie es am Anfang, tun Sie, was Sie brauchen (meistens sind dies Operationen, die einen gemeinsamen ObjectContext benötigen), entsorgen Sie sie am Ende. Die meisten DI-Frameworks unterstützen dieses Szenario, aber Sie können auch HttpModule verwenden, um einen Kontext zu erstellen und ihn in HttpContext.Current.Items zu platzieren. Das ist ein einfaches Beispiel:

public class MyEntitiesHttpModule : IHttpModule 
{ 
    public void Init(HttpApplication application) 
    { 
     application.BeginRequest += ApplicationBeginRequest; 
     application.EndRequest += ApplicationEndRequest; 
    } 

    private void ApplicationEndRequest(object sender, EventArgs e) 
    { 
     if (HttpContext.Current.Items[@"MyEntities"] != null) 
      ((MyEntities)HttpContext.Current.Items[@"MyEntities"]).Dispose(); 
    } 

    private static void ApplicationBeginRequest(Object source, EventArgs e) 
    { 
     var context = new MyEntities(); 
     HttpContext.Current.Items[@"MyEntities"] = context; 
    } 
} 
+1

Ich denke, das ist eine weniger wartungsfreundliche Lösung als einfach einen ObjectContext zu erstellen, wenn Sie einen in der Datenschicht benötigen. Mein Einwand gegen diese Lösung besteht darin, dass Sie eine Abhängigkeit zwischen Ihrer UI-Schicht und Ihrer Datenschicht erstellen, die nicht notwendig ist. Wie Sie mit einer Datenbank kommunizieren, ist eine interne Angelegenheit für die Datenschicht. Zweitens mag es auf den ersten Blick einfach sein, sich nie Sorgen über Probleme mit dem Lazy-Loading machen zu müssen, aber eines Tages versucht man einen Fehler aufzuspüren und kann nicht feststellen, wo es schief gelaufen ist, weil man keine Ahnung hat, wo die Daten liegen Fehler wurde geladen (spricht aus Erfahrung ..) –

+1

@rwwilden: Sorry, aber wie schafft es die Abhängigkeit zwischen UI und Datenschicht? Ich benutze Repository-Muster und Repositories müssen den Kontext teilen. Der Kontext wird vom DI-Container eingegeben. Die Anfrage ist nicht so lang und hat nicht so viele Operationen, die so viele Probleme verursachen können. Wenn Sie geeignete Muster verwenden, haben Sie keine Probleme. – LukLed

+1

@rwwilden: Es gab Millionen Fragen zu ObjectContext-Wiederverwendung, hier auf SO und anderen Seiten. Pro Anfrage scheint die Nutzung zu dominieren, es ist nicht nur meine Meinung. – LukLed

1

Wie Luke sagt, diese Frage wurde mehrmals auf SO gestellt.

Für eine Webanwendung scheint pro Zyklus der Zyklus am besten zu funktionieren. Singleton ist definitiv eine schlechte Idee.

Pro Anfrage funktioniert gut, weil eine Webseite einen Benutzer hat, vielleicht einige Projekte, die zu diesem Benutzer gehören, vielleicht einige Nachrichten für diesen Benutzer. Sie wollen den gleichen ObjectContext, also können Sie User.Messages aufrufen, um sie zu erhalten, vielleicht einige Nachrichten als gelesen markieren, vielleicht ein Projekt hinzufügen und dann das gesamte Objektdiagramm nach Abschluss des Seitenzyklus festschreiben oder abbrechen.

+1

Statisches Singleton ist nicht nur eine schlechte Idee, es ist auch nicht threadsicher! Ein erstellter Kontext sollte nur in einem Thread verwendet werden. –

0

Verspäteter Beitrag hier von 7 Monaten. Ich befasse mich gerade mit dieser Frage in meiner App und lehne mich an die @LukLed-Lösung an, indem ich für die Dauer meiner HttpRequest einen Singleton-ObjectContext erstelle. Für meine Architektur habe ich mehrere Steuerelemente, die zum Erstellen einer Seite verwendet werden, und diese Steuerelemente haben alle ihre eigenen Datenbedenken, die schreibgeschützte Daten aus der EF-Schicht ziehen. Es scheint verschwenderisch zu sein, dass sie jeweils ihren eigenen ObjectContext erstellen und verwenden. Außerdem gibt es ein paar Situationen, in denen ein Steuerelement Daten in den Kontext ziehen kann, die von anderen Steuerelementen wiederverwendet werden können. Auf meiner Hauptseite beispielsweise enthält meine Kopfzeile oben auf der Seite Benutzerinformationen, die von den anderen Steuerelementen auf der Seite wiederverwendet werden können.

Meine einzige Sorge ist, dass ich Entitäten in den Kontext ziehen kann, der die Abfragen anderer Steuerelemente beeinflussen wird. Ich habe das noch nicht gesehen, weiß aber nicht, ob ich nach Ärger frage. Ich denke, wir werden sehen!

0
public class DBModel { 

     private const string _PREFIX = "ObjectContext"; 

     // DBModel.GetInstance<EntityObject>(); 
     public static ObjectContext GetInstance<T>() { 
      var key = CreateKey<T>(); 
      HttpContext.Current.Items[key] = HttpContext.Current.Items[key] ?? Activator.CreateInstance<T>(); 
      return HttpContext.Current.Items[key] as ObjectContext; 
     } 

     private static string CreateKey<T>() { 
      return string.Format("{0}_{1}", _PREFIX, typeof(T).Name); 
     } 
    }