Utilizzo del caricamento lento di Entity Framework POCO con cache distribuita

Entity Framework è un motore di mappatura relazionale a oggetti molto popolare fornito da Microsoft e viene sempre più utilizzato in applicazioni ad alto traffico. Inoltre, molte di queste applicazioni ad alto traffico necessitano di una scalabilità che deriva dall'utilizzo di una cache distribuita in memoria. Tuttavia, in alcune situazioni Entity Framework e la cache distribuita in memoria diventano incompatibili. Lascia che ti spieghi come.

Se si utilizza Entity Framework con Plain Old CLR Objects (POCO) insieme alla sua capacità di caricamento lento, Entity Framework genera dinamicamente oggetti proxy che contengono il codice per eseguire il caricamento lento. Inoltre, queste definizioni di oggetti dinamici esistono solo all'interno del processo dell'applicazione e pertanto non possono essere serializzate per una cache distribuita fuori processo.

Ecco un esempio di proxy generato per a Customer entità in cui si desidera utilizzare il caricamento lento di Entity Framework per i correlati orders. Guarda come appare un nome di classe generato dinamicamente. Questo nome di classe è disponibile solo all'interno del processo di candidatura e sarebbe sconosciuto al di fuori del processo.

Utilizzo di Entity Framework POCO
Esempio di proxy generato dal caricamento lento di Entity Framework

Ora, il problema è che una cache distribuita è sempre fuori processo e richiede di serializzare tutti gli oggetti prima di memorizzarli nella cache e quindi potrebbe essere necessario deserializzare questi oggetti su una macchina diversa quando si accede da un'altra casella client. Pertanto, il tipo di oggetto deve essere noto su entrambe le macchine ai fini della deserializzazione. E questo non è possibile con proxy generato dinamicamente in Entity Framework perché sono noti solo all'interno del processo di applicazione su una macchina. Quindi, l'unico modo per te è disabilitare la generazione di proxy in Entity Framework per usarlo con una cache distribuita, ma questo non è uno scenario molto pratico in quanto ciò compromette anche le capacità di caricamento lento di Entity Framework.

Come utilizzare il caricamento pigro di Entity Framework POCO senza proxy?

Per ovviare a questo problema e utilizzare Entity Framework con il caricamento lento, è innanzitutto necessario disabilitare il proxy in modo che non causi problemi di serializzazione. È quindi necessario inserire del codice aggiuntivo nell'applicazione per ottenere il caricamento lento da soli perché se il proxy è disattivato non è disponibile il supporto per il caricamento lento in Entity Framework.

Inoltre, dovresti scrivere questo codice aggiuntivo in modo tale che ti aiuti a ottenere la funzionalità di caricamento lento di Entity Framework e allo stesso tempo non violi il POCO-ness delle tue entità. Discutiamo questo approccio passo dopo passo in modo più dettagliato con un esempio.

Se si dispone di un Customer oggetto che ha un Orders elencarlo come proprietà, il caricamento lento dovrebbe funzionare in modo tale che se si accede al file correlato Orders per un cliente e non sono stati ancora caricati (ovvero non esistono nel contesto di Entity Framework), quindi il Customer L'oggetto effettua automaticamente una chiamata al caricamento correlato Orders. Sto utilizzando questo esempio di seguito per dimostrare come implementare il caricamento lento di Entity Framework senza proxy e utilizzarli anche in una cache distribuita.

  1. Il primo passaggio consiste nel disattivare la generazione di proxy di Entity Framework e anche disattivare la funzionalità di caricamento lento di Entity Framework. Implementi tu stesso il codice di caricamento lento nel passaggio successivo. I context.ContextOptions.ProxyCreationEnabled la proprietà è true per impostazione predefinita. Devi impostarlo esplicitamente su "false" nel costruttore predefinito del tuo oggetto contesto per disattivare questa funzione.
    {
      public NorthwindContext() : base("name=NorthwindContext")
      {
        this.ContextOptions.ProxyCreationEnabled = false;
        this.ContextOptions.LazyLoadingEnabled = false;
      }
    }
    La disabilitazione della generazione del proxy e delle impostazioni di caricamento lento di Entity Framework assicura che il proxy dinamico non venga più creato e che non vi siano problemi di serializzazione con una cache distribuita. Oggetti CLR vecchi normali effettivi (POCO) Customer oggetto viene utilizzato da Entity Framework e quindi può essere memorizzato nella cache e recuperato in una cache distribuita senza problemi.

  2. Il passaggio successivo consiste nell'introdurre del codice che ti aiuti a ottenere il caricamento lento di Entity Framework per gli ordini correlati per un cliente. Come accennato in precedenza, questo codice ti aiuta a raggiungere l'obiettivo, ma dovrebbe anche assicurarsi che gli oggetti cliente e Ordine effettivi rimangano ancora Plain Old CLR Objects (POCO).

    Per questo, crei un'altra classe che ha Entity Framework statico ObjectContext e una funzione utilizzata per la funzionalità di caricamento lento di Entity Framework per gli ordini. Questa funzione viene chiamata per riferimento nell'oggetto POCO del cliente effettivo in un secondo momento. Ecco la definizione del codice per la tua classe Helper.


    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. Ora devi aggiornare il Customer oggetto in modo che abbia la capacità di Entity Framework di caricare in modo lento tutti gli ordini correlati per un cliente. Ecco come aggiornare l'oggetto Cliente e i getter dell'elenco Ordini per chiamare questa funzionalità per riferimento. Devi ancora impostare il OrderLazyLoad metodo per puntare alla funzione di caricamento lento definita nella classe Helper che viene eseguita nel passaggio successivo nel programma principale.
    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. Ora è necessario modificare il programma effettivo per utilizzare questa funzionalità estesa.
    1. Imposta il contesto dell'oggetto nella classe helper CustomerHelper.CurrentContext) essere lo stesso utilizzato nel programma principale in modo che tutte le entità vengano caricate nello stesso contesto dell'oggetto, ovvero si utilizza lo stesso contesto dell'oggetto nel programma consumer e nella funzione definita nella classe helper per il caricamento lento.
      NorthwindContext Context = new NorthwindContext();
      CustomerHelper.CurrentContext = Context;
    2. Hai anche impostato il OrderLazyLoad metodo per puntare alla funzione di caricamento lento dell'Helper. Questo è un posto più appropriato per farlo perché non vuoi il tuo Customer oggetto per fare riferimento direttamente all'oggetto della classe Helper.
      Customer.OrderLazyLoad = Helper.CustomerHelper.DoLazyLoading;
  5. Esegui il programma in cui puoi interrogare i clienti e quindi memorizzarli nella cache in una cache distribuita e visualizzare anche gli ordini correlati con il supporto aggiuntivo del caricamento lento di Entity Framework. Ogni volta che il tuo programma accede al Orders da parte di un Customer, viene chiamata anche la funzionalità di caricamento lento indotto.
    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();
    }

Sommario

Ho discusso un approccio per utilizzare una cache distribuita per la memorizzazione nella cache di Plain Old CLR Objects (POCO) utilizzati in Entity Framework senza doversi preoccupare del problema di serializzazione ed essere ancora in grado di avere la piena funzionalità del caricamento lento di Entity Framework. Sebbene questo approccio preveda la scrittura di codice per ottenere il caricamento lento, in sostanza si hanno i vantaggi della memorizzazione nella cache distribuita come prestazioni elevate, scalabilità e affidabilità in un'applicazione Entity Framework.

© Copyright Alachisoft 2002 - . Tutti i diritti riservati. NCache è un marchio registrato di Diyatech Corp.