2

カスタム EFContextProviderについて読んで実装した後も、サーバー側の検証を実行する最良の方法と、保存する前にビジネス ルールを適用する方法を理解しようとしています...つまり、私の質問は、本来あるべき 2 つのメソッドを中心に展開しています。オーバーライド:

  • protected override bool BeforeSaveEntity(EntityInfo entityInfo) { //}
  • protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap) { // }

ドキュメントでは、「 BeforeSaveEntities メソッドが一度呼び出される前に、すべてのエンティティに対して BeforeSaveEntity メソッドが呼び出される」と指定されていることを認識しています。また、私が持っている質問は、ドメイン固有の関係を持つ複数のエンティティに対するビジネス ルールの検証/適用に関するものであり、必ずしも単一のエンティティのプロパティを検証するわけではありません (そのため、ここで説明したようにカスタム検証が機能すると思います) 。

だから私の質問は:

  1. サーバーから検証エラーを返すにはどうすればよいですか? ビジネス ルールを適用したら、それらが失敗した場合、1 つ以上のエンティティに検証エラーを追加するにはどうすればよいですか?
  2. サーバー側のコードがどのビジネスルールを適用するかを「認識」できるように、ある種の検証コンテキストを渡すにはどうすればよいですか? 私のアプリケーションは、いくつかの異なる場所に新しい顧客を追加できます。アプリのコンテキストに基づいて、ビジネス ルールを適用するか、オプションにする必要があります。たとえば、明示的な「新規顧客の追加」画面と、「オンザフライ」で新しい顧客を作成できる「印刷チェック」画面がある場合 (この場合、より多くのルールをチェックする必要があります)。これは望ましい設計ではないかもしれませんが、要件です。顧客を作成できる場所は他にもほとんどありません....サーバー側では、ビジネスルールを適用する方法(および順序)を決定するために、この「コンテキスト」を取得しません...さらに、

ありがとうZ...

4

2 に答える 2

2

Breeze は、保存中に .NET Validation 属性を使用して登録済みの検証を実行します。以下は、エンティティ レベルとプロパティ レベルの両方で検証属性を適用する例です。これらの検証はいずれも Customer オブジェクトの保存中に実行され、検証エラーは SaveChanges 'fail' で返されます。約束。ただし、現時点では、エラー結果を調べて、結果のエラーを正しいエンティティ/プロパティに添付する必要があります。

[AttributeUsage(AttributeTargets.Class)] // NEW
public class CustomerValidator : ValidationAttribute {
  public override Boolean IsValid(Object value) {
    var cust = value as Customer;
    if (cust != null && cust.CompanyName.ToLower() == "xxx") {
      ErrorMessage = "This customer is not valid!";
      return false;
    }
    return true;
  }
}

[AttributeUsage(AttributeTargets.Property)]
public class ContactNameValidator : ValidationAttribute {
  public override Boolean IsValid(Object value) {
    try {
      var val = (string)value;
      if (!string.IsNullOrEmpty(val) && val.StartsWith("xxx")) {
        ErrorMessage = "{0} should not start with 'xxx'"";
        return false;
      }
      return true;
    } catch (Exception e) {
      var x = e;
      return false;
    }
  }
}

[MetadataType(typeof(CustomerMetaData))]
[CustomerValidator]
public partial class Customer {

  [ContactNameValidator]
  public string ContactName {
    get;
    set;
  }
}
于 2013-06-05T17:22:52.417 に答える
1

1) 通常、「カスタム」検証エラーをサーバーからクライアントに返す最も簡単な方法は、サーバーで単純にエラーをスローすることです。私が試したことはありませんが、うまくいくと思うのは、そのエラーを特定のエンティティに適用したい場合は、失敗したエンティティ/エンティティの EntityKey を含むプロパティを含む例外を作成し、この例外をスローすることです。クライアントでは、約束失敗ブランチでこのエラーを取得し、特定のエンティティに検証エラーを自分で適用できるはずです。(ちなみに、このプロセスを簡単にするための Breeze への機能要求は妥当なように思えます。コミュニティの関心を評価できるように、 Breeze User Voiceに投稿してください。)

2) 「コンテキスト」を保存に適用するには、2 つの方法があります。最も簡単な方法は、SaveOptions.tagプロパティを使用することです。このプロパティはクライアントで設定でき、SaveOptions プロパティを介して ContextProvider 内で使用するためにサーバーで逆シリアル化されます。(このようなもの):

 public class NorthwindContextProvider : EFContextProvider<NorthwindIBContext_EDMX_2012> {

    protected override bool BeforeSaveEntity(EntityInfo entityInfo) {
       if ((string)SaveOptions.Tag == "myCustomSaveSetting") {

       }
    }

もう 1 つの方法は、保存の「バージョン」ごとに完全に別個のエンドポイントを作成することです。これは、 SaveOptionsインスタンスの「resourceName」プロパティを介して行うことができます。

 var so = new SaveOptions({ resourceName: "MyCustomSave" });
 return myEntityManager.saveChanges(null, so);

標準の「SaveChanges」メソッドではなく、「MyCustomSave」コントローラ メソッドに移動します。すなわち

public class NorthwindIBModelController : ApiController {

    [HttpPost]
    public SaveResult MyCustomSave(JObject saveBundle) {
        ContextProvider.BeforeSaveEntitiesDelegate = MyCustomBeforeSaveEntities;
        return ContextProvider.SaveChanges(saveBundle);
    }

    private Dictionary<Type, List<EntityInfo>> MyCustomBeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap) {     
        // your code...
    }
 }
于 2013-06-05T00:11:44.230 に答える