我正在使用实体框架5,我试图延迟加载一个实体集合,我将模型剥离到基本框架中,以获得一个简单的可运行示例。
这是我的模型:
public class A
{
public int Id { get; set; }
public EntityCollection<B> Bs
{
get { return bs; }
set { bs = value; }
}
private EntityCollection<B> bs;
public A()
{
bs = new EntityCollection<B>();
}
}
public class B
{
public int Id { get; set; }
public A A { get; set; }
}
public class DbModel : DbContext
{
public DbSet<A> As { get; set; }
public DbSet<B> Bs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<A>()
.HasKey( t => t.Id )
.HasMany(a => a.Bs)
.WithRequired(b => b.A);
modelBuilder.Entity<A>()
.Property(t => t.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<B>()
.HasKey(b => b.Id)
.HasRequired(b => b.A);
modelBuilder.Entity<B>()
.Property( t => t.Id )
.HasDatabaseGeneratedOption( DatabaseGeneratedOption.Identity );
}这是一个证明我的问题的测试:
[TestInitialize]
public void Initialize()
{
model = new DbModel();
model.Configuration.ProxyCreationEnabled = false;
if (model.Database.Exists()) model.Database.Delete();
model.Database.Create();
A a = model.As.Create();
model.As.Add(a);
B b = model.Bs.Create();
a.Bs.Add(b);
model.ChangeTracker.DetectChanges();
model.SaveChanges();
}
[TestMethod]
public void TestMethod1()
{
// arrange
DbModel tModel = new DbModel();
A a = tModel.As.First();
// act
a.Bs.Load();
}其结果是:
测试方法TestProject1.UnitTest1.TestMethod 1抛出异常:
System.InvalidOperationException:当这个RelatedEnd的所有者为null时,不允许被请求的操作。使用默认构造函数创建的RelatedEnd对象只应在序列化期间用作容器。
发布于 2012-11-25 12:55:53
事实证明,我使用的类来自ADO家族的不同范例。正如格特·阿诺德( Gert )指出的那样,它不适用于EntityCollection,它为关联集合使用了一个简单的列表。
public class A
{
public int Id { get; set; }
public List<B> Bs
{
get { return bs; }
set { bs = value; }
}
private List<B> bs = new List<B>();
}因为我不想要代理,所以对象对模型没有“知识”。因此,模型本身必须用于加载实体的关联。对于这个示例,我在模型中添加了以下方法:
public class DbModel : DbContext
{
public DbSet<A> As { get; set; }
public DbSet<B> Bs { get; set; }
//…
public A LoadAWithAssociations(A targetA)
{
return As.Include("Bs").First(a => a.Id.Equals(targetA.Id));
}
}我调整了测试以使用新的方法。
[TestMethod]
public void TestMethod1()
{
// arrange
DbModel tModel = new DbModel();
A a = tModel.As.First();
// act
A result = tModel.LoadAWithAssociations(a);
// assert
Assert.IsNotNull(result);
Assert.IsTrue(result.Bs.Count > 0);
}它现在变成了绿色
发布于 2012-11-18 22:04:34
EntitySet是linq的一部分.这并不能解释这个特殊的例外,但与DbContext的合作不那么顺利也就不足为奇了。使用DbContext API时,通常会将1:n导航属性定义为像ICollection这样的接口。
public virtual ICollection<B> Bs { get; set; }(virtual用于为延迟加载启用代理创建)
顺便提一下:您可以使用model.Database.Delete(),而无需检查数据库是否存在。DetectChanges()就在SaveChanges()之前是多余的。
发布于 2012-11-18 19:14:05
这个代码有点复杂。你真的想要一个类(B)包含对A类的引用,而A类的集合是B?也许只是混淆的名称,但我无法想象像这样的对象模型的场景。
在任何情况下,我的本能反应都是寻找一个循环引用或另一个条件,即阻止在一个类上实例化一个对象属性。
此外,您正在使用a.Bs.Load()在测试方法中使用急切加载。设置ProxyCreationEnabled = false时将禁用延迟加载。
https://stackoverflow.com/questions/13441623
复制相似问题