Kategorie szkoleń | Egzaminy | Kontakt
  • 1
  • 1
  • 78

Na szkoleniu z Entity Framework dowiedziałem się, że jedną z metod optymalizacji Entity Framework jest generowanie widoków za pomocą EF Power Tools. Niestety trzeba pamiętać o tym, aby po każdej zmianie modelu przegenerować widoki. Czy istnieje możliwość wygenerowania widoków z kodu?

 

  • Zapytał
  • @ | 18.04.2016
  • TRENER ALTKOM AKADEMII

Odpowiedź (1)

  • 0

Tak, istnieje taka możliwość.

Standardowo Entity Framework generuje widoki samodzielnie przy pierwszym zapytaniu do bazy danych. Niestety ma to negatywny wpływ na czas uruchamiania aplikacji. Dlatego wspomniane pre-generowanie widoków (nie mylić z views na bazie danych) za pomocą EF Power Tools może odczuwalnie przyspieszyć start aplikacji, zwłaszcza przy większej ilości encji.

Niestety tak jak napisałeś trzeba pamiętać, aby po każdej zmianie modelu przegenerować widoki i przekompilować aplikację.

Dużo lepszym sposobem byłoby automatycznie przegenerowanie widoków przy starcie aplikacji i wykorzystanie ich przy kolejnych uruchomieniach. Zatem aplikacja powinna sprawdzać przy uruchamianiu czy nie zmienił się model i w razie czego wygenerować widoki i zachować je gdzieś na dysku do kolejnego uruchomienia.

Niestety klasa DbContext nie posiada wprost metody do generowania widoków. Taką metodę posiadała starsza klasa ObjectContext. Okazuje się jednak, że DbContext jest nakładką na ObjectContext i można się dostać do starszej klasy pewnym trickiem.

Wystarczy zrzutować obiekt DbContext na interfejs IObjectContextAdapter:

 

  ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;

 

Mając już ObjectContext możemy dostać się do metody generującej widoki:

 

 var workspace = objectContext.MetadataWorkspace;

                var mappingCollection = workspace.GetItemCollection(DataSpace.CSSpace);

                var storage = mappingCollection as System.Data.Entity.Core.Mapping.StorageMappingItemCollection;

                IList<EdmSchemaError> errors = new List<EdmSchemaError>();

                var views = storage.GenerateViews(errors);

                var hash = storage.ComputeMappingHashValue();

 

Tak wygenerowane powinniśmy przechować poza zasobami aplikacji, aby nie trzeba jej rekompilować.

Tak wygenerowane widoki można później ładować. Dokładniej opisane jest to w MSDN:

https://msdn.microsoft.com/en-us/data/dn469601.aspx#generating

Pełna implementacja może zająć sporo czasu, zatem proponuję skorzystać z gotowej implementacji w postaci biblioteki EFInteractiveViews

Pobieramy paczkę EFInteractiveViews za pomocą nugeta:

 

Install-Package EFInteractiveViews

 

Następnie wskazujemy miejsce gdzie będą przechowywane wygenerowane widoki:

 

using (var context = new MyDbContext())
{
    InteractiveViews
        .SetViewCacheFactory(
            context, 
            new FileViewCacheFactory(@"C:\MyViews.xml"));
}

 

Co ciekawe, istnieje również możliwość przechowywania widoków w bazie danych:

 

using (var context = new MyDbContext())
{
    InteractiveViews
        .SetViewCacheFactory(
            context, 
            new SqlServerViewCacheFactory(context.Database.Connection.ConnectionString));
}

 

Dokładny opis biblioteki można znaleźć na stronie: 

https://blog.3d-logic.com/2013/12/14/using-pre-generated-views-without-having-to-pre-generate-views-ef6/

Powodzenia!

 

  • Odpowiedział
  • @ | 18.04.2016
  • TRENER ALTKOM AKADEMII