【问题标题】:Entity framework lazy loading not working in 1..* unidirectional relationship实体框架延迟加载在 1..* 单向关系中不起作用
【发布时间】:2016-08-10 12:17:41
【问题描述】:

我有以下实体

public class A
{
    public int AId {get; set;}
}

public class B
{
    public int BId {get; set;}
    public virtual A Child1 {get; set;}
    public virtual A Child2 {get; set;}
}

使用以下配置

modelBuilder.Entity<B>()
            .HasRequired(x => x.Child1)
            .WithMany()
            .Map(x => x.MapKey("Child1Id"))

modelBuilder.Entity<B>()
            .HasRequired(x => x.Child2)
            .WithMany()
            .Map(x => x.MapKey("Child2Id"))

由于某种原因,实体框架在请求对象 B 的实体时不会延迟加载 Child1 或 Child2 属性。即

var b1 = context.Bs.FirstOrDefault();
Assert.IsNull(b.Child1) // true
Assert.IsNull(b.Child2) // true

但如果我明确加载它们,它会起作用。

var b2 = context.Bs.Include(x => x.Child1).Include(x => x.Child2).FirstOrDefault();
Assert.NotNull(b2.Child1) // true
Assert.NotNull(b2.Child2) // true

有谁知道为什么属性没有延迟加载?

编辑

好像

context.Bs.FirstOrDefault()

返回实体本身而不是代理类型。这表明该物业 ProxyCreationEnabled 是 false,但我已经仔细检查过它并设置为 true。

编辑 2

好的,终于找到问题了。我已将 Bs 构造函数设置为私有,这当然使得无法使用代理类扩展对象。因此,导航属性设置为 null。

【问题讨论】:

  • 他们已经被延迟加载......因为他们不存在(延迟部分)
  • 阅读这篇精彩的文章loading entities from msdn
  • 不存在属性,如果我在查询中明确包含它们,它就可以工作。
  • 您是否在 EF 选项中启用了延迟加载?
  • 是的,它已启用。

标签: c# entity-framework entity-framework-6 lazy-loading


【解决方案1】:

我已经修改了您的代码,以便使用延迟加载。只需复制粘贴,一切都会好起来的。

在写行之前用 VS 检查 b1,你会看到延迟加载的对象,不要害怕长实体名称,因为我已经启用了代理创建。

 public class Program
 {
     public static void Main(string[] args)
     {
         Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>());

         using (var myDbContext = new MyDbContext("DefaultConnection"))
         {
             var a1 = new A();
             var a2 = new A();

             var b1 = new B
             {
                 Child1 = a1,
                 Child2 = a2
             };

             myDbContext.Bs.Add(b1);
             myDbContext.SaveChanges();
         }

         using (var myDbContext = new MyDbContext("DefaultConnection"))
         {
             var b1 = myDbContext.Bs.FirstOrDefault();
             b1.ToString();
             Console.WriteLine(b1.ToString());
         }
     }

     public class A
     {
         public int AId { get; set; }
     }

     public class B
     {
         public int BId { get; set; }
         public virtual A Child1 { get; set; }
         public virtual A Child2 { get; set; }
     }

     public class MyDbContext : DbContext
     {
         public DbSet<A> As { get; set; }
         public DbSet<B> Bs { get; set; }

         protected override void OnModelCreating(DbModelBuilder modelBuilder)
         {
             modelBuilder.Entity<B>()
                 .HasRequired(x => x.Child1)
                 .WithMany()
                 .Map(x => x.MapKey("Child1Id")).WillCascadeOnDelete(false);

             modelBuilder.Entity<B>()
                 .HasRequired(x => x.Child2)
                 .WithMany()
                 .Map(x => x.MapKey("Child2Id")).WillCascadeOnDelete(false);

             base.OnModelCreating(modelBuilder);
         }

         public MyDbContext(string connectionString)
           : base("name=" + connectionString)
         {
             this.Configuration.LazyLoadingEnabled = true;
             this.Configuration.ProxyCreationEnabled = true;
         }
     }
 }

【讨论】:

  • 我会在 Visual Studio 更新后立即尝试。但默认情况下 ProxyCreationEnabled 不是 true 吗?
  • 是的,正确的 100% 我刚刚添加以确保您没有在某处禁用代理,因为如果您设置 ProxyCreationEnabled = false,此方法将无法正常工作
  • 这很奇怪,因为您的示例运行良好,但我的代码没有,而且我在任何地方都找不到任何差异。本周晚些时候将继续对此进行调查。
  • 我的问题是上下文不返回代理类型,而只返回实体本身。我不明白你的例子和我的代码有什么区别。
  • @olif 您必须确保以下几点: POCO 类必须声明为具有公共访问权限。 POCO 类不得密封(在 Visual Basic 中为 NotInheritable) POCO 类不得为抽象类(在 Visual Basic 中为 MustInherit)。每个导航属性必须声明为公共、虚拟每个集合属性必须是 ICollection ProxyCreationEnabled 选项在上下文类中不得为 false(默认为 true)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多