Dapper – ja to wolę mieć kontrolę nad SQLem

Komunikacja z bazą danych to element, który w większości standardowych aplikacji zajmuje najwięcej czasu. Logika biznesowa, nawet dosyć złożona, jest nieporównywalnie szybsza niż odczytanie czegoś z tabeli w bazie. Poza tym, że sama komunikacja wymaga czasu to dochodzi jeszcze dopasowanie rekordów z bazy do obiektów w kodzie. W końcu po to nasz język posiada silne typowanie żebyśmy z tego korzystali. W tym celu korzystamy z bibliotek nazywanych ORM – Object-Relational Mapping. Pozwalają nam one wykonywać polecenia w bazie danych operując w kodzie na standardowych obiektach. Jednak również to zadanie wymaga czasu. A do tego wszystkiego może się okazać, że SQL jaki wysyłamy do bazy nie jest tym, który zadziała najlepiej…

Król jest tylko jeden?

Bez wątpienia najpopularniejszym ORMem w świecie .NET jest Entity Framework od Microsoftu. Pojawia się w większości tutoriali i można go mieć wstępnie skonfigurowanego w nowym projekcie. Jego wykorzystanie jeszcze wzrosło kiedy do akcji wszedł .NET Core. Wtedy to Entity Framework Core jako pierwszy był dostępny dla tej technologii. Drugi popularny ORM – NHibernate potrzebował więcej czasu na przeportowanie na nowy framework.

Nie taki idealny

M.in. przez to nie tylko pojedynczy programiści jako jedyny słuszny wybór uznają Entity Framework. Również całe firmy nierzadko uważają, że jest on dobrym wyborem.

Jednak każdy kto próbował za jego pomocą wykonać bardziej skomplikowane zapytanie złożone np. z kilku JOINów i GROUP BY ten wie ile nerwów można stracić. Innym kłopotliwym zagadnieniem jest problem N+1 czyli dosyć łatwe doprowadzenie do sytuacji kiedy próbując pobrać kilka wierszy ładujemy do pamięci całą bazę. Związane jest to z lazy loadingiem i połączeniami między obiektami. Dla mniej wprawnego programisty problem ten będzie jednocześnie trudny do znalezienia i dosyć prosty do stworzenia.

Oprócz tego Entity Framework z racji swojej uniwersalności i operowania w pełni na obiektach i metodach C# potrafi wyprodukować SQL, któremu daleko do ideału. I niestety nad tym SQLem nie mamy za bardzo kontroli. Przynajmniej bezpośredniej. Bo oczywiście można próbować różnych kombinacji i kolejności wywołań metod. Ale na samym końcu i tak biblioteka zrobi wszystko po swojemu.

Dodatkowo Entity Framework, jako produkt Microsoftu, najlepiej wspiera bazę Microsoft SQL Sever. Chcąc połączyć się np. z bazą Oracle czeka nas więcej pracy.

Alternatywa skrojona na wymiar

Jaka jest najczęstsza operacja na danych w przeciętnej aplikacji webowej? Mam nadzieję, że nikogo nie zaskoczę mówiąc, że odczyt danych. Nawet jeżeli nasza aplikacja zawiera dużo formularzy to na jeden zapis przydać może przynajmniej kilka operacji odczytu. Czy to wartości potrzebnych w tym formularzy, czy częściej po prostu danych już wprowadzonych do bazy. Potrzebujemy je po prostu wyciągnąć z tabel i wysłać do widoku.

Dlaczego więc mielibyśmy zaprzęgać do tego ciężki ORM, który potrafi mieć problemy z joinami albo mający domyślnie włączone śledzenie obiektów? Operacja odczytu powinna być szybka, skoro jest powtarzana bardzo często. Narzut frameworka nie sprzyja temu. Więc warto by było ten narzut zminimalizować.

Właśnie z tego powodu ekipa odpowiedzialna za znany programistom serwis StackOverflow stworzyła microORM, który potem udostępnili jako open-source. Mowa o bibliotece Dapper. Znaleźć go można na GitHubie. Tam też znajduje się instrukcja jak wszystko ze sobą połączyć i używać. Jest też oczywiście dostępny jako paczka w managerze NuGet więc instalacja w projekcie jest prosta.

Przejmij kontrolę

Dapper jest przykładem ORMa, którego funkcjonalność jest ograniczona do minimum. Robi on tylko i aż mapowanie pomiędzy zapytaniami i obiektami w kodzie. Jednak o to jak wyglądać będzie zapytanie musimy zatroszczyć się sami. Dapper wykonuje jedynie kod SQL, który sami napiszemy. Jego odpowiedzialnością jest jedynie zamiana zwróconych wartości na obiekty w kodzie C# albo wstawienie wartości z kodu C# do zapytania SQL.

Dzięki temu mamy pełną kontrolę nad tym jak wyglądać będzie zapytanie. Ale też przez to musimy znać w miarę dobrze SQLa, żeby pisać zapytania, które potrzebujemy. Przez to problem słabego SQLa to jedynie nasz problem ;)

Efektem minimalnej funkcjonalności Dappera jest jego wydajność. Dapper do czasu odświeżenia Entity Frameworka wraz z nadejściem wersji Core był nie do doścignięcia przez standardowe ORMy jeżeli chodzi o czas wykonania zapytań. Nadal jest w czołówce.

Czy warto?

W pracy używamy obu frameworków. Jak to tak zapytasz? Po prostu Dapper z racji szybkości działania i bezproblemowego wsparcia innych baz danych służy nam do odczytu danych. A przy zapisie wykorzystujemy możliwości Entity Frameworka takie jak śledzenie obiektów. Po prostu dobieramy narzędzia do problemów.

Jeżeli czujesz, że straciłeś kontrolę nad tym jak wyglądają zapytania do bazy, albo potrzebujesz czegoś lżejszego to Dapper jest ciekawą alternatywą. Jednak jego lekkość i minimalizm powoduje, że nie jest od dla każdego. Na pewno nie jest dla osób, które uważają, że programista C# nie musi znać SQLa. Nie jest też dla tych, którzy chcą aby jednym poleceniem zrobić wszystko. Dapper wymaga od nas dużo więcej uwagi. Ale odwdzięcza się przejrzystością i wydajnością trudną do osiągnięcia w standardowych dużych ORMach.

Spisał się w przypadku StackOverflow, a czy spisze się w Twoim projekcie?

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *