Ich frage mich, was ist der beste Weg, um die Validierung von Datenbankbeschränkungen (z.B. UNIQUE) in einer ASP.NET MVC-Anwendung zu tun, bauen mit DDD im Verstand, wo die zugrunde liegenden Schichten sind Application Layer (Anwendungsdienste), Domain Layer (Domain-Modell) und Infrastructure Layer (Persistenz-Logik, Protokollierung, etc.).
Ich habe mir viele DDD-Beispiele angeschaut, aber viele von ihnen erwähnen nicht, wie man die Validierung im Repository durchführt (ich nehme an, dass diese Art der Validierung hierher passt). Wenn Sie von irgendwelchen Beispielen wissen, die dies tun, bitte teilen Sie sie es wird sehr geschätzt werden.
Genauer gesagt, habe ich zwei Fragen. Wie würden Sie die eigentliche Validierung durchführen? Würden Sie explizit prüfen, ob ein Kundenname bereits vorhanden ist, indem Sie die Datenbank abfragen, oder würden Sie versuchen, ihn direkt in die Datenbank einzufügen und den Fehler abzufangen, falls es einen gibt (scheint unübersichtlich)? Ich bevorzuge die erste Variante, und wenn ich mich dafür entscheide, sollte dies im Repository geschehen oder sollte es die Aufgabe eines Anwendungsdienstes sein?
Wenn der Fehler erkannt wird, wie würden Sie es an ASP.NET MVC übergeben, so dass der Benutzer freundlich über den Fehler informiert werden kann? Vorzugsweise unter Verwendung der ModelStateDictionary
so dass der Fehler auf dem Formular leicht zu erkennen ist.
In der N-Lyered-App von Microsoft Spanien wird die IValidatableObject
Schnittstelle und die einfachste Eigenschaftsüberprüfung wird an der Entität selbst vorgenommen, wie z. B.:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var validationResults = new List<ValidationResult>();
if (String.IsNullOrWhiteSpace(this.FirstName))
validationResults.Add(new ValidationResult(Messages.validation_CustomerFirstNameCannotBeNull, new string[] { "FirstName" }));
return validationResults;
}
Bevor die Entität persistiert wird, wird die Nachricht Validate aufgerufen, um sicherzustellen, dass die Eigenschaften gültig sind:
void SaveCustomer(Customer customer)
{
var validator = EntityValidatorFactory.CreateValidator();
if (validator.IsValid(customer)) //if customer is valid
{
_customerRepository.Add(customer);
_customerRepository.UnitOfWork.Commit();
}
else
throw new ApplicationValidationErrorsException(validator.GetInvalidMessages<Customer>(customer));
}
Die ApplicationValidationErrorsException kann dann in der MVC-Anwendung abgefangen werden und die Validierungsfehlermeldungen können geparst und in die ModelStateDictionary
.
Ich könnte die gesamte Validierungslogik in die SaveCustomer-Methode einbauen, z. B. die Abfrage der Datenbank, um zu prüfen, ob ein Kunde bereits in einer bestimmten Spalte (der UNIQUE-Spalte) existiert. Vielleicht ist das in Ordnung, aber ich würde es vorziehen, dass die validator.IsValid
(oder etwas Ähnliches) würde dies für mich tun, oder dass die Validierung noch einmal in der Infrastrukturschicht durchgeführt wird (wenn es hierher gehört, bin ich nicht sicher).
Was meinen Sie dazu? Wie machen Sie das? Ich bin sehr daran interessiert, mehr Einblick in verschiedene Validierungstechniken bei mehrschichtigen Anwendungen zu erhalten.
Mögliche Lösung #1
Wenn die Validierungslogik nicht in der Präsentationsschicht durchgeführt werden kann (wie Iulian Margarintescu vorschlägt) und in der Serviceschicht durchgeführt werden muss, wie würden Sie Validierungsfehler an die Präsentationsschicht weitergeben?
Microsoft hat einen Vorschlag aquí (siehe Liste 5). Was halten Sie von diesem Ansatz?