实体框架5循环延迟加载导致OutOfMemoryException

时间:2013-03-16 23:19:19

标签: lazy-loading json.net entity-framework-5 automapper

我遇到了EF 5和Lazy加载循环引用的问题。

下图代表我的模特。 enter image description here

主要问题是Model和ModelProperties类之间,因为Model包含IEnumerable导航属性而ModelProperty包含Model导航属性。

所以这个设计会导致下面的情况 enter image description here

您可以访问完整图片http://tinypic.com/r/2vskuxl/6

你可以想象这会引起很大的问题,OutOfMemory异常。

我唯一能找到的解决方案是禁用延迟加载和使用其他方法。但延迟加载非常简化我们的工作。 我希望有一个配置或属性来帮助我只加载延迟加载的两个级别的关系。

有没有办法实现这个目标?

更新 关于Julie Lerman的请求,这里是EF的视觉模型。 我强调了导致问题的主要关系。 enter image description here 您也可以在http://tinypic.com/r/30v15pg/6

访问完整尺寸

更新2: 这是模型定义。

public class Model {
        public int ModelID { get; set; }
        public int BrandID {
            get;
            set;
        }
        public virtual Brand Brand { get; set; }
        public string Logo { get; set; }
        public string Name { get; set; }
        public virtual ICollection<ModelProperty> ModelProperties {
            get;
            set;
        }
}

public class ModelProperty {

    public int ModelPropertyID {
        get;
        set;
    }

    public virtual int PropertyDefinitionID {
        get;
        set;
    }

    public virtual PropertyDefinition PropertyDefinition {
        get;
        set;
    }

    public virtual int ModelID {
        get;
        set;
    }

    public virtual Model Model {
        get;
        set;
    }

    public bool IsContainable {
        get;
        set;
    }

    public bool HasFilterDefinition {
        get;
        set;
    }

    public virtual ICollection<ModelPropertyValue> ModelPropertyValues {
        get;
        set;
    }

    public virtual ICollection<ModelPropertyMatchingFilter> ModelPropertyMatchingFilter {
        get;
        set;
    }
}

还有ModelProperty的实体配置。

 public class ModelPropertyEntityTypeConfiguration : EntityTypeConfiguration<ModelProperty> {
        public ModelPropertyEntityTypeConfiguration() {
            HasKey(p => p.ModelPropertyID);

            HasRequired(p => p.PropertyDefinition).WithMany(s => s.ModelProperties).HasForeignKey(s => s.PropertyDefinitionID).WillCascadeOnDelete(false);
            HasRequired(p => p.Model).WithMany(s => s.ModelProperties).HasForeignKey(s => s.ModelID).WillCascadeOnDelete(false);
            HasMany(p => p.ModelPropertyValues).WithRequired(s => s.ModelProperty).HasForeignKey(s => s.ModelPropertyID).WillCascadeOnDelete(true); 
            HasMany(p => p.ModelPropertyMatchingFilter).WithRequired(s => s.ContainerModelProperty).HasForeignKey(s => s.ContainerModelPropertyID).WillCascadeOnDelete(false);
            ToTable("dbo.ModelProperties");
        }
    }

更新3: 我不确定,但Automapper也会导致这种情况。因为实体框架配置文件告诉了在运行时调用的数千个Autommaper方法。

更新4: 这是EFProf堆栈跟踪: enter image description here 您可以访问更大的版本http://tinypic.com/r/21cazv4/6

更新5 您可以在此处查看示例项目:https://github.com/bahadirarslan/AutomapperCircularReference 在示例中,您可以通过快速监视轻松看到无限循环。

2 个答案:

答案 0 :(得分:1)

感谢您的更新。你的模特看起来很好。它绝对知道这只是一个1:*的关系。 Ladislav(像往常一样)是正确的。 LL不会导致问题......除了在序列化过程中的一个地方。您是否有机会在服务中使用您的代码?使用常规延迟加载,只有您明确提到的属性才会延迟加载。但是在序列化期间,序列化“提及”每个属性,因此它只是在整个图形中保持加载和加载属性并导致循环依赖性问题。对于服务,我们必须在返回数据之前关闭延迟加载(使用context.configuration.lazyloadingenabled = false)。因此,在服务方法中,您可以急切加载或延迟加载或显式加载以获取图形,但在返回结果之前禁用延迟加载。

答案 1 :(得分:1)

您应该禁用延迟加载以绕过代理对象,或者您应该返回DTO所需的内容。使用DTO是首选,因为隐藏了域名的详细信息