Pracuję w firmie, która korzysta z procedur przechowywanych tylko dla wszystkich danych, co sprawia, że bardzo denerwujące jest utrzymywanie synchronizacji naszych lokalnych baz danych, ponieważ każde zatwierdzenie musimy uruchamiać nowe procesy. W przeszłości korzystałem z podstawowych ORM i uważam, że doświadczenie jest znacznie lepsze i czystsze. Chciałbym zasugerować kierownikowi ds. Rozwoju i reszcie zespołu, że rozważamy użycie pewnego rodzaju ORM do przyszłego rozwoju (reszta zespołu zna tylko procedury składowane i nigdy nie używała niczego innego). Obecna architektura to .NET 3.5 napisany jak .NET 1.1, z „boskimi klasami”, które używają dziwnej implementacji ActiveRecord i zwracają nietypowe zestawy danych, które są zapętlone w plikach za kodem - klasy działają mniej więcej tak:
class Foo {
public bool LoadFoo() {
bool blnResult = false;
if (this.FooID == 0) {
throw new Exception("FooID must be set before calling this method.");
}
DataSet ds = // ... call to Sproc
if (ds.Tables[0].Rows.Count > 0) {
foo.FooName = ds.Tables[0].Rows[0]["FooName"].ToString();
// other properties set
blnResult = true;
}
return blnResult;
}
}
// Consumer
Foo foo = new Foo();
foo.FooID = 1234;
foo.LoadFoo();
// do stuff with foo...
Prawie nie ma zastosowania żadnych wzorców projektowych. Nie ma żadnych testów (nikt inny nie wie, jak pisać testy jednostkowe, a testowanie odbywa się poprzez ręczne załadowanie strony internetowej i przeglądanie). Przeglądając naszą bazę danych mamy: 199 tabel, 13 widoków, aż 926 procedur przechowywanych i 93 funkcje. Około 30 tabel jest używanych do zadań wsadowych lub rzeczy zewnętrznych, pozostałe są używane w naszej podstawowej aplikacji.
Czy w tym scenariuszu warto w ogóle zastosować inne podejście? Mówię o posunięciu się naprzód tylko dlatego, że nie wolno nam refaktoryzować istniejącego kodu, ponieważ „działa”, więc nie możemy zmienić istniejących klas na użycie ORM, ale nie wiem, jak często dodajemy nowe moduły zamiast tego dodawania / naprawy bieżących modułów, więc nie jestem pewien, czy ORM jest właściwym podejściem (zbyt dużo zainwestowanych w procedury składowane i DataSets). Jeśli jest to właściwy wybór, jak mam przedstawić przypadek użycia takiego? Z mojej głowy jedyne korzyści, jakie mogę wymyślić, to czystszy kod (choć może nie być, ponieważ obecna architektura nie jest t zbudowany z myślą o ORM, abyśmy mogli w zasadzie sforsować ORMy w przyszłych modułach, ale stare nadal będą korzystać z DataSets) i mniej kłopotów, aby pamiętać, jakie skrypty procedur zostały uruchomione, a które należy uruchomić, itd., ale o to chodzi i nie wiem, jak przekonujący byłby to argument. Utrzymanie jest kolejnym problemem, ale wydaje się, że nikt poza mną nie martwi się.
źródło
Odpowiedzi:
Przechowywane procedury są złe, często są powolne i mniej więcej tak wydajne, jak zwykły kod po stronie klienta.
[Przyspieszenie jest zwykle spowodowane sposobem zaprojektowania interfejsu klienta i procedury składowanej oraz sposobem zapisywania transakcji jako krótkich, ukierunkowanych serii SQL.]
Procedury przechowywane są jednym z najgorszych miejsc do umieszczenia kodu. Dzieli twoją aplikację na dwa języki i platformy zgodnie z często losowymi regułami.
[Pytanie to zostanie ocenione z wynikiem około -30, ponieważ wiele osób uważa, że przechowywane procedury mają magiczne moce i muszą być stosowane pomimo problemów, które powodują.]
Przeniesienie całego kodu procedury składowanej do klienta znacznie ułatwi wszystkim.
Nadal będziesz musiał od czasu do czasu aktualizować schemat i model ORM. Jednak zmiany schematu są odizolowane od zmian ORM, co pozwala na pewną niezależność między aplikacjami a schematem bazy danych.
Będziesz mógł testować, naprawiać, utrzymywać, rozumieć i dostosowywać wszystkie te procedury przechowywane podczas ich przepisywania. Twoja aplikacja będzie działać mniej więcej tak samo i stanie się znacznie mniej krucha, ponieważ nie rozpadasz się już na dwie różne technologie.
ORM nie są magią, a dobre umiejętności projektowania baz danych są absolutnie niezbędne, aby działały.
Ponadto programy z dużą liczbą klientów SQL mogą stać się wolne z powodu złego myślenia o granicach transakcji. Jednym z powodów, dla których procedury przechowywane wydają się być szybkie, jest to, że procedury przechowywane zmuszają do bardzo, bardzo ostrożnego projektowania transakcji.
ORM nie wymuszają w magiczny sposób ostrożnego projektowania transakcji. Projektowanie transakcji wciąż musi być wykonywane tak samo ostrożnie, jak podczas pisania procedur przechowywanych.
źródło
Procedury przechowywane są dobre, szybkie i bardzo wydajne i są idealnym miejscem do umieszczenia kodu związanego z danymi. Przeniesienie całego tego kodu do klienta ułatwi ci trochę jako programistę klienta (nieco, ponieważ nadal będziesz musiał aktualizować schemat i model ORM, gdy zmiany je zmieniają), ale stracisz cały istniejący kod i sprawisz, że Twoja aplikacja działa wolniej i prawdopodobnie jest bardziej delikatna, biorąc pod uwagę utratę wszystkich umiejętności SQL.
Zastanawiam się, czy DBA siedzą tam i mówią „och, każde zatwierdzenie, muszę ponownie ściągać klienta, powinniśmy zamiast tego przenieść cały kod do formularzy DB”.
W twoim przypadku powinieneś być w stanie zastąpić istniejący niestandardowy ORM (tj. Twoje zabawne klasy) komuś innym bez żadnych strat, z wyjątkiem zmian w sposobie pisania kodu za kodem. Możesz także zachować SP, ponieważ większość (wszystkich?) ORM chętnie je nazywa. Tak więc poleciłbym zastąpienie tych klas „Foo” ORM i odtąd. Nie zaleciłbym wymiany twoich SP.
PS. Wygląda na to, że masz dużo wspólnego kodu w klasach kodu, co sprawia, że same w sobie stanowią wzorzec projektowy. Jak myślisz, jaki jest wzór? (ok, może nie być najlepszy, a nawet dobry, ale wciąż jest to DP)
Edit: a teraz z Dapper , każdy powód, aby uniknąć sprocs nad ciężkiej ORM nie ma.
źródło
ds.Tables[0].Rows[0]["FooName"].ToString()
badziewia. Menedżer uwielbia procedury przechowywane? On je zatrzyma. Ale fizycznie niemożliwe byłoby argumentowanie, że przeniesienie całego tego powtarzalnego kodu bojlera na coś wygenerowanego przez, powiedzmy, LINQ na SQL, było złe.Wygląda na to, że próbujesz poprowadzić swój zespół od jednej skrajności (procedury składowane i zestawy danych) do drugiej (pełna ORM). Sądzę, że istnieją inne, bardziej inkrementalne zmiany, które można wprowadzić w celu poprawy jakości kodu warstwy dostępu do danych, które zespół może chętniej zaakceptować.
Na wpół upieczony kod implementacji aktywnego rekordu, który opublikowałeś, nie jest zbyt elegancki - zaleciłbym zbadanie Wzorca Repozytorium, który jest łatwy do zrozumienia i wdrożenia i jest bardzo popularny wśród programistów .NET. Ten wzór jest często kojarzony z ORM, ale równie łatwo można tworzyć repozytoria za pomocą zwykłego ADO.NET.
Co do DataSet - fuj! Biblioteki klas będą znacznie łatwiejsze w obsłudze, jeśli zwrócisz obiekty o typie statycznym (lub nawet dynamicznym). Wierzę w tę ilustrację wyjaśnia moją opinię o DataSet lepiej niż mogłem.
Ponadto możesz porzucić zapisane procy bez przeskakiwania do ORM - nie ma nic złego w używaniu parametru SQL SQL. W rzeczywistości zdecydowanie wolę to niż używanie przechowywanych proc, chyba że masz skomplikowane procedury, które oszczędzają na wielu podróżach w obie strony na serwer. Ja też go nienawidzę, gdy otwieram starszą bazę danych i widzę niekończącą się listę procedur CRUD.
Nie zniechęcam do korzystania z ORM - generalnie używam ich w większości projektów, nad którymi pracuję. Widzę jednak, dlaczego próbowanie wprowadzenia jednego do tego projektu i twojego zespołu może być bardzo trudne, brzmi to tak, jakby przestali się uczyć nowych rzeczy około 8 lat temu. Powiedziawszy, że zdecydowanie spojrzę na nową rasę „Micro ORM”, takich jak Dapper (używany do zasilania tej strony nie mniej) i Massive , z których oba są niezwykle łatwe w użyciu i trzymają cię bliżej SQL niż typowe ORM i które Twój zespół może chętniej zaakceptować.
źródło
Jestem w podobnej sytuacji, właściwie nasz sprzęt, władza i polityka przechodzą na stronę bazy danych, więc wszystko przechodzi procedurę składowaną. Niestety są one kłopotliwe dla kodera, szczególnie jeśli chodzi o generowanie metadanych i kodu, ponieważ w procedurach przechowywanych nie ma tak bogatych metadanych jak tabele.
Niezależnie od tego nadal możesz pisać elegancki i czysty kod za pomocą przechowywanych proc. Obecnie sam wdrażam wzorzec repozytorium ze wszystkimi procedurami przechowywanymi. Sugerowałbym, aby spojrzeć na FluentAdo.net na jego genialny pomysł podczas mapowania z lidera danych z powrotem do twoich obiektów biznesowych. Wziąłem kawałek tego pomysłu i zmieniłem jego przeznaczenie na moje domowe rozwiązanie.
źródło
JFTR - jestem skromnym programistą PHP, ale brzmi to jak kwestia polityczna.
Biorąc pod uwagę skalę „zgnilizny” napędzającej aplikację, to - pomijając najlepsze praktyki - pojawiłby się znaczny narzut, aby ją wykorzenić. Brzmi to tak, jakby graniczyło z terytorium przepisywania.
Czy możesz zagwarantować, że zaproponowana przez ciebie alternatywa przyniosłaby korzyści uzasadniające koszty dla firmy? Podejrzewam, że ROI tego przedsięwzięcia może być trudne do sprzedania firmie. Chyba że aplikacja jest niestabilna lub możesz udowodnić zasadność przeglądu pod względem finansowym - może to być trudne.
Czy ORM jest jedyną alternatywą dla SPROCS? Istnieje kilka wzorców projektowych między pełnowymiarowym ORM a waniliowym SQL. Być może mógłbyś rozpocząć proces od stopniowego przenoszenia SPROCS z DB do DBAL. Istnieje oczywiście niebezpieczeństwo, że z czasem przerośnie to w ORM - ale będziesz miał krok bliżej celu.
źródło
Kilka lat temu przeszliśmy z SP na ORM.
W jednym przypadku musieliśmy zaktualizować 80 tabel. Stary model szacowania oszacowałby na to 80 godzin w przypadku entlib i SP. Zrobiliśmy to w 10 :)
Dało nam to o 80% mniej czasu poświęcanego na tworzenie warstwy dostępu do danych.
źródło
Bardziej wydaje mi się, że podstawowym problemem jest to, że Twoje wdrożenia nie działają poprawnie i automatycznie.
Może być łatwiej ustawić silnik ciągłej kompilacji, który wie, jak manipulować bazami danych w razie potrzeby po każdym zatwierdzeniu.
źródło