Verwenden von Entity Framework POCO Lazy Loading mit verteiltem Cache

Entity Framework ist eine sehr beliebte objektrelationale Mapping-Engine von Microsoft und wird zunehmend in Anwendungen mit hohem Datenverkehr eingesetzt. Und viele dieser Anwendungen mit hohem Datenverkehr benötigen Skalierbarkeit, die durch die Verwendung eines verteilten In-Memory-Cache erreicht wird. In einigen Situationen sind Entity Framework und der verteilte In-Memory-Cache jedoch nicht kompatibel. Lassen Sie mich erklären, wie.

Wenn Sie Entity Framework mit Plain Old CLR Objects (POCO) zusammen mit seiner Lazy-Loading-Funktion verwenden, generiert Entity Framework dynamisch Proxy-Objekte, die den Code für das Lazy-Loading enthalten. Und diese dynamischen Objektdefinitionen existieren nur innerhalb des Anwendungsprozesses und können daher nicht für einen verteilten Cache außerhalb des Prozesses serialisiert werden.

Hier ist ein Beispiel für die Generierung eines Proxys für a Customer Entität, für die Sie Entity Framework Lazy Loading für verwandte Elemente verwenden möchten orders. Sehen Sie, wie ein dynamisch generierter Klassenname aussieht. Dieser Klassenname ist nur innerhalb des Bewerbungsprozesses verfügbar und wäre außerhalb des Prozesses unbekannt.

Verwenden des Entity Framework POCO
Beispiel für einen Proxy, der durch verzögertes Laden von Entity Framework generiert wird

Das Problem besteht nun darin, dass ein verteilter Cache immer außer Prozess ist und Sie alle Objekte serialisieren müssen, bevor Sie sie zwischenspeichern. Anschließend müssen diese Objekte möglicherweise auf einem anderen Computer deserialisiert werden, wenn von einer anderen Client-Box aus auf sie zugegriffen wird. Daher muss der Objekttyp für Deserialisierungszwecke auf beiden Maschinen bekannt sein. Dies ist mit dynamisch generierten Proxys im Entity Framework nicht möglich, da diese nur innerhalb des Anwendungsprozesses auf einem Computer bekannt sind. Die einzige Möglichkeit für Sie besteht also darin, die Proxy-Generierung in Entity Framework zu deaktivieren, um sie mit einem verteilten Cache zu verwenden. Dies ist jedoch kein sehr praktisches Szenario, da dadurch auch die Lazy-Loading-Funktionen von Entity Framework beeinträchtigt werden.

Wie verwende ich Entity Framework POCO Lazy Loading ohne Proxy?

Um dieses Problem zu lösen und Entity Framework mit Lazy Loading zu verwenden, müssen Sie zunächst den Proxy deaktivieren, damit er keine Serialisierungsprobleme verursacht. Anschließend müssen Sie zusätzlichen Code in Ihre Anwendung einfügen, um selbst Lazy Loading zu erreichen, denn wenn der Proxy deaktiviert ist, gibt es in Entity Framework keine Unterstützung für Lazy Loading.

Außerdem sollten Sie diesen zusätzlichen Code so schreiben, dass er Ihnen hilft, die Lazy-Loading-Funktionalität von Entity Framework zu erreichen, und gleichzeitig die POCO-Qualität Ihrer Entitäten nicht verletzt. Lassen Sie uns diesen Ansatz Schritt für Schritt anhand eines Beispiels näher erläutern.

Wenn du ein ... hast Customer Objekt, das eine hat Orders Wenn Sie die Liste als Eigenschaft darin auflisten, sollte Lazy Loading so funktionieren, dass Sie auf die zugehörige Datei zugreifen Orders für einen Kunden und sie wurden noch nicht geladen (was bedeutet, dass sie im Entity Framework-Kontext nicht vorhanden sind), dann die Customer Das Objekt führt automatisch einen Ladeaufruf durch Orders. Ich verwende dieses Beispiel unten, um zu demonstrieren, wie Entity Framework Lazy Loading ohne Proxy implementiert und auch in einem verteilten Cache verwendet wird.

  1. Der erste Schritt besteht darin, die Entity Framework-Proxy-Generierung und auch die Entity Framework-Lazy-Loading-Funktionalität zu deaktivieren. Im nächsten Schritt implementieren Sie den Lazy-Loading-Code selbst. Das context.ContextOptions.ProxyCreationEnabled Die Eigenschaft ist standardmäßig true. Sie müssen es im Standardkonstruktor Ihres Kontextobjekts explizit auf „false“ setzen, um diese Funktion zu deaktivieren.
    {
      public NorthwindContext() : base("name=NorthwindContext")
      {
        this.ContextOptions.ProxyCreationEnabled = false;
        this.ContextOptions.LazyLoadingEnabled = false;
      }
    }
    Durch das Deaktivieren der Proxy-Generierung und der Entity Framework Lazy Loading-Einstellungen wird sichergestellt, dass kein dynamischer Proxy mehr erstellt wird und es bei einem verteilten Cache kein Serialisierungsproblem gibt. Tatsächliche einfache alte CLR-Objekte (POCO) Customer Das Objekt wird vom Entity-Framework verwendet und kann daher problemlos in einem verteilten Cache zwischengespeichert und abgerufen werden.

  2. Der nächste Schritt besteht darin, Code einzuführen, der Ihnen dabei hilft, Entity Framework Lazy Loading für zugehörige Bestellungen für einen Kunden zu erreichen. Wie oben erwähnt, hilft Ihnen dieser Code, das Ziel zu erreichen, aber er sollte auch sicherstellen, dass tatsächliche Kunden- und Bestellobjekte weiterhin Plain Old CLR Objects (POCO) bleiben.

    Dazu erstellen Sie eine weitere Klasse mit statischem Entity-Framework ObjectContext und eine Funktion, die für die Lazy-Loading-Funktionalität von Entity Framework für Bestellungen verwendet wird. Diese Funktion wird später per Referenz im eigentlichen Kunden-POCO-Objekt aufgerufen. Hier ist die Codedefinition für Ihre Helper-Klasse.


    namespace Helper
      {
          public class CustomerHelper
              {
                  public static NorthwindContext CurrentContext;
                  static public void DoLazyLoading(Customer customer, List<Order> orders)
                      {
                          if (CurrentContext == null) return; //no lazy loading
                          var query = from o in CurrentContext.Orders where o.CustomerID == customer.CustomerID select o;
                  
                  foreach (Order o in query)
                          { orders.Add(o); }
                    }
                }
    }
  3. Sie müssen jetzt die aktualisieren Customer Objekt, sodass es über die Fähigkeit des Entity Frameworks verfügt, alle zugehörigen Bestellungen für einen Kunden verzögert zu laden. So aktualisieren Sie die Getter für das Kundenobjekt und die Bestellliste, um diese Funktionalität per Referenz aufzurufen. Sie müssen das noch einstellen OrderLazyLoad Methode, um auf die Lazy-Loading-Funktion zu verweisen, die in der Hilfsklasse definiert ist. Dies erfolgt im nächsten Schritt in Ihrem Hauptprogramm.
    namespace MyPOCOs
    {
      [Serializable]
      public class Customer
      {
        public string CustomerID { get; set; }
        public string CompanyName { get; set; }
        public static Action < Customer, List < Order >> OrderLazyLoad = null;
    
        private List < Order > orders; 
        public virtual List< Order > Orders
        {
          get
          {
            if (orders == null)
            {
              orders = new List < Order >();
              OrderLazyLoad(this, orders);
            }
            return orders;
          }
          set
          {
            orders = value;
          }
        }
      }
      [Serializable]
      public class Order…
    }
  4. Sie müssen nun Ihr eigentliches Programm ändern, um diese erweiterte Funktionalität nutzen zu können.
    1. Sie legen den Objektkontext in der Hilfsklasse fest CustomerHelper.CurrentContext) muss derselbe sein wie im Hauptprogramm, sodass alle Entitäten unter demselben Objektkontext geladen werden, dh Sie verwenden denselben Objektkontext sowohl im Verbraucherprogramm als auch in der Funktion, die in der Hilfsklasse für verzögertes Laden definiert ist.
      NorthwindContext Context = new NorthwindContext();
      CustomerHelper.CurrentContext = Context;
    2. Sie legen auch fest OrderLazyLoad Methode, um auf die Lazy-Loading-Funktion des Helfers zu verweisen. Dies ist ein geeigneterer Ort, um dies zu tun, da Sie dies nicht möchten Customer -Objekt, um direkt auf das Objekt der Helper-Klasse zu verweisen.
      Customer.OrderLazyLoad = Helper.CustomerHelper.DoLazyLoading;
  5. Führen Sie das Programm aus, mit dem Sie Kunden abfragen und diese dann auch in einem verteilten Cache zwischenspeichern und mit der zusätzlichen Unterstützung von Entity Framework Lazy Loading auch zugehörige Bestellungen anzeigen können. Jedes Mal, wenn Ihr Programm auf die zugreift Orders von einem Customer, wird auch die induzierte Lazy-Loading-Funktionalität aufgerufen.
    static void Main(string[] args)
    {
      Cache mycache = NCache.InitializeCache("mycache");        
      NorthwindContext Context = new NorthwindContext();
      CustomerHelper.CurrentContext = Context;
      Customer.OrderLazyLoad = Helper.CustomerHelper.DoLazyLoading;
    
      var query = from c in Context.Customers where c.CompanyName.StartsWith("b") select c;
      foreach (Customer c in query)
      {
        mycache.Insert(c.CustomerID, c);
        Console.WriteLine("{0}", c.CustomerID);
        foreach (Order order in c.Orders)
        {
          Console.WriteLine("\t{0}", order.OrderDate.ToString());
        }
      }
      Console.ReadLine();
    }

Zusammenfassung

Ich habe einen Ansatz besprochen, um einen verteilten Cache zum Zwischenspeichern von Plain Old CLR Objects (POCO) zu verwenden, die in Entity Framework verwendet werden, ohne sich um Serialisierungsprobleme kümmern zu müssen und trotzdem die volle Funktionalität des verzögerten Ladens von Entity Framework nutzen zu können. Bei diesem Ansatz ist zwar das Schreiben von etwas Code erforderlich, um ein verzögertes Laden zu erreichen, doch im Wesentlichen profitieren Sie von den Vorteilen des verteilten Cachings wie hoher Leistung, Skalierbarkeit und Zuverlässigkeit in einer Entity-Framework-Anwendung.

© Copyright Alachisoft 2002 - Alle Rechte vorbehalten NCache ist eine eingetragene Marke der Diyatech Corp.