IValidatableObject is useless for EF navigation properties?

风格不统一 提交于 2019-12-01 14:08:11

There are a few interesting points here. EntityFramework tracks changes to navigation properties independently on the changes to entities. context.ChangeTracker.Entries() returns only changes to entities and not to relationships. This is the reason why you don't see these. If you really want to look at relationships and how they changed you can drop down to the ObjectContext and do the following:

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

The scenario that is more interesting to me is the one when you need to re-validate your entity when the relationship changes. I assume that you don't have foreign keys - otherwise your entity would have been marked as modified as changing the navigation proprerty would change the value of the foreign key which in turn would mark the entity as modified. Anyways given that I have three valid entities - what is the scenario where changing relationships could make the entity (or the model) invalid? Also, note that validation by itself is only validating the given entity but never follows navigation properties to validate related entities. Finally if you really need to validate entities when relationships change I think you have 4 options:

  • try adding foreign keys so that changing relationships will change the foreign key which should mark the entity as modified (disclaimer: I have not tried that)

  • override DbContext.ShouldValidateEntity() method to validate all the entities instead of only modified ones (this is where the filtering logic happens). Note that it may have some negative impact on performance. Here is the code you would need to add to your class derived from DbContext:

        protected  override bool ShouldValidateEntity(DbEntityEntry entityEntry)
        {
            return (entityEntry.State & EntityState.Deleted) == 0;
        }
  • override DbContext.SaveChanges() so that you invoke validation for all modified entities and for all entities that are involved in modified relationships (use the code above, you are most likely only interested in relationship entries that have been added)

  • when you modify a collection manually mark the entity as modified. Note that it may cause sending unneeded updates to the database so depending on how many entities you are tracking it may be much cheaper just to validate all but deleted entities

You can find more details about validation and validation customization here: 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 (Yes it's for the CTP and EF 4.1 but it sill holds)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!