2009-08-08 4 views
0

Ich habe zwei Tabellen in meiner Datenbank:Was ist die eleganteste Methode zum Implementieren einer Geschäftsregel für eine untergeordnete Sammlung in LINQ?

Wiki 
    WikiId 
    ... 

WikiUser 
    WikiUserId (PK) 
    WikiId 
    UserId 
    IsOwner 
    ... 

Diese Tabellen haben eine (Wiki) zu viele (WikiUser) Beziehung.

Wie würde ich das folgende Geschäftsregel in meinem LINQ Entitätsklassen implementieren:

„Ein Wiki muss einen Eigentümer haben genau?“

Ich habe versucht, die Tabellen zu aktualisieren, wie folgt:

Wiki 
    WikiId (PK) 
    OwnerId (FK to WikiUser) 
    ... 

WikiUser 
    WikiUserId (PK) 
    WikiId 
    UserId 
    ... 

Dies erzwingt die Einschränkung, aber wenn ich das aus der WikiUser Sammlung Wiki WikiUser Aufzeichnung des Besitzers entfernen, Ich erhalte eine hässliche SqlException. Dies scheint so zu sein, als wäre es schwierig, in der Benutzeroberfläche zu erfassen und zu handhaben.

Gibt es eine Möglichkeit, diese Überprüfung durchzuführen, bevor die SqlException generiert wird? Eine bessere Möglichkeit, meine Datenbank zu strukturieren? Eine Möglichkeit, die SqlException abzufangen und in etwas Nützlicheres zu übersetzen?

Edit: Ich würde es vorziehen, die Validierungsregeln innerhalb der LINQ-Entitätsklassen wenn möglich zu halten.

Edit 2: Einige weitere Details über meine spezifische Situation.

In meiner Anwendung sollte der Benutzer in der Lage sein, Benutzer aus dem Wiki zu entfernen. Sie sollten in der Lage sein, jeden Benutzer zu entfernen, mit Ausnahme des Benutzers, der derzeit als "Besitzer" des Wikis markiert ist (ein Wiki muss immer genau einen Besitzer haben).

In meiner Steuerlogik, würde Ich mag so etwas verwenden:

wiki.WikiUsers.Remove(wikiUser); 
mRepository.Save(); 

Und irgendwelche gebrochen auf die UI-Ebene übertragen Regeln.

Was ich will nicht zu tun haben, ist dies:

if(wikiUser.WikiUserId != wiki.OwnerId) { 
    wiki.WikiUsers.Remove(wikiUser); 
    mRepository.Save(); 
} 
else { 
    //Handle errors. 
} 

ich auch nicht besonders wollen, den Code zu meinem Repository bewegen (weil es nichts gibt, um anzuzeigen, nicht die native zu verwenden entfernen Funktionen), so dass ich nicht auch wie dieser Code wollen:

mRepository.RemoveWikiUser(wiki, wikiUser) 
mRepository.Save(); 

diese akzeptabel wäre:

try { 
    wiki.WikiUsers.Remove(wikiUser); 
    mRepository.Save(); 
} 
catch(ValidationException ve) { 
    //Display ve.Message 
} 

Aber das fängt zu viele Fehler:

try { 
    wiki.WikiUsers.Remove(wikiUser); 
    mRepository.Save(); 
} 
catch(SqlException se) { 
    //Display se.Message 
} 

Ich würde es vorziehen, nicht auch explizit eine Geschäftsregelprüfung zu nennen (obwohl es notwendig sein kann):

wiki.WIkiUsers.Remove(wikiUser); 
if(wiki.CheckRules()) { 
    mRepository.Save(); 
} 
else { 
    //Display broken rules 
} 

Antwort

0

Diese Frage Abhängigkeiten hat zu viele zu beantworten Nun, die größte davon ist, wo Sie die Geschäftsregeln insgesamt durchsetzen wollen. In der Reihenfolge der Präferenz müssen Sie fragen: Haben Sie einen Business Rule Layer? Wenn nicht, haben Sie eine unabhängige Datenzugriffsebene? Wenn nicht, verwenden Sie ein Datenanbietermodell?Wenn nicht, dann versuchen Sie, dies zu erzwingen (oder die SqlException zu behandeln), wo auch immer Sie die Konfigurationsoberfläche bearbeiten.

Für so etwas wie ein Wiki brauchen Sie wahrscheinlich keine sehr komplexe Business-Rule-Engine, nur weil Ihre Problemdomäne schon ziemlich eingeschränkt ist. Auch das klingt nach einer Art Regel, die sich so gut wie nie ändert, also ist es etwas übertrieben, sie in einer formalen Regelebene zu isolieren. Daher empfiehlt es sich, diese Art von Einschränkung in der Datenschicht oder im Datenanbieter zu verwenden. Wenn Sie beispielsweise Linq to Sql verwenden, können Sie das widerspiegeln, was Sie in SQL Server getan haben, indem Sie die OwnerId-Eigenschaft in Ihrem Modell als nicht Nullable-Eigenschaft festlegen, die durch eine Beziehung zur WikiUser-Tabelle gebunden ist. Dadurch wird erzwungen, dass die OwnerId-Eigenschaft ausgefüllt wird (da keine Nullwerte zulässig sind), und Sie erhalten die eindeutige Einschränkung, nach der Sie suchen.

+0

Meine Präferenz wäre die Validierung innerhalb der LINQ-Objekte. Bevor ich dieses Thema anschaute, hatte ich geplant, mich auf OnValidate zu stützen. – AaronSieb

+0

Das Hauptproblem tritt auf, wenn ich einen WikiUser aus der Wiki-Sammlung des Wikis entferne (mit anderen Worten, wenn ich einen WikiUser lösche). Es ist an diesem Punkt, dass ich die SqlException erhalte, und lieber etwas gezielter erhalten würde. – AaronSieb

+0

Passiert das für alle Benutzer oder nur den Besitzer? Was möchten Sie tun, wenn der Besitzer gelöscht wird? Sollte dieser Vorgang verhindert werden oder sollte die OwnerId einfach auf Null gesetzt werden? –

Verwandte Themen