Czy uważa się, że zapisywanie kodu SQL w kodzie źródłowym jest anty-wzorcem?

87

Czy uważa się za anty-wzorzec kodowania kodu SQL w aplikacji takiej jak ta:

public List<int> getPersonIDs()
{    
    List<int> listPersonIDs = new List<int>();
    using (SqlConnection connection = new SqlConnection(
        ConfigurationManager.ConnectionStrings["Connection"].ConnectionString))
    using (SqlCommand command = new SqlCommand())
    {
        command.CommandText = "select id from Person";
        command.Connection = connection;
        connection.Open();
        SqlDataReader datareader = command.ExecuteReader();
        while (datareader.Read())
        {
            listPersonIDs.Add(Convert.ToInt32(datareader["ID"]));
        }
    }
    return listPersonIDs;
}

Normalnie miałbym warstwę repozytorium itp., Ale dla uproszczenia wykluczyłem ją z powyższego kodu.

Niedawno otrzymałem informację zwrotną od kolegi, który skarżył się, że SQL został napisany w kodzie źródłowym. Nie miałem okazji zapytać, dlaczego, a teraz go nie ma przez dwa tygodnie (może dłużej). Zakładam, że miał na myśli albo:

  1. Użyj LINQ
    lub
  2. Użyj procedur przechowywanych dla SQL

Mam rację? Czy uważa się, że zapisywanie kodu SQL w kodzie źródłowym jest anty-wzorcem? Jesteśmy małym zespołem pracującym nad tym projektem. Myślę, że zaletą procedur przechowywanych jest to, że programiści SQL mogą zaangażować się w proces programowania (pisanie procedur przechowywanych itp.).

Edytuj Poniższy link mówi o zakodowanych instrukcjach SQL: https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/hard-coded-sql-statements . Czy jest jakaś korzyść z przygotowania instrukcji SQL?

w0051977
źródło
31
„Użyj Linq” i „Użyj procedur przechowywanych” nie są powodem; są tylko sugestiami. Poczekaj dwa tygodnie i zapytaj go o powody.
Robert Harvey
47
Sieć Stack Exchange wykorzystuje mikro-ORM o nazwie Dapper. Myślę, że rozsądnie jest powiedzieć, że zdecydowana większość kodu Dappera to „zakodowany SQL” (mniej więcej). Więc jeśli jest to zła praktyka, to jest to zła praktyka przyjęta przez jedną z najbardziej znanych aplikacji internetowych na świecie.
Robert Harvey
16
Aby odpowiedzieć na twoje pytanie dotyczące repozytoriów, zakodowany SQL jest wciąż zakodowanym SQL bez względu na to gdzie go umieścisz. Różnica polega na tym, że repozytorium zapewnia miejsce do enkapsulacji zakodowanego SQL. Jest to warstwa abstrakcji, która ukrywa szczegóły SQL w pozostałej części programu.
Robert Harvey
26
Nie, SQL wewnątrz kodu nie jest anty-wzorcem. Ale to strasznie dużo kodu płyty kotłowej dla prostego zapytania SQL.
GrandmasterB
45
Istnieje różnica między „w kodzie źródłowym” a „rozłożonym po całym kodzie źródłowym”
tofro

Odpowiedzi:

112

Wyłączyłeś kluczową część dla uproszczenia. Repozytorium jest warstwą abstrakcji dla trwałości. Wydzielamy uporczywość na jej własną warstwę, abyśmy mogli łatwiej zmieniać technologię utrwalania , kiedy jest taka potrzeba. Dlatego posiadanie SQL poza warstwą trwałości całkowicie ogranicza wysiłek posiadania oddzielnej warstwy trwałości.

W rezultacie: SQL jest w porządku w warstwie trwałości, która jest specyficzna dla technologii SQL (np. SQL jest w porządku, SQLCustomerRepositoryale nie w a MongoCustomerRepository). Poza warstwą trwałości SQL łamie twoją abstrakcję i dlatego jest uważane przeze mnie za bardzo złą praktykę .

Jeśli chodzi o narzędzia takie jak LINQ lub JPQL: mogą one jedynie wyodrębnić smaki SQL. Posiadanie zapytań o kod LINQ lub JPQL poza repozytorium przerywa abstrakcję trwałości tak samo jak surowy SQL.


Kolejną ogromną zaletą oddzielnej warstwy trwałości jest to, że pozwala ona na unittestowanie kodu logiki biznesowej bez konieczności konfigurowania serwera DB.

Otrzymujesz szybki profil jednostki z niskim profilem pamięci i powtarzalnymi wynikami na wszystkich platformach obsługiwanych przez Twój język.

W architekturze usługi MVC + jest to proste zadanie wyśmiewania instancji repozytorium, tworzenia pewnych fałszywych danych w pamięci i określania, że ​​repozytorium powinno zwracać te fałszywe dane, gdy wywoływany jest określony moduł pobierający. Następnie możesz zdefiniować dane testowe według najcichszych i nie martw się o późniejsze wyczyszczenie bazy danych.

Testowanie zapisów w bazie danych jest tak proste: sprawdź, czy zostały wywołane odpowiednie metody aktualizacji w warstwie trwałości, i zapewnij, że jednostki były w odpowiednim stanie, kiedy to się stało.

marstato
źródło
80
Pomysł, że „możemy zmienić technologię trwałości” jest nierealistyczny i niepotrzebny w zdecydowanej większości projektów w świecie rzeczywistym. SQL / relacyjna baza danych to zupełnie inna bestia niż bazy danych NoSQL, takie jak MongoDB. Zobacz ten szczegółowy artykuł na ten temat. Co najwyżej projekt, który zaczął używać NoSQL, ostatecznie zdałby sobie sprawę ze swojego błędu, a następnie przeszedł na RDBMS. Z mojego doświadczenia wynika, że ​​bezpośrednie używanie obiektowego języka zapytań (takiego jak JPA-QL) z kodu biznesowego zapewnia najlepsze wyniki.
Rogério
6
Co jeśli istnieje bardzo mała szansa, że ​​warstwa trwałości zostanie zmieniona? Co jeśli nie ma mapowania jeden na jeden podczas zmiany warstwy trwałości? Jaka jest zaleta dodatkowego poziomu abstrakcji?
pllee
19
@ Rogério Migracja ze sklepu NoSQL do RDBMS lub odwrotnie jest, jak mówisz, prawdopodobnie nierealistyczna (zakładając, że wybór technologii był właściwy na początek). Byłem jednak zaangażowany w wiele rzeczywistych projektów, w których przeprowadziliśmy migrację z jednego RDBMS do drugiego; w tym scenariuszu enkapsulowana warstwa trwałości jest zdecydowanie zaletą.
David
6
„Pomysł, że„ możemy zmienić technologię trwałości ”jest nierealistyczny i niepotrzebny w zdecydowanej większości projektów w świecie rzeczywistym.” Moja firma wcześniej pisała kod przy takim założeniu. Musieliśmy przebudować całą bazę kodu, aby obsługiwała nie jeden, ale trzy całkowicie różne systemy pamięci / zapytań i rozważamy trzeci i czwarty. Co gorsza, nawet gdy mieliśmy tylko jedną bazę danych, brak konsolidacji doprowadził do różnego rodzaju grzechów kodu.
NPSF3000
3
@ Rogério Znasz „ogromną większość rzeczywistych projektów”? W mojej firmie większość aplikacji może współpracować z jednym z wielu popularnych DBMS, co jest bardzo przydatne, ponieważ większość naszych klientów ma niefunkcjonalne wymagania w tym zakresie.
BartoszKP
55

Obecnie większość standardowych aplikacji biznesowych wykorzystuje różne warstwy z różnymi obowiązkami. Jednak jakie warstwy używasz w swojej aplikacji i która warstwa odpowiada za Ciebie i twój zespół. Zanim podejmiesz decyzję, czy umieszczenie SQL bezpośrednio w funkcji, którą nam pokazałeś, jest właściwe, czy złe, musisz wiedzieć

  • która warstwa w Twojej aplikacji ma jaką odpowiedzialność

  • z której warstwy pochodzi powyższa funkcja

Nie ma na to rozwiązania „uniwersalnego”. W niektórych aplikacjach projektanci wolą używać frameworku ORM i pozwolić, aby frameworki wygenerowały cały SQL. W niektórych aplikacjach projektanci wolą przechowywać taki SQL wyłącznie w procedurach przechowywanych. W przypadku niektórych aplikacji istnieje odręcznie zapisywana warstwa trwałości (lub repozytorium), w której żyje SQL, a w przypadku innych aplikacji można w określonych okolicznościach zdefiniować wyjątki od ścisłego umieszczenia SQL w tej warstwie trwałości.

Więc o czym musisz pomyśleć: jakie warstwy chcesz lub potrzebujesz w konkretnej aplikacji i jak chcesz mieć obowiązki? Napisałeś „Normalnie miałbym warstwę repozytorium” , ale jakie dokładnie obowiązki chcesz mieć w tej warstwie i jakie obowiązki chcesz nałożyć gdzie indziej? Odpowiedz najpierw, a potem sam możesz odpowiedzieć na swoje pytanie.

Doktor Brown
źródło
1
Zredagowałem pytanie. Nie jestem pewien, czy to rzuca jakieś światło.
w0051977
18
@ w0051977: opublikowany link nie mówi nam nic o Twojej aplikacji, prawda? Wygląda na to, że szukasz prostej reguły Braindead, gdzie umieszczać SQL lub nie, która pasuje do każdej aplikacji. Nie ma żadnego. To jest decyzja projektowa ty musisz zrobić o swojej indywidualnej aplikacji (prawdopodobnie wraz z zespołem).
Doc Brown
7
+1. W szczególności chciałbym zauważyć, że nie ma rzeczywistej różnicy między SQL w metodzie, a SQL w procedurze przechowywanej, pod względem tego, jak „coś jest„ zakodowane na stałe ”, lub jak można go ponownie użyć, utrzymać itp. Jakakolwiek abstrakcja, którą można zrobić z procedurę można wykonać za pomocą metody. Oczywiście procedury mogą być przydatne, ale reguła rote „nie możemy mieć SQL w metodach, więc postawmy to wszystko w procedurach” prawdopodobnie spowoduje po prostu wiele cruft z niewielkimi korzyściami.
1
@ user82096 Powiedziałbym, że ogólnie mówiąc, umieszczenie kodu dostępu db w SP jest szkodliwe w prawie każdym projekcie, który widziałem. (Stos MS) Oprócz faktycznego spadku wydajności (sztywne pamięci podręczne planu wykonania), utrzymanie systemu było trudniejsze, ponieważ logika była podzielona, ​​a SP były obsługiwane przez inny zestaw ludzi niż twórcy logiki aplikacji. Zwłaszcza na platformie Azure, gdzie zmiany kodu między gniazdami wdrożeniowymi są jak sekundy pracy, ale migracje schematów innych niż kod pierwszy / db-pierwszy między gniazdami są nieco problematyczne.
Sentinel,
33

Marstato daje dobrą odpowiedź, ale chciałbym dodać więcej komentarzy.

SQL w źródle NIE jest anty-wzorcem, ale może powodować problemy. Pamiętam, kiedy musiałeś wstawiać zapytania SQL we właściwościach składników upuszczanych na każdą formę. To sprawiło, że wszystko było naprawdę brzydkie, naprawdę szybkie i trzeba było skakać przez obręcze, aby znaleźć zapytania. Stałem się silnym zwolennikiem scentralizowania dostępu do bazy danych w jak największym stopniu w ramach ograniczeń języków, z którymi pracowałem. Twój kolega może mieć retrospekcje do tych mrocznych dni.

Teraz niektóre komentarze mówią o zablokowaniu dostawcy, jakby to automatycznie było czymś złym. To nie jest Jeśli mam podpisania czek sześć postać każdego roku korzystać z Oracle, można założyć, że chcę żadnej aplikacji z dostępem do bazy danych za pomocą dodatkowej składni Oracle odpowiednioale w pełni. Nie będę szczęśliwy, jeśli moja błyszcząca baza danych zostanie sparaliżowana przez programistów piszących waniliowo ANSI SQL, gdy istnieje „sposób Oracle” na pisanie SQL, który nie kaleczy bazy danych. Tak, zmiana baz danych będzie trudniejsza, ale widziałem to tylko w witrynie dużego klienta kilka razy w ciągu ponad 20 lat, a jedna z tych spraw przenosiła się z bazy danych DB2 -> Oracle, ponieważ komputer mainframe, na którym przechowywano bazę danych DB2, był przestarzały i został wycofany z eksploatacji . Tak, to jest blokada dostawcy, ale dla klientów korporacyjnych pożądane jest opłacenie drogiego, wydajnego RDBMS, takiego jak Oracle lub Microsoft SQL Server, a następnie wykorzystanie go w jak największym stopniu. Jako kocyk komfortowy masz umowę wsparcia. Jeśli płacę za bazę danych z bogatą implementacją procedury składowanej,

To prowadzi do następnego punktu: jeśli piszesz aplikację, która uzyskuje dostęp do bazy danych SQL , musisz nauczyć się języka SQL, a także innego języka, a przez naukę rozumiem również optymalizację zapytań; Zdenerwuję się na tobie, jeśli napiszesz kod generujący SQL, który opróżnia pamięć podręczną SQL zaporą prawie identycznych zapytań, gdy mógłbyś użyć jednego sprytnie sparametryzowanego zapytania.

Bez wymówek, bez chowania się za ścianą Hibernacji. Źle używane ORM mogą naprawdę osłabić wydajność aplikacji. Pamiętam kilka lat temu pytanie na temat Przepełnienia stosu:

W Hibernacji iteruję przez 250 000 rekordów, sprawdzając wartości kilku właściwości i aktualizując obiekty spełniające określone warunki. Działa trochę wolno, co mogę zrobić, aby go przyspieszyć?

Co powiesz na „UPDATE table SET field1 = gdzie field2 ma wartość True, a Field3> 100”. Problemem może być tworzenie i usuwanie 250 000 obiektów ...

tzn. zignoruj ​​Hibernację, gdy nie jest właściwe jego użycie. Zrozumieć bazę danych.

Podsumowując, osadzanie SQL w kodzie może być złą praktyką, ale są znacznie gorsze rzeczy, które możesz zrobić, próbując uniknąć osadzania SQL.

Mcottle
źródło
5
Nie powiedziałem, że „blokada dostawcy” to zła rzecz. Powiedziałem, że pochodzi z kompromisów. Na dzisiejszym rynku z db jako xaaS takie stare kontrakty i licencje na uruchamianie selfhosted db będą coraz rzadsze. Dzisiaj znacznie łatwiej jest zmienić db od dostawcy A na B w porównaniu do tego, jak to było 10 lat temu. Jeśli czytasz komentarze, nie jestem zwolennikiem korzystania z jakiejkolwiek funkcji przechowywania danych. Łatwo jest więc umieścić niektóre szczegółowe informacje o dostawcy w czymś (aplikacji), która ma być niezależna od dostawcy. Staramy się podążać za SOLiD tylko do końca, aby zablokować kod do pojedynczego magazynu danych. Nic wielkiego
Laiv
2
To świetna odpowiedź. Często właściwym podejściem jest takie, które prowadzi do najmniej złej sytuacji, jeśli napisany jest najgorszy możliwy kod. Najgorszy możliwy kod ORM może być znacznie gorszy niż najgorszy możliwy wbudowany SQL.
jwg
@Laiv dobre punkty PaaS jest trochę zmieniaczem gier - będę musiał pomyśleć więcej o implikacjach.
mcottle
3
@jwg Chciałbym powiedzieć, że powyżej średniego kodu ORM jest gorszy niż poniżej średniego wbudowanego SQL :)
mcottle
@macottle Zakładając, że poniżej średniej osadzony SQL został napisany przez ppl powyżej średniej tego, kto pisze ORM. W co bardzo w to wątpię. Wielu deweloperów nie jest w stanie napisać pozostawionych JOINów bez wcześniejszego sprawdzenia SO.
Laiv
14

Tak, stałe kodowanie ciągów SQL w kodzie aplikacji jest ogólnie anty-wzorcem.

Spróbujmy odłożyć na bok tolerancję, którą wypracowaliśmy od lat postrzegania tego w kodzie produkcyjnym. Mieszanie całkowicie różnych języków z różną składnią w tym samym pliku nie jest na ogół pożądaną techniką programowania. Różni się to od języków szablonów, takich jak Razor, które mają nadawać kontekstowe znaczenie wielu językach. Jak wspomina Sava B. w komentarzu poniżej, SQL w twoim C # lub innym języku aplikacji (Python, C ++ itp.) Jest ciągiem jak każdy inny i jest semantycznie bez znaczenia. To samo dotyczy w większości przypadków mieszania więcej niż jednego języka, choć oczywiście są sytuacje, w których jest to dopuszczalne, takie jak wbudowanie w C, małe i zrozumiałe fragmenty CSS w HTML (zauważ, że CSS jest zaprojektowany do mieszania z HTML ), i inni.

Clean Code autorstwa Roberta C. Martina, str.  288 (Robert C. Martin o mieszaniu języków, Clean Code , rozdział 17, „Zapachy i heurystyka kodu”, strona 288)

Dla tej odpowiedzi skupię się na SQL (jak zadano w pytaniu). Podczas przechowywania SQL jako zestawu oddzielonych ciągów mogą wystąpić następujące problemy:

  • Logika bazy danych jest trudna do zlokalizowania. Czego szukasz, aby znaleźć wszystkie swoje instrukcje SQL? Ciągi znaków z „SELECT”, „UPDATE”, „MERGE” itp.?
  • Refaktoryzacja użycia tego samego lub podobnego SQL staje się trudna.
  • Dodanie obsługi innych baz danych jest trudne. Jak można to osiągnąć? Dodać instrukcje if..then dla każdej bazy danych i przechowywać wszystkie zapytania jako ciągi w metodzie?
  • Deweloperzy czytają instrukcje w innym języku i rozpraszają ich przesunięcie punktu ciężkości z celu metody na szczegóły implementacji metody (sposób i miejsce pobierania danych).
  • Podczas gdy jednowierszowe mogą nie stanowić większego problemu, wbudowane ciągi SQL zaczynają się rozpadać, gdy instrukcje stają się bardziej złożone. Co robisz z zestawieniem wiersza 113? Umieścić wszystkie 113 wierszy w metodzie?
  • W jaki sposób programista skutecznie przenosi zapytania tam iz powrotem między swoim edytorem SQL (SSMS, SQL Developer itp.) A kodem źródłowym? @Prefiks C # ułatwia to, ale widziałem dużo kodu, który cytuje każdą linię SQL i unika znaku nowej linii. "SELECT col1, col2...colN"\ "FROM painfulExample"\ "WHERE maintainability IS NULL"\ "AND modification.effort > @necessary"\
  • Znaki wcięcia używane do wyrównania kodu SQL z otaczającym kodem aplikacji są przesyłane przez sieć przy każdym wykonaniu. Jest to prawdopodobnie nieistotne w przypadku małych aplikacji, ale może się sumować w miarę wzrostu użytkowania oprogramowania.

Pełne ORM (obiekty mapujące obiektowo-relacyjne, takie jak Entity Framework lub Hibernacja) mogą wyeliminować losowo zaszyty SQL w kodzie aplikacji. Moje użycie SQL i plików zasobów jest tylko przykładem. ORM, klasy pomocnicze itp. Mogą pomóc w osiągnięciu celu czyszczenia kodu.

Jak Kevin powiedział we wcześniejszej odpowiedzi, kod SQL może być akceptowalny w małych projektach, ale duże projekty zaczynają się jako małe projekty, a prawdopodobieństwo, że większość zespołów wróci i zrobi to poprawnie, jest często odwrotnie proporcjonalne do rozmiaru kodu.

Istnieje wiele prostych sposobów utrzymywania SQL w projekcie. Jedną z metod, których często używam, jest umieszczenie każdej instrukcji SQL w pliku zasobów Visual Studio, zwykle o nazwie „sql”. Plik tekstowy, dokument JSON lub inne źródło danych może być uzasadnione w zależności od narzędzi. W niektórych przypadkach najlepszą opcją może być osobna klasa poświęcona tworzeniu łańcuchów SQL, ale może ona zawierać niektóre z wyżej opisanych problemów.

Przykład SQL: Który wygląda bardziej elegancko ?:

using(DbConnection connection = Database.SystemConnection()) {
    var eyesoreSql = @"
    SELECT
        Viewable.ViewId,
        Viewable.HelpText,
        PageSize.Width,
        PageSize.Height,
        Layout.CSSClass,
        PaginationType.GroupingText
    FROM Viewable
    LEFT JOIN PageSize
        ON PageSize.Id = Viewable.PageSizeId
    LEFT JOIN Layout
        ON Layout.Id = Viewable.LayoutId
    LEFT JOIN Theme
        ON Theme.Id = Viewable.ThemeId
    LEFT JOIN PaginationType
        ON PaginationType.Id = Viewable.PaginationTypeId
    LEFT JOIN PaginationMenu
        ON PaginationMenu.Id = Viewable.PaginationMenuId
    WHERE Viewable.Id = @Id
    ";
    var results = connection.Query<int>(eyesoreSql, new { Id });
}

Staje się

using(DbConnection connection = Database.SystemConnection()) {
    var results = connection.Query<int>(sql.GetViewable, new { Id });
}

SQL zawsze znajduje się w łatwym do zlokalizowania pliku lub zgrupowanym zestawie plików, każdy z opisową nazwą, która opisuje, co robi, a nie jak to robi, każdy z miejscem na komentarz, który nie zakłóci przepływu kodu aplikacji :

SQL w zasobie

Ta prosta metoda wykonuje pojedyncze zapytanie. Z mojego doświadczenia wynika, że ​​korzyści są skalowane, ponieważ użycie „języka obcego” staje się coraz bardziej wyrafinowane. Moje użycie pliku zasobów jest tylko przykładem. Różne metody mogą być bardziej odpowiednie w zależności od języka (w tym przypadku SQL) i platformy.

Ta i inne metody rozwiązują powyższą listę w następujący sposób:

  1. Kod bazy danych jest łatwy do zlokalizowania, ponieważ jest już scentralizowany. W większych projektach grupuj jak-SQL w osobne pliki, być może w folderze o nazwie SQL.
  2. Obsługa drugiej, trzeciej itd. Baz danych jest łatwiejsza. Utwórz interfejs (lub abstrakcję innego języka), który zwraca unikalne instrukcje dla każdej bazy danych. Implementacja dla każdej bazy danych staje się niewiele więcej niż stwierdzeniem podobnym do: return SqlResource.DoTheThing;To prawda, że ​​te implementacje mogą pomijać zasób i zawierać SQL w ciągu, ale niektóre (nie wszystkie) problemy powyżej nadal będą się pojawiać.
  3. Refaktoryzacja jest prosta - wystarczy ponownie użyć tego samego zasobu. Możesz nawet użyć tego samego wpisu zasobu dla różnych systemów DBMS przez kilka instrukcji formatu. Robię to często.
  4. Używanie języka dodatkowego może używać nazw opisowych, np. sql.GetOrdersForAccountZamiast bardziej rozwartychSELECT ... FROM ... WHERE...
  5. Instrukcje SQL są przywoływane z jedną linią, niezależnie od ich wielkości i złożoności.
  6. SQL można kopiować i wklejać między narzędziami baz danych, takimi jak SSMS i SQL Developer, bez modyfikacji lub starannego kopiowania. Brak znaków cudzysłowu. Brak końcowych ukośników odwrotnych. W przypadku edytora zasobów Visual Studio jedno kliknięcie podświetla instrukcję SQL. CTRL + C, a następnie wklej go do edytora SQL.

Tworzenie SQL w zasobie jest szybkie, więc nie ma większego impulsu do mieszania wykorzystania zasobów z SQL-in-code.

Niezależnie od wybranej metody odkryłem, że mieszanie języków zwykle obniża jakość kodu. Mam nadzieję, że niektóre opisane tutaj problemy i rozwiązania pomogą deweloperom wyeliminować ten zapach kodu, gdy jest to właściwe.

Charles Burns
źródło
13
Myślę, że to zbyt mocno koncentruje się na złej krytyce posiadania SQL w kodzie źródłowym. Posiadanie dwóch różnych języków w tym samym pliku niekoniecznie jest straszne. Zależy to od wielu rzeczy, takich jak sposób ich powiązania i sposób prezentacji.
jwg
9
„mieszanie całkowicie różnych języków z różną składnią w tym samym pliku” To okropny argument. Odnosi się to również do silnika widoku Razor oraz HTML, CSS i JavaScript. Uwielbiam powieści graficzne!
Ian Newson
4
To popycha złożoność gdzie indziej. Tak, twój oryginalny kod jest czystszy, kosztem dodania pośrednictwa, do którego programista musi teraz przejść w celu konserwacji. Prawdziwym powodem, dla którego to zrobiłeś, jest użycie każdej instrukcji SQL w wielu miejscach w kodzie. W ten sposób tak naprawdę nie różni się niczym od zwykłego refaktoryzacji („Metoda wyodrębniania”).
Robert Harvey
3
Mówiąc prościej, nie jest to odpowiedź na pytanie „co mam zrobić z ciągami SQL”, ale odpowiedź na pytanie „co zrobić z dowolną kolekcją wystarczająco złożonych ciągów”, które to pytanie twoja odpowiedź wymownie wymawia.
Robert Harvey
2
@RobertHarvey: Jestem pewien, że nasze doświadczenia się różnią, ale sam uważam, że ta abstrakcja jest w większości przypadków wygrana. Z pewnością udoskonalę swoje kompromisy w zakresie abstrakcji, tak jak robiłem to od lat, i mogę kiedyś przywrócić SQL w kodzie. YMMV. :) Myślę, że mikrousługi mogą być świetne i one również generalnie oddzielają twoje szczegóły SQL (jeśli SQL jest w ogóle używany) od podstawowego kodu aplikacji. W mniejszym stopniu opowiadam się za „skorzystaj z mojej specyficznej metody: zasobów”, a bardziej „Ogólnie nie mieszaj języków ropy i wody”.
Charles Burns
13

To zależy. Istnieje wiele różnych podejść, które mogą działać:

  1. Zmodularyzuj SQL i wyodrębnij go na oddzielny zestaw klas, funkcji lub innej jednostki abstrakcji, której używa twój paradygmat, a następnie wywołaj go za pomocą logiki aplikacji.
  2. Przenieś wszystkie złożone zapytania SQL do widoków, a następnie wykonuj bardzo proste zapytania SQL w logice aplikacji, aby nie trzeba niczego modulować.
  3. Użyj biblioteki mapowania obiektowo-relacyjnego.
  4. YAGNI, po prostu napisz SQL bezpośrednio w logice aplikacji.

Jak to często bywa, jeśli twój projekt wybrał już jedną z tych technik, powinieneś być spójny z resztą projektu.

(1) i (3) są względnie dobre w utrzymywaniu niezależności między logiką aplikacji a bazą danych, w tym sensie, że aplikacja będzie kontynuować kompilację i przejść podstawowe testy dymu, jeśli zastąpisz bazę danych innym dostawcą. Jednak większość dostawców nie jest w pełni zgodna ze standardem SQL, więc zastąpienie dowolnego dostawcy innym dostawcą będzie prawdopodobnie wymagało obszernych testów i wykrywania błędów, niezależnie od używanej techniki. Jestem sceptycznie nastawiony do tego, że jest to tak wielka sprawa, jak się wydaje. Zmiana baz danych jest w zasadzie ostatecznością, gdy nie możesz uzyskać bieżącej bazy danych, która zaspokoi Twoje potrzeby. Jeśli tak się stanie, prawdopodobnie źle wybrałeś bazę danych.

Wybór między (1) i (3) zależy głównie od tego, jak bardzo lubisz ORM. Moim zdaniem są one nadużywane. Stanowią słabą reprezentację relacyjnego modelu danych, ponieważ wiersze nie mają tożsamości w sposób, w jaki obiekty mają tożsamość. Prawdopodobnie napotkasz punkty bólu wokół unikalnych ograniczeń, połączeń i możesz mieć trudności z wyrażaniem bardziej skomplikowanych zapytań w zależności od mocy ORM. Z drugiej strony (1) prawdopodobnie będzie wymagał znacznie więcej kodu niż ORM.

(2) według mojego doświadczenia jest rzadko spotykany. Problem polega na tym, że wiele sklepów zabrania SWE bezpośredniego modyfikowania schematu bazy danych (ponieważ „takie jest zadanie DBA”). To niekoniecznie jest samo w sobie Złe; zmiany schematu mają znaczny potencjał do niszczenia rzeczy i mogą wymagać ostrożnego wdrożenia. Jednak aby (2) działało, SWE powinny przynajmniej móc wprowadzać nowe widoki i modyfikować zapytania pomocnicze istniejących widoków przy minimalnej biurokracji lub bez biurokracji. Jeśli tak nie jest w twoim miejscu pracy, (2) prawdopodobnie nie będzie dla ciebie pracował.

Z drugiej strony, jeśli możesz sprawić, że (2) zadziała, jest to znacznie lepsze niż większość innych rozwiązań, ponieważ utrzymuje logikę relacyjną w SQL zamiast kodu aplikacji. W przeciwieństwie do języków programowania ogólnego przeznaczenia, SQL jest specjalnie zaprojektowany dla relacyjnego modelu danych i odpowiednio lepiej wyraża skomplikowane zapytania i transformacje danych. Widoki można również przenosić wraz z resztą schematu podczas zmiany baz danych, ale utrudniają one takie ruchy.

W przypadku odczytów procedury składowane są w zasadzie po prostu gorszą wersją (2). Nie polecam ich w tym zakresie, ale nadal możesz chcieć ich do zapisu, jeśli twoja baza danych nie obsługuje widoków , które można aktualizować , lub jeśli musisz zrobić coś bardziej złożonego niż wstawianie lub aktualizowanie pojedynczego wiersza na raz (np. transakcje, odczyt, zapis itp.). Możesz połączyć procedurę składowaną z widokiem za pomocą wyzwalacza (tjCREATE TRIGGER trigger_name INSTEAD OF INSERT ON view_name FOR EACH ROW EXECUTE PROCEDURE procedure_name;), ale opinie różnią się znacznie co do tego, czy jest to rzeczywiście dobry pomysł. Zwolennicy powiedzą ci, że utrzymuje SQL, że twoja aplikacja wykonuje się tak prosto, jak to możliwe. Krytycy powiedzą ci, że jest to niedopuszczalny poziom „magii” i że powinieneś po prostu wykonać procedurę bezpośrednio z aplikacji. Powiedziałbym, że jest to lepszy pomysł, jeśli procedura składowana wygląda lub działa dużo jak u INSERT, UPDATEalbo DELETEi gorzej pomysł, nawet jeśli robi coś innego. Ostatecznie musisz sam zdecydować, który styl ma większy sens.

(4) jest nierozwiązaniem. Może się to przydać w przypadku małych projektów lub dużych, które sporadycznie wchodzą w interakcje z bazą danych. Ale w przypadku projektów z dużą ilością SQL nie jest to dobry pomysł, ponieważ możesz mieć przypadkowe duplikaty lub odmiany tego samego zapytania rozrzucone wokół aplikacji, co zakłóca czytelność i refaktoryzację.

Kevin
źródło
2, jak napisano, zasadniczo zakłada bazę danych tylko do odczytu. Procedury składowane nie były rzadkością w przypadku zapytań, które modyfikują.
jpmc26
@ jpmc26: Zapisuję zapisy w nawiasach ... czy masz konkretne zalecenie dotyczące poprawy tej odpowiedzi?
Kevin
Hm Przepraszamy za komentowanie przed udzieleniem odpowiedzi, a następnie rozproszenie uwagi. Jednak możliwe do zaktualizowania widoki utrudniają śledzenie, gdzie aktualizowana jest tabela. Ograniczanie aktualizacji bezpośrednio do tabel, niezależnie od mechanizmu, ma swoje zalety pod względem rozumienia logiki kodu. Jeśli ograniczasz logikę do bazy danych, nie możesz tego egzekwować bez procedur składowanych. Mają także tę zaletę, że umożliwiają wiele operacji za pomocą jednego połączenia. Konkluzja: Nie sądzę, że powinieneś być wobec nich taki trudny.
jpmc26
@ jpmc26: To jest sprawiedliwe.
Kevin
8

Czy uważa się za anty-wzorzec zapisywanie kodu SQL w kodzie źródłowym?

Niekoniecznie. Jeśli przeczytasz tutaj wszystkie komentarze, w kodzie źródłowym znajdziesz prawidłowe argumenty dla zakodowanych na stałe instrukcji SQL.

Problem dotyczy miejsca, w którym umieszczasz wyciągi . Jeśli umieścisz instrukcje SQL w całym projekcie, prawdopodobnie zignorujesz niektóre zasady SOLID, których zwykle staramy się przestrzegać.

założyć, że miał na myśli; zarówno:

1) Użyj LINQ

lub

2) Użyj procedur przechowywanych dla SQL

Nie możemy powiedzieć, co miał na myśli. Możemy jednak zgadywać. Na przykład pierwszy, jaki przychodzi mi do głowy, to blokada dostawcy . Twarde kodowanie instrukcji SQL może doprowadzić do ścisłego powiązania aplikacji z silnikiem DB. Na przykład przy użyciu określonych funkcji dostawcy, które nie są zgodne z ANSI.

To niekoniecznie jest złe lub złe. Po prostu wskazuję na fakt.

Ignorowanie zasad SOLID i blokad dostawcy może mieć negatywne konsekwencje, które możesz ignorować. Dlatego zazwyczaj dobrze jest siedzieć z zespołem i ujawniać swoje wątpliwości.

Myślę, że zaletą procedur przechowywanych jest to, że programiści SQL mogą zaangażować się w proces programowania (pisanie procedur przechowywanych itp.)

Myślę, że nie ma to nic wspólnego z zaletami procedur przechowywanych. Co więcej, jeśli twój kolega nie lubi zakodowanego SQL, prawdopodobnie przeniesienie firmy do procedur przechowywanych również go nie polubi.

Edycja: Poniższy link mówi o zakodowanych instrukcjach SQL:  https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/hard-coded-sql-statements . Czy jest jakaś korzyść z przygotowania instrukcji SQL?

Tak. Post zawiera zalety przygotowanych wypowiedzi . To rodzaj szablonów SQL. Bardziej bezpieczne niż konkatenacja łańcuchów. Ale post nie zachęca cię do pójścia tą drogą ani nie potwierdza, że ​​masz rację. Wyjaśnia tylko, w jaki sposób możemy używać zakodowanego SQL w bezpieczny i wydajny sposób.

Podsumowując, najpierw spróbuj spytać kolegę. Wyślij e-mail, zadzwoń do niego ... Niezależnie od tego, czy odpowie, czy nie, usiądź z zespołem i ujawnij swoje wątpliwości. Znajdź rozwiązanie, które najlepiej odpowiada Twoim wymaganiom. Nie rób fałszywych założeń na podstawie tego, co tam czytasz.

Laiv
źródło
1
Dzięki. +1 za „Twarde kodowanie instrukcji SQL może prowadzić do ścisłego połączenia twojej aplikacji z inżynierem db.”. Wędruję, czy miał na myśli raczej SQL Server niż SQL, tzn. SQLConnection niż dbConnection; SQLCommand zamiast dbCommand i SQLDataReader zamiast dbDataReader.
w0051977
Nie. Miałem na myśli użycie wyrażeń niezgodnych z ANSI. Na przykład: select GETDATE(), ....GETDATE () to funkcja daty SqlServer. W innych silnikach funkcja ma inną nazwę, inne wyrażenie ...
Laiv
14
„Blokada dostawcy” ... Jak często ludzie / przedsiębiorstwa faktycznie migrują bazę danych swojego istniejącego produktu do innego RDBMS? Nawet w projektach wykorzystujących wyłącznie ORM nigdy tego nie widziałem: zwykle oprogramowanie jest również przepisywane od zera, ponieważ między nimi zmieniły się potrzeby. Dlatego myślenie o tym przypomina mi „przedwczesną optymalizację”. Tak, to jest całkowicie subiektywne.
Olivier Grégoire
1
Nie obchodzi mnie, jak często się zdarza. Nie obchodzi mnie to. Może się zdarzyć. W projektach typu greenfield koszt wdrożenia DAL wyodrębnionego z bazy danych wynosi prawie 0. Możliwa migracja nie. Argumenty przeciwko ORM są dość słabe. ORM nie są jak 15 lat temu, kiedy Hibernacja była całkiem zielona. To, co widziałem, to wiele „domyślnie” konfiguracji i całkiem więcej złych projektów modeli danych. Podobnie jak wiele innych narzędzi, wiele osób robi samouczek „Pierwsze kroki” i nie obchodzi ich, co dzieje się pod maską. Narzędzie nie stanowi problemu. Problem polega na tym, kto nie wie, jak i kiedy go użyć.
Laiv
Z drugiej strony, zablokowanie dostawcy niekoniecznie jest złe. Gdybym został zapytany, powiedziałbym , że nie lubię . Jednak jestem już zablokowany na Spring, Tomcat, JBoss lub Websphere (jeszcze gorzej). Takich, których mogę uniknąć. Tych, których nie mogę po prostu z tym żyć. To kwestia preferencji.
Laiv
3

Tak, myślę, że to zła praktyka. Inni wskazywali na zalety przechowywania całego kodu dostępu do danych we własnej warstwie. Nie musisz go szukać, łatwiej jest go zoptymalizować i przetestować ... Ale nawet w tej warstwie masz kilka możliwości: użyj ORM, użyj sproców lub osadzić zapytania SQL jako ciągi znaków. Powiedziałbym, że ciągi zapytań SQL są zdecydowanie najgorszą opcją.

Dzięki ORM programowanie staje się znacznie łatwiejsze i mniej podatne na błędy. Dzięki EF definiujesz swój schemat po prostu tworząc klasy modelu (i tak musiałbyś je utworzyć). Wysyłanie zapytań za pomocą LINQ to pestka - często unikasz 2 linii c #, w których inaczej musiałbyś pisać i utrzymywać sproc. IMO ma to ogromną zaletę, jeśli chodzi o produktywność i łatwość konserwacji - mniej kodu, mniej problemów. Ale jest narzut związany z wydajnością, nawet jeśli wiesz, co robisz.

Sproc (lub funkcje) to druga opcja. Tutaj piszesz zapytania SQL ręcznie. Ale przynajmniej masz gwarancję, że są poprawne. Jeśli pracujesz w .NET, Visual Studio wyrzuci nawet błędy kompilatora, jeśli SQL jest nieprawidłowy. To jest świetne. Jeśli zmienisz lub usuniesz część kolumn, a niektóre zapytania staną się nieprawidłowe, przynajmniej prawdopodobnie dowiesz się o tym podczas kompilacji. Znacznie łatwiej jest także utrzymywać sproki we własnych plikach - prawdopodobnie dostaniesz podświetlanie składni, autouzupełnianie ... itd.

Jeśli Twoje zapytania są przechowywane jako sproki, możesz je również zmienić bez ponownej kompilacji i ponownego wdrożenia aplikacji. Jeśli zauważysz, że coś w twoim SQL jest zepsute, DBA może to naprawić bez potrzeby dostępu do kodu aplikacji. Ogólnie rzecz biorąc, jeśli twoje zapytania są w literałach łańcuchowych, dbas nie może wykonać swojej pracy prawie tak łatwo.

Zapytania SQL jako ciągi literalne sprawią, że twój dostęp do kodu c # będzie mniej czytelny.

Zasadniczo magiczne stałe są złe. Dotyczy to literałów łańcuchowych.

Sava B.
źródło
Zezwolenie DBA na zmianę SQL bez aktualizacji aplikacji skutecznie dzieli aplikację na dwie osobno opracowane, oddzielnie wdrożone jednostki. Teraz musisz zarządzać umową interfejsu między nimi, synchronizować wydawanie współzależnych zmian itp. To może być dobra lub zła rzecz, ale to znacznie więcej niż „umieszczenie całego SQL w jednym miejscu”, to daleko - podjęcie decyzji architektonicznej.
IMSoP,
2

Nie jest to anty-wzór (odpowiedź ta jest niebezpiecznie bliska opinii). Ale formatowanie kodu jest ważne, a ciąg SQL powinien być sformatowany, aby był wyraźnie oddzielony od kodu, który go używa. Na przykład

    string query = 
    @"SELECT foo, bar
      FROM table
      WHERE id = @tn";
rleir
źródło
7
Najbardziej rażącym problemem jest to, skąd pochodzi ta wartość 42. Czy łączysz tę wartość z łańcuchem? Jeśli tak, to skąd to się wzięło? W jaki sposób został oczyszczony, aby złagodzić ataki SQL injection? Dlaczego ten przykład nie pokazuje sparametryzowanego zapytania?
Craig
Chciałem tylko pokazać formatowanie. Przepraszam, zapomniałem go sparametryzować. Teraz naprawiono po odwołaniu do msdn.microsoft.com/library/bb738521(v=vs.100).aspx
rleir
+1 za znaczenie formatowania, chociaż utrzymuję, że ciągi SQL mają zapach kodu niezależnie od formatowania.
Charles Burns
1
Czy nalegasz na użycie ORM? Kiedy ORM nie jest używany, w mniejszym projekcie używam klasy „shim” zawierającej osadzony SQL.
rleir
Ciągi SQL zdecydowanie nie są zapachem kodu. Bez ORM, jako menedżer i architekt, zachęcałbym ich do korzystania z SP zarówno z powodu konserwacji, jak i czasami wydajności.
Sentinel,
1

Nie mogę ci powiedzieć, co miał na myśli twój kolega. Ale mogę odpowiedzieć na to:

Czy jest jakaś korzyść z przygotowania instrukcji SQL?

TAK . Używanie przygotowanych instrukcji ze zmiennymi powiązanymi jest zalecaną ochroną przed wstrzykiwaniem SQL , który pozostaje największym zagrożeniem bezpieczeństwa dla aplikacji internetowych od ponad dekady . Ten atak jest tak powszechny, że pojawiał się w komiksach internetowych prawie dziesięć lat temu, i nadszedł najwyższy czas, aby wdrożyć skuteczne zabezpieczenia.

... a najskuteczniejszą obroną przed złym połączeniem ciągów zapytań nie jest przede wszystkim reprezentowanie zapytań jako ciągów, ale użycie bezpiecznego API typu zapytań do tworzenia zapytań. Na przykład oto, jak napisałbym zapytanie w Javie przy użyciu QueryDSL:

List<UUID> ids = select(person.id).from(person).fetch();

Jak widać, nie ma tu żadnego dosłownego ciągu, co sprawia, że ​​wstrzyknięcie SQL jest prawie niemożliwe. Co więcej, miałem napisane uzupełnienie kodu i moje IDE może refaktoryzować to, czy kiedykolwiek zmienię nazwę kolumny id. Ponadto mogę łatwo znaleźć wszystkie zapytania dotyczące tabeli osób, pytając moje IDE, gdzie personzmienna jest dostępna. Aha, czy zauważyłeś, że jest trochę krótszy i łatwiejszy dla oczu niż twój kod?

Mogę tylko założyć, że coś takiego jest dostępne również dla C #. Na przykład słyszę świetne rzeczy o LINQ.

Podsumowując, reprezentowanie zapytań jako ciągów SQL utrudnia IDE znaczącą pomoc w pisaniu i refaktoryzacji zapytań, odracza wykrywanie błędów składni i typów od czasu kompilacji do czasu wykonania, a także przyczynia się do powstawania luk w iniekcji SQL [1]. Tak, istnieją ważne powody, dla których można nie chcieć ciągów SQL w kodzie źródłowym.

[1]: Tak, prawidłowe użycie przygotowanych instrukcji zapobiega także wstrzykiwaniu SQL. Ale ta inna odpowiedź w tym wątku była podatna na wstrzyknięcie SQL, dopóki komentator tego nie zauważył, nie budzi zaufania do młodszych programistów, którzy używają ich poprawnie w razie potrzeby ...

meriton
źródło
Dla jasności: użycie przygotowanych instrukcji nie zapobiega wstrzyknięciu SQL. Używanie przygotowanych instrukcji z powiązanymi zmiennymi. Możliwe jest użycie przygotowanych instrukcji zbudowanych z niezaufanych danych.
Andy Lester,
1

Wiele świetnych odpowiedzi tutaj. Oprócz tego, co już powiedziano, chciałbym dodać jeszcze jedną rzecz.

Nie uważam używania wbudowanego SQL za anty-wzorzec. To, co uważam za anty-wzór, to każdy programista robiąc swoje. Jako zespół musisz zdecydować się na wspólny standard. Jeśli wszyscy używają linq, wtedy używasz linq, jeśli wszyscy używają widoków i procedur przechowywanych, robisz to.

Zawsze jednak miej otwarty umysł i nie daj się zwieść dogmatom. Jeśli twój sklep jest sklepem „linq”, korzystasz z niego. Z wyjątkiem tego jednego miejsca, w którym linq absolutnie nie działa. (Ale nie powinieneś 99,9% czasu).

Chciałbym więc zbadać kod w bazie kodu i sprawdzić, jak pracują twoi koledzy.

Pieter B.
źródło
+1 Dobry punkt. Obsługa jest ważniejsza niż większość innych kwestii, więc nie bądź zbyt sprytny :) To powiedziawszy, jeśli jesteś sklepem ORM, nie zapomnij, że są przypadki, w których ORM nie jest odpowiedzią i musisz napisać bezpośredni SQL. Nie optymalizuj przedwcześnie, ale w każdej nietrywialnej aplikacji będą czasy, kiedy będziesz musiał zejść tą drogą.
mcottle,
0

Kod wygląda jak z warstwy interakcji z bazą danych, która znajduje się między bazą danych a resztą kodu. Jeśli tak, to nie jest to anty-wzór.

Ta metoda jest częścią warstwy, nawet jeśli OP myśli inaczej (zwykły dostęp do bazy danych, brak mieszania z czymkolwiek innym). Być może jest źle umieszczony w kodzie. Ta metoda należy do osobnej klasy „warstwy interfejsu bazy danych”. Byłoby anty-wzorcem umieszczanie go w zwykłej klasie obok metod realizujących działania inne niż bazy danych.

Anty-wzorzec polegałby na wywołaniu SQL z innego losowego miejsca w kodzie. Musisz zdefiniować warstwę między bazą danych a resztą kodu, ale nie jest tak, że musisz bezwzględnie użyć popularnego narzędzia, które może ci w tym pomóc.

h22
źródło
0

Moim zdaniem nie ma anty-wzorca, ale będziesz miał do czynienia z odstępami formatowania łańcucha, szczególnie w przypadku dużych zapytań, które nie mieszczą się w jednej linii.

kolejną zaletą jest to, że staje się znacznie trudniejsze w przypadku dynamicznych zapytań, które powinny być budowane zgodnie z określonymi warunkami.

var query = "select * from accounts";

if(users.IsInRole('admin'))
{
   query += " join secret_balances";
}

Sugeruję użycie narzędzia do tworzenia zapytań SQL

amd
źródło
Być może po prostu używasz skrótu, ale to naprawdę zły pomysł, aby ślepo używać „WYBIERZ *”, ponieważ zwrócisz niepotrzebne pola (przepustowość !!) Ponadto, chociaż nie mam problemu z warunkową klauzulą ​​administracyjną prowadzi bardzo śliskim zboczem do warunkowej klauzuli „GDZIE” i jest to droga, która prowadzi prosto do piekła wydajności.
mcottle,
0

W przypadku wielu nowoczesnych organizacji z potokami szybkiego wdrażania, w których zmiany kodu mogą być kompilowane, testowane i przekazywane do produkcji w ciągu kilku minut, całkowicie sensowne jest osadzanie instrukcji SQL w kodzie aplikacji. To niekoniecznie jest anty-wzór w zależności od tego, jak sobie z tym poradzisz.

Prawidłowy przypadek zastosowania obecnie procedur przechowywanych dotyczy organizacji, w których istnieje wiele procesów związanych z wdrożeniami produkcyjnymi, które mogą obejmować tygodnie cykli kontroli jakości itp. W tym scenariuszu zespół DBA może rozwiązać problemy z wydajnością pojawiające się dopiero po początkowym wdrożeniu produkcyjnym poprzez optymalizację zapytania w procedurach przechowywanych.

Jeśli nie jesteś w takiej sytuacji, zalecamy osadzenie kodu SQL w kodzie aplikacji. Przeczytaj inne odpowiedzi w tym wątku, aby uzyskać porady na temat tego, jak to zrobić.


Oryginalny tekst poniżej dla kontekstu

Główną zaletą procedur przechowywanych jest to, że można zoptymalizować wydajność bazy danych bez ponownej kompilacji i ponownego wdrażania aplikacji.

W wielu organizacjach kod może zostać przekazany do produkcji dopiero po cyklu kontroli jakości itp., Co może potrwać kilka dni lub tygodni. Jeśli w Twoim systemie wystąpi problem z wydajnością bazy danych z powodu zmiany wzorców użytkowania lub zwiększenia rozmiarów tabel itp., Może być dość trudne do wyśledzenia problemu z zakodowanymi zapytaniami, podczas gdy baza danych będzie zawierała narzędzia / raporty itp., Które zidentyfikują problematyczne procedury przechowywane . Dzięki procedurom przechowywanym rozwiązania mogą być testowane / testowane w produkcji, a problem może zostać szybko rozwiązany bez konieczności wypychania nowej wersji oprogramowania aplikacji.

Jeśli ten problem nie jest ważny w twoim systemie, to jest to całkowicie poprawna decyzja, aby na stałe zapisać instrukcje SQL w aplikacji.

bikeman868
źródło
Źle ...........
Strażnik
Czy uważasz, że Twój komentarz jest komuś pomocny?
bikeman868 11.0418
To jest po prostu niepoprawne. Załóżmy, że mamy projekt Web API2 z EF jako dostępem do danych i Azure Sql jako magazynem. Nie, pozbądźmy się EF i skorzystaj z ręcznie wykonanego SQL. Schemat db jest przechowywany w projekcie SSDT SQL Server. Migracja schematu db polega na upewnieniu się, że podstawa kodu jest zsynchronizowana ze schematem db i w pełni przetestowana przed wypuszczeniem zmiany do testu db na platformie Azure. Zmiana kodu polega na wypchnięciu do gniazda wdrażania usługi aplikacji, co zajmuje 2 sekundy. Plus ręcznie wykonany SQL ma plusy wydajności w stosunku do procedur przechowywanych, ogólnie mówiąc, pomimo „mądrości” wręcz przeciwnie.
Sentinel,
W twoim przypadku wdrożenie może potrwać kilka sekund, ale nie jest tak w przypadku wielu osób. Nie powiedziałem, że procedury przechowywane są lepsze, tylko że w pewnych okolicznościach mają pewne zalety. Moje ostatnie stwierdzenie jest takie, że jeśli te okoliczności się nie zdarzają, to umieszczenie SQL w aplikacji jest bardzo ważne. W jaki sposób przeczy to temu, co mówisz?
bikeman868 11.0418
Procedury przechowywane są ręcznie spreparowane SQL?
bikeman868