Pojedynek ORM

0

W pracy zabieramy się za nową aplikację. Urządzenia końcowe <-> REST <-> DAL <-> ORM.

Do teraz używaliśmy Entity Framework. Jednak jest dużo głosów, że jest do bani i zastanawiamy się nad alternatywami np. NHibernate. Czy ktoś używa komercyjnie? Czy są jakieś przewagi nad?

10

IMHO, Entity Framework do niczego się nie nadaje, nawet do bani.

NHibernate:

  • Operuje na abstrakcjach, nie implementacjach. Głównym tworem jest ISession, który można bezpośrednio mockować i używać w testach. Nie tak jak w EF, który wymaga opakowania Contextu we wrapperository, żeby jakiekolwiek testowanie było możliwe.
  • Cache drugiego poziomu (jedno dla wszystkich session w aplikacji). W EF niemożliwe nawet do zaimplementowania, ze względu na brak fabryki dla Contextów.
  • Kontrola nad generowanym kodem SQL. NH pozwala chociażby na wybór typu joina, EF zawsze robi left.
  • Rozszerzalność - NHibernate ofertuje ponad 30 zdarzeń dotyczących operacji na encjach (każda crudowa operacja w wersji pre i post oraz specjalne zdarzenia dla kolekcji) dzięki czemu wystarczy się podpiąć i wykonać jakąś logikę. EF dla porównania oferuje dwa zdarzenia.
  • Filtry - globalny where dla danego typu encji. W EF niby też jest coś podobnego, ale nie bardzo używane.
  • Generatory pozwalają NHibernate na ustawienie ID po stronie aplikacji, dzięki czemu zapis grafu obiektów nie wymaga ciągłego odpytywania bazy o ostatnio wstawione ID.
  • Wsadowe wstawianie danych do bazy. W EF niemożliwe do zaimplementowania ze względu na brak generatorów ID.
  • Wsparcie dla leniwych właściwości (właściwości, nie całych obiektów).
  • Wsparcie dla różnych typów kolekcji: list, bagów, setów, słowników.
  • Wsparcie dla różnych typów kolumn dla optimistic concurrency (data, int, timestamp...) EF wspiera tylko timestamp albo wszystkie kolumny.
  • Obsługa future queries - kilka zapytań w ramach jednego UoW można wysłać do bazy jednocześnie. (Np. zapytanie o stronę do grida oraz o liczbę wszystkich rekordów w tabeli.)
  • Możliwość generowania zapytań na podstawie nazw właściwości. EF uznaje tylko wyrażenia lambda, czyli jak UI prosi o sortowanie wg nazwy kolumny grida, to nie można tego po prostu przekazać do EF.
  • Pozwala na definiowanie wyliczanych właściwości tłumaczonych na kod SQL. Dzięki temu można np. dla pozycji faktury zdefiniować sobie wartość TotalPrice jako ItemCount * ItemPrice i używać jej w zapytaniach: .Where(x => x.TotalPrice > 5.0). W EF oczywiście niemożliwe.

Pozostaje też kwestia przyzwoitości - jak można używać czegoś, co nie jest zaprojektowane w zgodzie nawet z SRP? W EF jeden obiekt trzyma konfigurację ORMa i UoW, w NH wszystko to jest mądrze podzielone na trzy obiekty (ten trzeci to fabryka UoW).

Ach, żeby nie było, że EF nie ma żadnych zalet. Ma jedną - designer, który pozwala w kilka sekund wygenerować model na podstawie już istniejącej bazy danych. To znacznie przyspiesza pracę, gdy do już istniejącej bazy danych chcemy zrobić jakąś prostą aplikację i nie zależy nam na architekturze, wydajności, itp.

Ale - ponieważ to jest dobre - to w nowej wersji nie będzie. :D

1

A czy ktoś może ustosunkować się do tego co tutaj jest napisane? http://elearning.pwste.edu.pl/blogjw/2-orm
Jak to tak naprawdę jest? Artykuł jest już dość stary ale... czy native SQL to już właściwie przeszłość i teraz wszyscy korzystają z ORM? Czy jednak jest to przerost formy nad treścią?

Czemu pytam? Mam obsługę native SQL dość dobrze opanowaną w swoich projektach i może warto byłoby się zainteresować innym podejściem. Jak wiele razy pisałem - nie programuję zawodowo w sensie komercyjnym ale jednak piszę w swojej pracy aplikacje, które naszą firmę mają jakoś tam wspomagać. Coraz więcej słyszę o ORM i się zastanawiam czy by tego w kolejnym projekcie nie wykorzystać...

Rozwijam się tak jak sam chcę, bo wszystkie moje aplikacje w firmie to moja własna inicjatywa i... nie mając nikogo nad głową, kto by dyktował mi technologię po prostu pytam. :)

0

Od ORM nie ma ucieczki, ale czasami dobrze jest wstępnie przygotować dane już w bazie. Zamiast robić zapytanie bezpośrednio w kodzie można np. skorzystać z widoku czy procedury przechowywanej, które zwrócą mniejszą paczkę danych. Niestety spotykam się często z programami, które niby przeszły testy, ale w produkcji się zamulają. Jak się później okazuje program był testowany na bazie zawierającej kilkaset rekordów, a na produkcji były kilkaset tysięcy i to co w testach trwało sekundę na produkcji trwa 30s

5

Koleś tam chyba chce udowodnić, że ORM w Pythonie są do bani. No i może ma rację, a może nie. Autor chyba nie do końca rozumie do czego ORMy służą, skoro nie wie nawet, że na podstawie definicji klas można wygenerować strukturę bazy danych.

ORMów używa się, bo pozwalają na przyspieszenie procesu tworzenie aplikacji. Nie trzeba tracić czasu na pisanie i debugowanie pełnego literówek SQL i mapowanie pobranych danych na obiekty, bo ORM robi to za nas. Dlatego nie używanie ORM to okradanie siebie z czasu bądź klienta z pieniędzy.
Ale ORMy to nie są uniwersalne narzędzia do każdego zastosowania. Są miejsca, w których się nie sprawdzają - np. hurtowy upload danych z pliku CSV do bazy - w tym celu istnieją lepsze narzędzia, i zaprzęganie do tego ORMa nie ma sensu. Kod SQL generowany przez ORMy też nie jest doskonały, często ma niepotrzebne podzapytania, złączenia, i inne cechy negatywnie wpływające na wydajność. Poza tym, ORMy działają na obiektach, więc np. jeśli chcesz coś z bazy usunąć, musisz to najpierw wczytać. Dla jednego obiektu nie ma problemu, ale przy tysiącu obiektów usuwanych na raz wg jakiegoś kryterium, już robi się absurd - w takim przypadku lepiej napisać procedurę składowaną i ją wywołać z aplikacji.
Ale wiele kodu SQL, na pewno ponad 90% można dzięki ORMom uniknąć. Zarówno w prostych jak i skomplikowanych projektach.

0

@somekind Wiesz... teraz robiłem sobie po prostu singletona, który w ramach całego projektu obsługiwał mi bazę danych w oparciu o native SQL, a w modelach miałem odwzorowane tabele z bazy danych na klasy (jeden do jednego) np:

Tabela..

// Pseudo-kod:
table user {
	int id;
	varchar[15] username;
	varchar[25] name;
	// etc...
}

...była jednym z modeli czyli klasą:

class UserModel {
	public int Id { get; set; }
	public string Username { get; set; }
	public string Name { get; set; }
}

Taki singleton był dla mnie bardzo wygodny, bo obsługiwał mi cały silnik bazy danych z jednej instancji w całym projekcie.
To teraz dla mvvm taki model to już nie będzie po prostu prosta klasa z własnościami i paroma metodami, tylko cała logika przejdzie z native SQL'a do tegoż modelu, obsłużona przez ORM?

PS: tak sobie myślę... mogę o tym poczytać w Internecie, pewnie... ale jestem ciekaw stricte Waszego zdania, bo trochę Was już znam :)

0
somekind napisał(a):

Ale - ponieważ to jest dobre - to w nowej wersji nie będzie. :D

NIe będzie designera do EF? MS strzela sobie w stopę chyba jak tak. EF był właśnie dlatego prostszy do ogarnięcia, że szybko można było wyklikać coś działającego, łącznie z przejrzystym diagramem bazy (no, powiedzmy że przejrzystym jeśli nie ma tam 500 tabel a 5 albo 10).

0

@XXYY To tak samo jak usunęli z serwera Windows 2012 w zarządzaniu GPO możliwość wpisania zaufanych stron i blokowania całej reszty. W serwerze 2008 mogłem sobie powpisywać, na które strony chcę ludzi wpuszczać prostym formularzem. Wpisywało się adresy, kolportowało się to przez polisy w całym AD i działało. Teraz tego już nie ma w GPO. Taka fajna funkcjonalność - usunięta.

Tłumaczyli to tym, że "nooo... tak zrobiono, bo teraz to przeniesiono na inny poziom abstrakcji, bo inny produkt tym będzie zarządzał etc..." - masakra, strasznie nam tego w pracy brakuje.

0

No cóż, wiele posunięć MS ciężko zrozumieć. A co komu np przeszkadzał generator instalatorów w Visual Studio? Można było wygenerować prawie całkowicie automatycznie działający instalator, było ClickOnce itd. Usunięto to i jaka alternatywa? Może Wix, ale tu wtyczka do Visuala (oficjalna), nie pozwala nawet na automatyczne dodanie plików (!), można bodajże tylko utworzyć custom action w dll i rozszerzenie do Wixa a cała reszta to dłubanie ręczne w xml-u.

1

Ja jestem zdania że ORM to dobrodziejstwo i w większości przypadków się sprawdza, więc czemu z niego nie korzystać. Jak gdzieś pojawiają się problemy z wydajnością to trzeba się przeprosić z SQL ale w większości przypadków ORM jest dobrym wyborem zamiast czystego SQLa.

1
grzesiek51114 napisał(a):

Taki singleton był dla mnie bardzo wygodny, bo obsługiwał mi cały silnik bazy danych z jednej instancji w całym projekcie.

Musiałeś napisać masę podobnego kodu SQL, masę mapowania z DataReaderów na obiekty i z obiektów na SqlCommandy, trochę konwersji między typami danych... Napisałeś kupę kodu, który musisz teraz utrzymywać, a którego mógłbyś wcale nie mieć.

Dla mnie wygoda to nie pisaniu kodu, a nie pisanie go dużo. :)

To teraz dla mvvm taki model to już nie będzie po prostu prosta klasa z własnościami i paroma metodami, tylko cała logika przejdzie z native SQL'a do tegoż modelu, obsłużona przez ORM?

Jaką logikę masz na myśli? ORM obsługuje głównie operacje CRUDowe, jeśli w bazie masz obecnie zaszytą np. logikę naliczania rabatów dla klientów w zależności od ich stażu w sklepie, to tego Ci ORM nie da, musiałbyś sam zaimplementować w C#.

XXYY napisał(a):

NIe będzie designera do EF? MS strzela sobie w stopę chyba jak tak. EF był właśnie dlatego prostszy do ogarnięcia, że szybko można było wyklikać coś działającego, łącznie z przejrzystym diagramem bazy (no, powiedzmy że przejrzystym jeśli nie ma tam 500 tabel a 5 albo 10).

EF i tak jest najpopularniejszy, bo promują go wszystkie tutoriale MS do MVC i WPF, więc dotnetowe-newbie-lemingi będą go używały.

Wcześniej zapomniałem o najważniejszej zalecie EF. Otóż, EF stosuje własną matematykę!
Dana jest właściwość typu decimal zmapowana na decimal(18,2) w bazie danych. Właściwość ma wartość np. 20.4777. Co się znajdzie w bazie po insercie? Oczywiście 20.47. Dlaczego nie `20.481, jak nakazuje matematyka? Bo czemu nie? Bo tak się da! Bo to jest Entity Framework! Bo się skompilowało, znaczy jest dobrze!

Żeby było śmieszniej, w czystym ADO.NET działa to dobrze. A EF przecież z niego korzysta. Jak oni zahackowali domyśle działanie ADO.NET, że to się posypało? I kto to kuźwa testował, że tak podstawowego przypadku nie wykryli?

Żeby było jeszcze śmieszniej, to nie zostało naprawione - ale w wersji 6.ileś dodano flagę włączającą prawidłowe zaokrąglanie: https://msdn.microsoft.com/en-us/library/system.data.entity.sqlserver.sqlproviderservices.truncatedecimalstoscale%28v=vs.113%29.aspx

Ale jakby nie patrzeć, żaden inny ORM nie daje możliwości wyboru między stosowaniem matematyki a totalnym wyjebaniem na jej zasady. Gimbusy są pewno zachwycone. :P

0

Gdzieś czytałem o tym zaokrągleniu i czemu tak jest.

Co do przypuszczenia, że EF jest tak popularny bo promują go w każdym kursie giganci jak Microsoft to jest prawda.
Zaczynałem naukę .NET, ASP.NET MVC to w każdej książce technologie .NET czyli wraz z EF, kursy internetowe czy to na codeproject czy MVA też z EF. Nie widziałem kursu z NHibernate. I to jest powód popularności ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1