8

ASP.NET MVC アプリケーションでデータベース制約 (UNIQUE など) の検証を行う最良の方法は何か、DDD を念頭に置いて構築するのに最適な方法は何だろうと思っています。基礎となる層はアプリケーション層 (アプリケーション サービス)、ドメイン層 (ドメイン モデル) です。およびインフラストラクチャ層 (永続化ロジック、ロギングなど)。

私は多くの DDD サンプルを調べてきましたが、それらの多くが言及していないのは、リポジトリで検証を行う方法です (このタイプの検証が適していると思います)。これを行っているサンプルを知っている場合は、それらを共有していただければ幸いです。

具体的には、2 つの質問があります。実際の検証をどのように実行しますか? データベースにクエリを実行して、顧客名が既に存在するかどうかを明示的に確認しますか?それとも、データベースに直接挿入してエラーがあればキャッチしますか? 私は最初のものを好みます。これを選択する場合、リポジトリで行うべきですか、それともアプリケーション サービスの仕事にするべきですか?

エラーが検出されたら、それを ASP.NET MVC にどのように渡して、ユーザーにエラーについて適切に通知できるようにしますか? ModelStateDictionaryエラーがフォーム上で簡単に強調表示されるように、を使用することをお勧めします。

Microsoft Spain による N-Lyered アプリでは、IValidatableObjectインターフェイスを使用し、次のような最も単純なプロパティ検証がエンティティ自体に配置されます。

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;
}

エンティティが永続化される前に、プロパティが有効であることを確認するために Validate メッセージが呼び出されます。

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));
}

次に、ApplicationValidationErrorsException を MVC アプリケーションでキャッチし、検証エラー メッセージを解析してModelStateDictionary.

すべての検証ロジックを SaveCustomer メソッドに追加できます。たとえば、特定の列 (UNIQUE 列) を使用して顧客が既に存在するかどうかを確認するデータベースをクエリします。おそらくこれで問題ありませんが、validator.IsValid(または同様のものが)私のためにこれを行うか、インフラストラクチャレイヤーで検証がもう一度実行されることを望みます(ここに属している場合はわかりません)。

どう思いますか?どのようにしますか?階層化されたアプリケーションのさまざまな検証手法について、より多くの洞察を得ることに非常に興味があります。


考えられる解決策 #1

検証ロジックをプレゼンテーション レイヤーで実行できず (Iulian Margarintescu が示唆するように)、サービス レイヤーで実行する必要がある場合、どのように検証エラーをプレゼンテーション レイヤーに渡しますか?

Microsoft はここで提案しています(リスト 5 を参照)。そのアプローチについてどう思いますか?

4

2 に答える 2

2

DDDについておっしゃっていますが、DDDにはエンティティやリポジトリよりもはるかに多くのものがあります。あなたはエリック・エバンス氏の著書「ドメイン駆動設計」に精通していると思います。戦略的設計と境界のあるコンテキストに関する章をもう一度読むことを強くお勧めします。また、エヴァンス氏は、ここで見つけることができる「本以来、私がDDDについて学んだこと」と呼ばれる非常に素晴らしい話をしています。GregYoungまたはUdiDahanによるSOA、CQRS、およびイベントソーシングに関する講演には、DDDおよびDDDの適用に関する多くの情報も含まれています。DDDの適用についての考え方を変えるものを発見する可能性があることを警告する必要があります。

検証についての質問ですが、1つのアプローチは、ユーザーが「名前」フィールドに何かを入力するとすぐにデータベースにクエリを実行し(アプリサービスに向けられたAjax呼び出しを使用して)、彼が入力したものはすでに存在します。ユーザーがフォームを送信したら、データベースにレコードを挿入し、重複するキーの例外を処理してみてください(リポジトリまたはアプリサービスレベルで)。事前に重複をチェックしているので、例外が発生することはかなりまれです。「申し訳ありませんが、再試行してください」という適切なメッセージが表示されます。これは、多くのユーザーがいない限り、おそらく決して表示されないためです。 。

Udi Dahanからのこの投稿には、検証への取り組みに関する情報も含まれています。これは、ビジネスが課す制約ではなく、ビジネスに課す制約である可能性があることを忘れないでください。おそらく、同じ名前の顧客を拒否するのではなく、登録できるようにすることで、ビジネスにより多くの価値がもたらされます。

また、DDDはテクノロジーよりもビジネスに重点を置いていることを忘れないでください。DDDを実行して、アプリを単一のアセンブリとしてデプロイできます。データベースの上にあるリポジトリの上にあるエンティティの上にあるサービスの上にあるクライアントコードのレイヤーは、それが良いデザインである理由なしに、「良い」デザインの名の下に何度も悪用されてきました。

これであなたの質問に答えられるかどうかはわかりませんが、自分で答えを見つけるためのガイドになることを願っています。

于 2012-05-02T02:59:19.993 に答える
0

データベースの制約 (UNIQUE など) の検証を行う最善の方法は何か疑問に思っています。

これを選択する場合、リポジトリで実行する必要がありますか?それともアプリケーション サービスのジョブにする必要がありますか?

それはあなたが検証しているものに依存します。

検証しようとしているのが集約ルートの作成である場合、それを「保持」するアプリ自体よりもグローバルなものはありません。この場合、検証をリポジトリに直接適用します。

エンティティの場合は、集約ルート コンテキストに存在します。この場合、この特定の集約ルート内の他のすべてのエンティティに対して、集約ルート自体のエンティティの一意性を検証しています。エンティティ/ルートの値オブジェクトについても同様です。

Ps リポジトリはサービスです。サービスを、必要だが適切に名前を付けるのが難しいコードのユニバーサル ストアと見なさないでください。ネーミングは重要です。同じことが、「ヘルパー」、「マネージャー」、「共通」、「ユーティリティ」などの名前にも当てはまります。これらはほとんど意味がありません。

また、パターン名でコード ベースを汚染する必要はありません: AllProducts > ProductRepository; OrderRegistrator > OrderService; order.isCompleted > IsOrderCompletedSpecification.IsSatisfiedBy.

具体的には、2 つの質問があります。実際の検証をどのように実行しますか? データベースにクエリを実行して、顧客名が既に存在するかどうかを明示的に確認しますか?それとも、データベースに直接挿入してエラーがあればキャッチしますか?

データベースにクエリを実行します。ただし、高パフォーマンスが懸念され、顧客名の可用性がデータベースで強制される唯一のものである場合は、データベースに依存することになります (ラウンド トリップが 1 回少なくなります)。

エラーが検出されたら、それを ASP.NET MVC にどのように渡して、ユーザーにエラーについて適切に通知できるようにしますか? フォーム上でエラーが簡単に強調表示されるように、ModelStateDictionary を使用することをお勧めします。

通常、アプリケーションのフローを制御するために例外を使用することはお勧めできませんが、UI に可能なことだけを表示するように強制したいので、検証が失敗した場合に備えて例外をスローしています。UIレイヤーには、きちんと拾ってhtmlに吐き出すハンドラーがあります。

また、コマンドの範囲を理解することも重要です (たとえば、製品注文コマンドは、顧客が債務者でないかどうか、および製品が店舗にあるかどうかという 2 つのことをチェックする場合があります)。コマンドに複数の検証が関連付けられている場合は、それらを結合して、UI がそれらを同時に受け取るようにする必要があります。そうしないと、煩わしいユーザーエクスペリエンスにつながります(その気の利いた製品を何度も注文しようとすると、複数のエラーが発生します).

于 2012-05-03T08:26:06.380 に答える