Pytanie Czy powinienem sprawdzić ograniczenia DB w kodzie lub czy powinienem wychwycić wyjątki zgłaszane przez DB


Mam aplikację, która zapisuje dane w tabeli o nazwie Praca. Tabela Zadania ma kolumnę o nazwie Nazwa, która ma ograniczenie UNIQUE. Kolumna Name nie jest PRIMARY KEY. Zastanawiam się, czy powinienem sam sprawdzić duplikaty wpisów, zanim spróbuję zapisać / zaktualizować nowy wpis, lub czy lepiej poczekać na wyjątek zgłoszony przez warstwę dostępu do danych. Używam NHibernate dla tej aplikacji, jeśli ma jakiekolwiek znaczenie


Dziękuję wszystkim za wspaniały wkład.

Znalazłem jeszcze jeden powód, dla którego powinienem potwierdzić w kodzie, a nie tylko czekać na wyrzucenie wyjątku (i złapany przez mój kod). Wygląda na to, że NHibernate generuje tylko wyjątek NHibernate.Exceptions.GenericADOException, który nie jest zbyt dobrze informatywny w odniesieniu do przyczyny wyjątku w tym przypadku. Czy może brakuje mi tutaj aspektu NHibernate?


14
2018-01-01 19:38


pochodzenie




Odpowiedzi:


Odpowiedź brzmi: jedno i drugie.

Jeśli twoja baza danych ma ograniczenia, może zagwarantować pewne niezmienniki dotyczące danych, takie jak wyjątkowość. Pomaga to na kilka sposobów:

  • Jeśli masz błąd w swoim aplikacja, naruszająca ograniczenie będzie oznaczało coś takiego w przeciwnym razie nie zostanie zauważony.

  • Inni użytkownicy bazy danych mogą zakładaj więcej o zachowaniu dane, jak DBMS wymusza niezmienniki.

  • Baza danych chroni się przed niepoprawne aktualizacje, które naruszają ograniczenia. Jeśli znajdziesz jakieś inne system lub interfejs zapełniający baza danych w dół ścieżki, ograniczenia egzekwowane przez bazę danych oznacza, że ​​wszystko złapane przez ograniczenia nie będą (lub przynajmniej jest mniej prawdopodobne) do złamania systemu.

Aplikacje i bazy danych żyją w relacji M: M w dowolnych, ale najbardziej trywialnych przypadkach. Aplikacja powinna nadal zawierać odpowiednie sprawdzenia poprawności danych i reguł biznesowych, ale nadal nie należy planować, aby aplikacja była jedynym klientem danych. Pracuj w hurtowni danych przez kilka lat, a zobaczysz efekty aplikacji zaprojektowanych przez ludzi z takim nastawieniem.


13
2018-01-01 19:49





Jeśli Twój projekt jest dobry (zarówno baza danych, jak i baza danych), baza danych nie powinna zawierać żadnych ograniczeń, które nie byłyby obsługiwane w interfejsie użytkownika - tzn. Nie należy przedstawiać bazy danych niespójnych danych. Ale nic nie jest doskonałe.

Odkryłem, że ograniczenie bazy danych do ograniczeń spójności danych pozwala mi obsłużyć wszystkie zatwierdzenia BL w kodzie proceduralnym, a jedyne przypadki, w których doświadczam wyjątków bazy danych, to błędy projektowania i kodowania, które mogą (i powinny być) naprawione.

W twoim przypadku sprawdzanie nazwy dla unikalności to sprawdzanie poprawności danych, poprawnie obsługiwane w kodzie. Który prawdopodobnie złapie błąd najbliższy punktu prowizji, gdzie masz nadzieję, że będziesz miał bardziej przyjazne zasoby interfejsu użytkownika, bez wprowadzania niepożądanego sprzężenia między abstrakcjami.


4
2018-01-01 22:59





Pozostawiłbym tę pracę całkowicie w bazie danych; Twój kod powinien skupiać się na przechwytywaniu i właściwej obsłudze wyjątku.

Powody:

  1. Wydajność- Baza danych będzie wysoce zoptymalizowany do egzekwowania ograniczenia w szybki i skuteczny droga. Nie będziesz miał czasu zoptymalizuj również swój kod.
  2. Łatwość utrzymania- Jeśli ograniczenia zmiany w przyszłości, nie będziesz mieć zmienić swój kod, a może ty będzie musiał po prostu dodać nowy połów {}. Jeśli ograniczenie zostanie usunięte, ty nie będzie musiał dotykać twojego kodu w wszystko.

3
2018-01-01 19:55



Niektóre aplikacje muszą powiedzieć użytkownikowi, co poszło nie tak. Jeśli chcesz wyjątek typu "Jest już użytkownik o nazwie" Joseph "" lub "Nazwa logowania" bw "jest już używana przez użytkownika" Bruce Willis "" lub cokolwiek innego, nie możesz tego zrobić po prostu catch handler, ponieważ nie masz wszystkich informacji lub jest to zbyt specyficzne dla bazy danych. - Stefan Steinegger


Jeśli chcesz sprawdzić ograniczenia samodzielnie, zrób to w warstwie dostępu do danych. Nic ponad tą warstwą nie powinno nic wiedzieć o twojej bazie danych ani jej ograniczeniach.

W większości przypadków powiedziałbym, że zostawię to w DAL, aby wychwycić wyjątki pochodzące od DB. Ale w twoim konkretnym przypadku myślę, że mówimy o podstawowej weryfikacji danych wejściowych. Przed wysłaniem całego formularza wybrałbym połączenie sprawdzające dostępność nazwy z bazą danych.


2
2018-01-01 19:53





Powinieneś zdecydowanie sprawdzić każdy wyjątek wyrzucony przez warstwę dostępu do danych. Problem z sprawdzeniem, czy istnieje rekord o tej samej wartości, wymaga zablokowania tabeli pod kątem modyfikacji, dopóki nie wstawisz nowego rekordu, aby zapobiec warunkom wyścigu.

Zazwyczaj zaleca się sprawdzenie wyjątków / błędów, nawet jeśli wcześniej wszystko sprawdziłeś. Prawie zawsze coś może pójść nie tak, lub nie zostało uwzględnione w kodzie, ale jest egzekwowane przez bazę danych.

Edytować: Jeśli dobrze rozumiem pytanie, to nie chodzi o to, czy ograniczenie powinno być egzekwowane przez bazę danych, czy nie, ale jak sobie z tym poradzić w kodzie aplikacji. Oczywiście, że powinieneś zawsze ustaw wszystkie ograniczenia w bazie danych, aby zapobiec wprowadzaniu złych danych do bazy danych.


1
2018-01-01 19:54



tak, masz mnie dobrze. Pytałem, czy mogę uniknąć podróży do bazy danych, aby sprawdzić duplikaty, gdy wiem, że wyjątek i tak zostanie odrzucony. - trendl
Ale aby sprawdzić, musisz również zapytać DB, więc musisz nawet wydać (przynajmniej) dwa zapytania: jeden do sprawdzenia i jeden do wstawienia / aktualizacji. Zakładając, że duplikaty są rzadkie, jest to nawet droższe niż próba wstawienia i przechwycenia wyjątku. - Simon Lehmann


Pytanie, na które musisz odpowiedzieć, brzmi:

"Czy muszę przedstawiać użytkownikowi ładne wiadomości". Przykład: Istnieje już zadanie o nazwie TestJob1. Jeśli odpowiedź jest Nie, po prostu złap błąd i przedstaw wspólny komunikat Jeśli odpowiedź jest tak, Czytaj dalej

Jeśli ty złap błąd po wstawieniu nie ma wystarczających informacji, aby przedstawić właściwy komunikat (przynajmniej w sposób agnostyczny)

Z drugiej strony może być Warunki wyścigu i możesz mieć jednoczesną transakcję próbującą wstawić te same dane, dlatego potrzebujesz Ograniczenie DB

Podejście, które działa dobrze, to:

  • sprawdź przed przedstawieniem ładnego wiadomość
  • wychwycić wyjątek i przedstawić wspólny komunikat o błędzie (zakładając, że tak się nie stanie często)

1
2018-01-15 15:06





Osobiście złapię wyjątek. To znacznie prostsze i wymaga znacznie mniej kodu.


0
2018-01-01 19:52





Wewnętrzny wyjątek GenericADOException wyjaśni, dlaczego akcja bazy danych nie powiodła się. Możesz złapać wyjątek OracleException / MSSQLException / [InsertCustomExceptionHere] i obsłużyć błąd z tej wiadomości. Jeśli chcesz przekazać to z powrotem do przodu (zakładając, że użytkownik jest tym, który wprowadził zduplikowane dane), możesz najpierw zawinąć je w niestandardowy wyjątek, aby nie łączyć przedniego interfejsu z bazą danych. W rzeczywistości nie chcesz przekazywać określonych wyjątków RDBMS.

Nie zgadzam się z sprawdzaniem db dla unikalności przed wykonaniem wstawki, dwukrotne przełączanie do bazy danych jest niezbyt wydajne iz pewnością nie jest skalowalne, jeśli masz duży ruch użytkowników.


0
2018-04-16 15:49