IValidatableObject是无用的EF导航属性? [英] IValidatableObject is useless for EF navigation properties?

查看:262
本文介绍了IValidatableObject是无用的EF导航属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

IValidatableObject.Validate只有被调用时,执行实体DbEntityEntry.State不同于不变。而只是改变导航属性不会改变的状态,因此在验证时不会发生。

IValidatableObject.Validate only gets called when the implementing entities DbEntityEntry.State differs from "Unchanged". And just changing a navigation property won't change the state and so the validation will never occur.

为什么微软经常发布半生不熟的测试版的东西?

Why Microsoft always releases half-baked beta things?

我甚至无法检测的导航属性变化着:<​​/ P>

I cannot even detect the navigation property change by hand:

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

返回一个空数组。

Returns an empty array.

推荐答案

这里有一些有趣的点。的EntityFramework跟踪更改导航属性独立的改变实体。 context.ChangeTracker.Entries()只返回变为实体,而不是关系。这就是为什么你看不到这些的原因。如果你真的想看看的关系,以及他们如何改变了你可以下降到ObjectContext中并执行以下操作:

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

这是更有趣的对我的情况是,当你需要重新验证你的实体时的关系的变化之一。我认为你没有外键 - 否则你的实体将被标记为已修改为改变导航亲preRTY会改变外键从而改性将标志着实体的价值。反正因为我有三个有效的实体 - 什么是场景变化的关系可以使实体(或模型)无效?此外,请注意验证本身是唯一的验证给定的实体,但从来没有如下的导航性能,以验证相关实体。 最后,如​​果你真的需要验证实体的关系时,改变我认为你有4个选项:

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)

覆盖DbContext.ShouldValidateEntity()方法来验证所有的实体,而不是只修改那些(这是哪里的筛选逻辑发生)。注意,它可能对性能有一些负面影响。这里是code,你将需要添加到您的类从的DbContext派生:

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

  • 覆盖DbContext.SaveChanges(),这样你调用验证所有修改的实体和参与修改的关系,所有的实体(使用上面的code,你最有可能只对关系条目已加入)

    • 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

      您可以找到有关验证和确认定制这里更多的细节: <一href="http://blogs.msdn.com/b/adonet/archive/2010/12/15/ef-feature-ctp5-validation.aspx">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,但它坎持有)

      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)

      这篇关于IValidatableObject是无用的EF导航属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆