【问题标题】:Entity Framework Code First - Orphaning solutions?实体框架代码优先 - 孤立解决方案?
【发布时间】:2012-11-20 14:04:12
【问题描述】:

我已经搜索了很长时间,试图为 EF 中常见的孤立问题找到令人满意的解决方案。

最简单的孤立形式之一是清除实体集合。实体之间的关系已删除,但子实体仍保留在数据库中。

我的要求:-

  • 集合的清除发生在域中,我希望能够简单地调用 clear 而不是更多。
  • 任何判断父子关系是否被破坏导致删除的逻辑都需要封装在存储库/DbContext中。
  • 我不想为了解决这个问题而用任何额外的东西“弄脏”域。这包括反向引用。

我怀疑这无法解决,因为我已经花费了大量时间寻找解决方案,但我是出于希望而提出的!

我查看的区域是 ChangeTracker 和我可以挂钩的任何可能的事件,类似于在各个地方弹出的 AssociationChanged 事件。 DbContext 中的某处必须知道这种关系已被破坏。如何访问它,这是个问题?

谢谢。

【问题讨论】:

    标签: entity-framework-4.1 ef-code-first


    【解决方案1】:

    您可以尝试以下解决方案吗? Mb 它适合您的需求。必须在 DetectChanges 和 SaveChanges 方法之间调用 DeleteOrphans 扩展方法。

    public static class DbContextExtensions { private static readonly ConcurrentDictionary< EntityType, ReadOnlyDictionary< string, NavigationProperty>> s_navPropMappings = new ConcurrentDictionary< EntityType, ReadOnlyDictionary< string, NavigationProperty>>();

        public static void DeleteOrphans( this DbContext source )
        {
            var context = ((IObjectContextAdapter)source).ObjectContext;
            foreach (var entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified))
            {
                var entityType = entry.EntitySet.ElementType as EntityType;
                if (entityType == null)
                    continue;
    
                var navPropMap = s_navPropMappings.GetOrAdd(entityType, CreateNavigationPropertyMap);
                var props = entry.GetModifiedProperties().ToArray();
                foreach (var prop in props)
                {
                    NavigationProperty navProp;
                    if (!navPropMap.TryGetValue(prop, out navProp))
                        continue;
    
                    var related = entry.RelationshipManager.GetRelatedEnd(navProp.RelationshipType.FullName, navProp.ToEndMember.Name);
                    var enumerator = related.GetEnumerator();
                    if (enumerator.MoveNext() && enumerator.Current != null)
                        continue;
    
                    entry.Delete();
                    break;
                }
            }
        }
    
        private static ReadOnlyDictionary<string, NavigationProperty> CreateNavigationPropertyMap( EntityType type )
        {
            var result = type.NavigationProperties
                .Where(v => v.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
                .Where(v => v.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One || (v.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne && v.FromEndMember.GetEntityType() == v.ToEndMember.GetEntityType()))
                .Select(v => new { NavigationProperty = v, DependentProperties = v.GetDependentProperties().Take(2).ToArray() })
                .Where(v => v.DependentProperties.Length == 1)
                .ToDictionary(v => v.DependentProperties[0].Name, v => v.NavigationProperty);
    
            return new ReadOnlyDictionary<string, NavigationProperty>(result);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-01
      • 2014-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-29
      • 2012-05-31
      相关资源
      最近更新 更多