2012-04-24 11 views
0

IValidatableObject.Validateは、実装エンティティDbEntityEntry.Stateが "Unchanged"と異なる場合にのみ呼び出されます。ナビゲーションプロパティを変更しても状態は変わらないので、検証は行われません。IValidatableObjectはEFナビゲーションプロパティでは役に立たないですか?

マイクロソフトでは常にベーキングされたベータ版をリリースするのはなぜですか?

私も手でナビゲーションプロパティの変更を検出することはできません。

var changes = context.ChangeTracker.Entries() 
    .Where(e => e.State != EntityState.Unchanged) 
    .ToArray(); 

は空の配列を返します。

答えて

5

ここに興味深い点がいくつかあります。 EntityFrameworkは、エンティティの変更とは独立してナビゲーションプロパティの変更を追跡します。 context.ChangeTracker.Entries()は、エンティティの変更のみを返し、リレーションシップの変更は返しません。これはあなたがこれらを見ない理由です。あなたは本当に関係で見てみたいと、彼らはどのように変化するかを次のObjectContextに落下して行うことができる場合:

var objectContext = ((IObjectContextAdapter) ctx).ObjectContext; 
foreach(var relationshipEntry in objectContext.ObjectStateManager 
               .GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted) 
               .Where(e => e.IsRelationship)) 
{ 
    EntityKey entityKey1, entityKey2; 

    if (relationshipEntry.State == EntityState.Added) 
    { 
     entityKey1 = (EntityKey)relationshipEntry.CurrentValues[0]; 
     entityKey2 = (EntityKey)relationshipEntry.CurrentValues[1];    
    } 
    else 
    { 
     entityKey1 = (EntityKey)relationshipEntry.OriginalValues[0]; 
     entityKey2 = (EntityKey)relationshipEntry.OriginalValues[1];       
    } 

    var entity1 = objectContext.GetObjectByKey((EntityKey)entityKey1); 
    var entity2 = objectContext.GetObjectByKey((EntityKey)entityKey2); 
} 

あなたを再検証する必要があるとき1である私にはもっと面白いですシナリオ関係が変更されたときのエンティティ。私はあなたが外部キーを持っていないと仮定しています。そうしないと、ナビゲーションプロパティの変更によって外部キーの値が変更され、エンティティが変更されたものとしてマークされます。とにかく私は3つの有効なエンティティを持っているとします。変化する関係がエンティティ(またはモデル)を無効にするシナリオは何ですか?また、検証自体は、指定されたエンティティの検証のみですが、関連するエンティティを検証するためにナビゲーションプロパティに従うことはありません。あなたが本当に関係は私が考える変更されたときに実体を検証する必要がある場合 は、最後には4つのオプションがあります。変更の関係は(免責事項を修正されたエンティティをマークする必要があり、外部キーを変更するように外部キーを追加すること

  • 試し:I

  • DbContext.ShouldValidateEntity()メソッドをオーバーライドして、変更されたエンティティのみではなくすべてのエンティティを検証します(ここでフィルタリングロジックが行われます)。パフォーマンスに多少の悪影響が生じる可能性があることに注意してください。あなたはすべての修正エンティティのためとされているすべてのエンティティの検証を呼び出すように

 protected override bool ShouldValidateEntity(DbEntityEntry entityEntry) 
     { 
      return (entityEntry.State & EntityState.Deleted) == 0; 
     } 
  • オーバーライドDbContext.SaveChanges():ここでは、DbContextから派生クラスに追加する必要がありますコードです(上記のコードを使用すると、追加された関係エントリにのみ関心があります)

  • コレクションを変更すると、手動でエンティティを変更済みとしてマークします。それはあなたが追跡している、ちょうどあなたがここに検証し、検証のカスタマイズについての詳細を見つけることができるすべてが、削除されたエンティティ

を検証するためにはるかに安いかもしれどのように多くの実体に応じて、データベースに不要な更新を送信引き起こす可能性があることに注意してください: http://blogs.msdn.com/b/adonet/archive/2010/12/15/ef-feature-ctp5-validation.aspx http://blogs.msdn.com/b/adonet/archive/2011/05/27/ef-4-1-validation.aspx (はい、CTPとEF 4.1用ですが、

+0

多くの関係がある場合はどうなりますか?私はビジネス/オブジェクトルールを持っています。ブール値のプロパティAが真の場合、コレクションBは空ではないということです。これはオブジェクトレベルの検証の一部ではありませんか?私は別の場所でこれを行う必要がありますか? – springy76

+0

BTW:外部キーが追加されたので、ObjectStateManagerはこれ以上関係エントリを返しません(エンティティ自体、より正確には、外部キーのプロパティは予期したとおりに変更済みとマークされます)。 – springy76

+0

1- *は非常にこの文脈では面白いシナリオです。この理由は、コレクションにエンティティを追加したり削除したりすることは、実際にはエンティティに「1」側のエンティティ(つまりプリンシパル)に影響を与えません。データベースを見ると、対応するテーブルには外部キーはありませんそれらが存在することを知ることさえできません。ただし関連テーブルでは、プリンシパルを指し示す外部キーが追加される(または削除される)行があります(ただし、他の方法ではありません)。値が変更されていなければ、プリンシパルは本当に変更されましたか? – Pawel

関連する問題