Entity framework 延迟加载在 1..* 单向关系中不起作用
Entity framework lazy loading not working in 1..* unidirectional relationship
我有以下实体
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"))
出于某种原因,Entity Framework 在请求对象 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()
returns 实体本身而不是代理类型。这表明 属性
ProxyCreationEnabled 是假的,但我仔细检查了它并将其设置为真。
编辑 2
好的,终于找到问题了。我已将 Bs 构造函数设置为私有,这当然使得无法使用代理 class 扩展对象。因此,导航属性设置为 null。
我修改了您的代码,以便使用延迟加载。只需复制粘贴,一切都应该没问题。
在写入行之前用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;
}
}
}
我有以下实体
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"))
出于某种原因,Entity Framework 在请求对象 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()
returns 实体本身而不是代理类型。这表明 属性 ProxyCreationEnabled 是假的,但我仔细检查了它并将其设置为真。
编辑 2
好的,终于找到问题了。我已将 Bs 构造函数设置为私有,这当然使得无法使用代理 class 扩展对象。因此,导航属性设置为 null。
我修改了您的代码,以便使用延迟加载。只需复制粘贴,一切都应该没问题。
在写入行之前用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;
}
}
}