Oto scenariusz:Wskazówki dotyczące POCO Validation z ASP.NET MVC/Entity Framework
- ASP.NET Web Application MVC2
- Entity Framework 4 (Czysta poco jest kontekst danych klienta)
- Repository Wzór
- Jednostka tempo prac
- Dependency Injection
- usługi Warstwa pośrednicząca Controller -> Repository
W zasadzie wszystkie fajne rzeczy. :)
Przepływ zdarzeń dla podstawowych operacji UI ("Dodawanie post"):
- kontroler wzywa Dodaj (post) metodę na warstwie usług
- warstwa Usługa nazywa Dodaj (T) na repozytorium
- Repository połączeń AddObject (T) na zamówienie kontekstu danych
- Controller wywołuje Comm to() na jednostce pracy
Teraz próbuję ustalić, gdzie mogę umieścić moją walidację.
Na tym etapie muszę dwa rodzaje walidacji
- Prosty, niezależna walidacja POCO takie jak „post musi mieć tytuł”. Wydaje się to naturalne dopasowanie do Data Annotations na POCO.
- Kompleksowa walidacja biznesowa, np. "Nie można dodać komentarza do zablokowanego wpisu". Nie można tego zrobić za pomocą adnotacji danych.
Teraz Czytam „Programowanie Entity Framework, drugie wydanie” Julie Lerman (co jest doskonałe BTW) i zostały patrząc do podpinania do zdarzenia SavingChanges w celu przeprowadzenia „last minute” walidacja . Byłby to dobry sposób na zapewnienie sprawdzania poprawności: zawsze dzieje się za każdym razem, gdy robię "coś" (dodawanie, modyfikowanie, usuwanie), ale jest to również trochę spóźnione IMO (ponieważ elementy są już w menedżerze stanu) - więc co mogę zrobić zrobić, jeśli sprawdzanie poprawności nie powiedzie się, usunąć je?
Mogę oczywiście uczynić z mojego urządzenia POCO interfejs (powiedz "IValidatable") i wywołać metodę w tym interfejsie podczas tego wydarzenia.
Ale wydaje się, że "za późno" na walidację biznesu - czy to jest konsensus?
Po prostu szukam wskazówek tutaj, próbuję zaprojektować wielokrotnego użytku, inteligentny schemat sprawdzania poprawności złożonej logiki biznesowej, biorąc pod uwagę powyższą architekturę.
Innym krzywa-ball dla Ciebie - jak wiadomo, POCO na EF oznaczać POCO mają wszystkie właściwości na DB - więc może mieć „postID” własności, z get/set dostępowych (jako potrzeb EF aby uzyskać/ustawić te właściwości).
Ale problem polega na tym, że "PostID" to kolumna o nazwie , czyli jak chronić pole przed ustawieniem explicity? Np. Jeśli (z jakiegoś powodu) wykonaj następujące czynności:
var post = service.FindSingle(10);
post.PostId = 10;
unitOfWork.Commit();
Spowoduje to zgłoszenie wyjątku SqlException. Jak mogę temu zapobiec? Nie mogę "ukryć" właściwości (uczynić ją prywatną, a nawet wewnętrzną), ponieważ POCO są w osobnym zestawie do repozytorium.
Uwaga dotycząca sprawdzania poprawności - planuję utworzyć niestandardowe wyjątki (wynikające z wyjątku). Więc gdy sprawdzanie poprawności nie powiedzie się, muszę rzucić te wyjątki.
ten sposób mogę kodować coś takiego na moim kontrolera:
[HttpPost]
public ActionResult AddPost(Post post)
{
try
{
IUnitOfWork uow = new UnitOfWork();
postService.Add(post);
uow.Commit();
}
catch(InvalidPostOperation ipo)
{
// add error to viewmodel
}
}
będę musiał ręcznie zrobić walidacji na każdym razem warstwy usług i czy dodatek? Jak mogę sobie z tym poradzić? (jak to jest w jednostce pracy, a nie w warstwie usług).
Tak, aby temu zapobiec, że jest „wszędzie” kwestia, oto moje pytania:
- Prosta walidacja POCO - Należy to zrobić z danymi adnotacje? Plusy/minusy/Gotcha?
- W jakich okolicznościach (jeśli w ogóle) powinniśmy być podłączeni do zdarzenia zdarzenia Kontekstu danych EF w celu potwierdzenia?
- Gdzie powinienem wykonywać kompleksową walidację biznesową? W usłudze explicity lub metoda na POCO (którą mogę wywołać z usługi). Jak mogę stworzyć schemat inteligentnego/wielokrotnego użytku?
- Jak możemy "ukryć" automatycznie generowane właściwości POCO przed manipulowaniem?
Wszelkie myśli będą najbardziej cenione.
Przepraszam, jeśli ten wpis jest "zbyt długi", ale jest to ważny problem i można go rozwiązać na wiele sposobów, dlatego chciałem podać wszystkie informacje, aby uzyskać najlepszą możliwą odpowiedź.
Dzięki.
EDIT
Poniższa odpowiedź jest pomocne, ale nadal jestem (idealnie) szuka więcej myśli. Ktoś jeszcze?
Zbyt wiele pytań w jednym, ale jeśli chodzi o # 3, należy pamiętać, że sprawdzanie poprawności ma znaczenie kontekstowe (lub oparte na zadaniach). To kuszące, aby utworzyć własność 'IsValid' na twoim' Post', ale gdzieś po linii będziesz potrzebował 'IsValidForDraft', który jest używany do zapisywania wersji roboczych, które nie posiadają pewnych informacji. I na pewno POCO nie powinien być świadom pojęcia "projektu publikacji". :) – bzlm
Aw, daj spokój, dlaczego głosować, aby zamknąć? Rozumiem, że jest to "długie" pytanie. Ale właśnie dlatego mam 4 pytania na końcu. To, że pytam o 4 rzeczy, nie oznacza, że ten Q zasługuje na głos, by zamknąć to, że jest "zbyt ogólnikowy". Wszystkie 4 q odnoszą się do jednego tematu. – RPM1984
@bzlm - tak, rozumiesz. :) – RPM1984