是否有更好/更清晰的方法来查找独立关联更改(添加/删除)?

时间:2014-08-20 09:11:30

标签: c# entity-framework many-to-many entity-framework-6

我发现this answer(除非我遗漏了某些内容)提供了一个很好的解决方案来捕获对DbContext中所有独立关联所做的所有更改。我正在尝试将该解决方案调整为更具体的内容,以创建可以在特定实体上查找特定导航属性的更改的函数。目标是让这个函数的用户不必担心EntityFramework的任何内部,而只关心他的POCO模型。

这是我到目前为止所做的,并且它有效。但在我看来,如果实体框架的内部实现细节发生变化,它看起来非常混乱并容易中断 - 特别是那里有一个“魔术字符串”"ClrPropertyInfo",可能不是EF接口合同的一部分。 / p>

public partial class EntityFrameworkMaterializer
{
    public IEnumerable<T2> GetAssociationChanges<T1,T2>(T1 parent, string propertyName, EntityState findState)
    {
        // this.context is a DbContext instance that is a property of the object.
        ObjectContext ocontext = ((IObjectContextAdapter)this.context).ObjectContext;
        MetadataWorkspace metadataWorkspace = ocontext.MetadataWorkspace;

        // Find the AssociationType that matches the property traits given as input            
        AssociationType atype =
            metadataWorkspace.GetItems<AssociationType>(DataSpace.CSpace)
            .Where(a => a.AssociationEndMembers.Any(
                ae => ae.MetadataProperties.Any(mp => mp.Name == "ClrPropertyInfo" // Magic string!!!
                    && ((PropertyInfo)mp.Value).Name == propertyName
                    && typeof(T1).IsAssignableFrom(((PropertyInfo)mp.Value).DeclaringType)
                    )
                    )
                    ).First();

        // Find added or deleted DbDataRecords from the above discovered type
        ocontext.DetectChanges();
        IEnumerable<DbDataRecord> dbDataRecords = ocontext.ObjectStateManager
            .GetObjectStateEntries(findState)
            .Where(e => e.IsRelationship)
            // Oddly, this works, while doing the same thing below requires comparing .Name...?
            .Where(e => e.EntitySet.ElementType == atype)
            .Select(e => findState == EntityState.Deleted ? e.OriginalValues : e.CurrentValues);

        // Get the actual entities using the EntityKeys in the DbDataRecord
        IList<T2> relationChanges = new List<T2>();
        foreach (System.Data.Common.DbDataRecord ddr in dbDataRecords)
        {
            EntityKey ek = (EntityKey)ddr[0];
            // Comparing .ElementType to atype doesn't work, see above...?
            if (!(ek.GetEntitySet(metadataWorkspace).ElementType.Name == atype.Name))
            {
                ek = (EntityKey)ddr[1];
            }
            relationChanges.Add((T2)ocontext.GetObjectByKey(ek));
        }
        return relationChanges;
    }
}

使用示例:

// Student <--> Course is many-to-many Independent Association
IEnumerable<Course> droppedCourses;
droppedCourses = GetAssociationChanges<Student, Course>(
    student,
    "EnrolledCourses",
    EntityState.Deleted
);

这是在调试器中进行大量逆向工程和挖掘对象的结果。除了魔术字符串问题之外,我想知道是否有更直接的途径来根据“结束”实体类型和导航属性名称来确定代表IAs的“关系条目”的类型。

0 个答案:

没有答案