0

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

Microsoft が常に中途半端なベータ版をリリースするのはなぜですか?

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

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

空の配列を返します。

4

1 に答える 1

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

私にとってより興味深いシナリオは、関係が変化したときにエンティティを再検証する必要がある場合です。外部キーを持っていないと仮定します。そうしないと、ナビゲーション プロパティを変更すると外部キーの値が変更され、エンティティが変更済みとしてマークされるため、エンティティは変更済みとしてマークされます。とにかく、3 つの有効なエンティティがあることを考えると、関係を変更するとエンティティ (またはモデル) が無効になるシナリオは何ですか? また、検証自体は特定のエンティティを検証するだけであり、ナビゲーション プロパティに従って関連エンティティを検証することはありません。最後に、関係が変更されたときにエンティティを検証する必要がある場合は、次の 4 つのオプションがあると思います。

  • 外部キーを追加して、関係を変更するとエンティティが変更済みとしてマークされる外部キーが変更されるようにします(免責事項:私はそれを試していません)

  • DbContext.ShouldValidateEntity() メソッドをオーバーライドして、変更されたエンティティだけでなく、すべてのエンティティを検証します (ここでフィルタリング ロジックが発生します)。パフォーマンスに悪影響を及ぼす可能性があることに注意してください。DbContext から派生したクラスに追加する必要があるコードは次のとおりです。

        protected  override bool ShouldValidateEntity(DbEntityEntry entityEntry)
        {
            return (entityEntry.State & EntityState.Deleted) == 0;
        }
  • DbContext.SaveChanges() をオーバーライドして、変更されたすべてのエンティティと、変更された関係に関係するすべてのエンティティの検証を呼び出すようにします (上記のコードを使用すると、追加された関係エントリのみに関心がある可能性が高くなります)。

  • コレクションを手動で変更するときは、エンティティを変更済みとしてマークします。不要な更新をデータベースに送信する可能性があるため、追跡しているエンティティの数によっては、削除されたエンティティを除くすべてのエンティティを検証するだけではるかに安価になる可能性があることに注意してください

検証と検証のカスタマイズの詳細については、 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 用ですが、まだ保持されています)

于 2012-04-24T18:58:36.800 に答える