Workaround umożliwiający czytanie widoków SQL w Entity Framework Core 1.1.0

Siemanko.

Od dawna nic nie piszę, ale postanowiłem to zmienić i co więcej, oprócz pisania planuje troszkę publicznie pokodować i pushować na github’a.

Często rozmyślam nad problemami pojawiającymi się podczas codziennej pracy z różnymi technologiami i równie często tworze w domu nowe solucje w Visual Studio tylko po to aby sprawdzić pomysły na rozwiązania wcześniej wspomnianych problemów. Ostatnio zadałem sobie pytanie czemu by tego nie wrzucać do sieci i w dodatku mieć jakiś temat na post na tym moim nieszczęsnym blogu? 😉 Dlatego od teraz każdy poryty kod bedzie lądował na githubie, a tu z kolei kilka zdań na temat przyczyn jego powstania 🙂

EF Core nie wspiera widoków SQL

Ostatnio w robocie piszę funkcjonalności związane z raportowaniem ilościowym danych wg wielu kryteriów. W projekcie używamy tylko i wyłącznie Microsoft’owego ORMa w wersji Core (gdyż aplikacja jest w Asp.Net Core). Przy tego typo raportach, które mam okazję implementować EF wypada bardzo słabo czasowo ponieważ where’owanie czy group’owanie po kolumnie w czwartej z kolei join’owanej tabeli powoduje, że ef musi wykonać całe query jeszcze przed uwzględnieniem where’a aby mieć zmapowane dane z tej czwartej join’owanej tabelki żeby w końcy wykonać na tych danych where’a. 🙂 Wiem, nieźle zakręciłem, ale chodzi finalnie o to że mimo iż w wyniku dostaniesz 10 rekordów to EF może wcześniej wykonać query na 10000 tys. rekordów żeby mieć dostęp do danych z którejś z kolei zjoinowanej tabelki, które zostały uwzględnione w klauzuli where :). W celu poprawy wydajności pomyślałem żeby stworzyć widok SQL, w którym będę miał wszystkie potrzebne kolumny. Niestety EF Core nie wspiera (jeszcze) widoków w przeciwieństwie do EF 6.

Workaround

Wymyśliłem sobie kontekst sklepu. W sklepie jest klilka produktów, które sa pogrupowane w kategorich. Produkt może byc w wielu kategoriach i kategoria może mieć wiele produktów więc mamy tabelkę łączącą relacje wiele do wielu. Oprócz tego produkty sa powiązane relacją jeden do wielu z tabelka zdjęć. Zdjęcie może być tylko dla jednego produktu, a produkt może mieć wiele zdjęć. Chcę pobrać listę kategorii z ich podstawowymi informacjami wraz z jednym losowym produktem i jego zdjęciem oznaczonym jako IsMinPhoto (czyli miniaturka).

Ef Core umożliwia wykonania selecta z czystego SQL poprzez metodkę FromSql(). Metodka ta może zostać wywołana na propercie DbSet<> obiektu DbContext. Utworzyłem sobie zatem model zawierający kolumny, które będą w widoku. Po utworzeniu bazy zostanie utworzona taka tabela jednakże będzie ona zawsze pusta. Tabela wymaga posiadania klucza Id na podstawie, którego EF mapuje rekordy z bazy danych na obiekty jednakże widok nie posiada swojego Id, gdyż jest to tylko zestaw kolumn z innych tabel. Jako klucz dla modelu odwzorującego widok dodałem pole typu string. Bardzo ważne jest aby odpowiednik tego pola znalazł sie także w widoku z tabelki, której rekordy się nie powtarzają w żadnej relacji (w moim przypadku tabelka Photo). Następnie utworzyłem widok SQL w SQL Managment Studio z użyciem designera.

model

Model EF

Bez tytułu.jpg

Widok SQL w SQL Mangment Studio

Czytanie z widoku

queryview

Podsumowanie

Zrobiłem porównanie czasowe z normalnym zapytaniem zrobionym przez Linq na ORMie i przy łącznie raptem kilkunastu rekordach we wszystkich tabelach wyciąganie danych z widoku jest 3krotnie szybsze i w Sql Profilerze widać tylko jedno zapytanie natomiast gdy robił to ORM zapytań w tym przypadku było 3.

Kodzik z testami do uruchomienia znajduje się na githubie.

Pjona!

Reklamy

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s