2

DDDを使用して単純なドメインをモデル化しようとしています。データベースレイヤーはEntityFrameworkを使用して実装され、ドメインオブジェクトはPOCOです。ドメインには、FirstName、LastName、およびUsernameプロパティを持つUserエンティティがあります。したがって、ドメインはユーザーのリポジトリを処理するIRepositoryを定義します。

ドメインロジックの1つの要件は、同じユーザー名を持つ2人のユーザーが存在できないことです。したがって、同じユーザー名を持つ別のユーザーがすでに存在するときに新しいユーザーを追加しようとすると、例外がスローされます。

IUnitOfWork unitOfWork = new UnitOfWork();
IRepository<User> users = unitOfWork.Users;

User user1 = new User() { Username = "jsmith", FirstName = "John", LastName = "Smith" };
users.Add(user1);   
users.Save();       // ok, new user added to the underlying database

User user2 = new User() { Username = "jsmith", FirstName = "Jim", LastName = "Smith" };
users.Add(user2); // exception here?
users.Save();     // or exception here?

これは、新しいユーザーを追加するWPFアプリケーションに入力する必要があるコードの例です。ここで、UnitOfWorkはEntityFrameworkのDbContextオブジェクトをカプセル化します。

私の質問は、このドメインルールをどこでどのように適用する必要があるかです。ユーザーをリポジトリに追加しようとしたとき、またはSave()メソッドが呼び出されたときに、例外をスローする必要がありますか?新しいユーザーを追加するためのドメインサービスを作成し、そこですべてのドメインロジックルールを処理する必要がありますか?

また、どのような例外をスローする必要がありますか?DuplicateUserExceptionなどのカスタムドメイン例外を作成する必要がありますか?

4

2 に答える 2

2

データベースは、そのルールの最終的な施行者です。さて、これはマルチユーザーアプリですか?その場合、最も実用的な方法は、 db に依存し、SQL 例外をキャッチしてから、UI にリダイレクトされるビジネスルール例外をスローすることです (つまり、エラー メッセージをトリガーします)。

名前がドメイン レベルで既に存在することを確認できますが (サービスを使用するのが最も効率的な方法です)、これは同時実行環境では失敗する可能性があります。ただし、これはシングル ユーザー アプリ向けのエレガントでクリーンなソリューションです。シングル ユーザー アプリとは、すべてのアプリが一度に 1 人のユーザーにサービスを提供することを意味します。WPF クライアントと Web サービスがある場合、それはマルチ ユーザー アプリです。

あなたの最善の策は、永続性(この場合はデータベース)にこのルールを処理させることです。これは、名前の重複がないことを確認するのがレポの責任であるためです(リポジトリはダムバケットではなく、永続性のマネージャーです)。並行性の問題も。

データベースとの通信方法は問題ではないため、EF については触れていません。明日 Azure db に切り替える場合、ソリューションは同じであり、実装の特定の部分のみが異なります。

于 2012-06-25T10:52:59.493 に答える
1

ExecuteSqlCommand私が持っていた最高の幸運は、カスタム初期化子を使用し、次のように使用してデータベースでUNIQUECONSTRAINTを指定することです。

public class MyInitializer
  : DropCreateDatabaseIfModelChanges<MyContext>
  // Or whichever base class you want to use. DropCreateDatabaseAlways<>,
  // MigrateDatabaseToLatestVersion<>, etc. or even IDatabaseInitializer<>
{
  public void InitializeDatabase(MyContext context)
  {
    // other initialization
    context.Database.ExecuteSqlCommand("ALTER TABLE Users" +
                                       "ADD CONSTRAINT UQ_Users_Username " +
                                       "UNIQUE(Username)");
  }
}

これにより、ロジックデータベースがバインドされたままになります。メソッドを実装EntityTypeConfiguration<User>してチェックを実行することもValidateできますが、チェックするためだけに検証のたびにデータベースにpingを実行します。

于 2012-06-24T21:51:07.363 に答える