首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EntityCollection的负载

EntityCollection的负载
EN

Stack Overflow用户
提问于 2012-11-18 15:39:39
回答 3查看 642关注 0票数 1

我正在使用实体框架5,我试图延迟加载一个实体集合,我将模型剥离到基本框架中,以获得一个简单的可运行示例。

这是我的模型:

代码语言:javascript
复制
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 );
    }

这是一个证明我的问题的测试:

代码语言:javascript
复制
   [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对象只应在序列化期间用作容器。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-25 12:55:53

事实证明,我使用的类来自ADO家族的不同范例。正如格特·阿诺德( Gert )指出的那样,它不适用于EntityCollection,它为关联集合使用了一个简单的列表。

代码语言:javascript
复制
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>();
}

因为我不想要代理,所以对象对模型没有“知识”。因此,模型本身必须用于加载实体的关联。对于这个示例,我在模型中添加了以下方法:

代码语言:javascript
复制
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));
    }
}

我调整了测试以使用新的方法。

代码语言:javascript
复制
  [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);
    }

它现在变成了绿色

票数 0
EN

Stack Overflow用户

发布于 2012-11-18 22:04:34

EntitySet是linq的一部分.这并不能解释这个特殊的例外,但与DbContext的合作不那么顺利也就不足为奇了。使用DbContext API时,通常会将1:n导航属性定义为像ICollection这样的接口。

代码语言:javascript
复制
public virtual ICollection<B> Bs { get; set; }

(virtual用于为延迟加载启用代理创建)

顺便提一下:您可以使用model.Database.Delete(),而无需检查数据库是否存在。DetectChanges()就在SaveChanges()之前是多余的。

票数 1
EN

Stack Overflow用户

发布于 2012-11-18 19:14:05

这个代码有点复杂。你真的想要一个类(B)包含对A类的引用,而A类的集合是B?也许只是混淆的名称,但我无法想象像这样的对象模型的场景。

在任何情况下,我的本能反应都是寻找一个循环引用或另一个条件,即阻止在一个类上实例化一个对象属性。

此外,您正在使用a.Bs.Load()在测试方法中使用急切加载。设置ProxyCreationEnabled = false时将禁用延迟加载。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13441623

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档