如何使用 EF6 正确设置多对多关系?

Posted

技术标签:

【中文标题】如何使用 EF6 正确设置多对多关系?【英文标题】:How to set up many to many relationship correctly with EF6? 【发布时间】:2020-01-24 14:30:05 【问题描述】:

我在让我的多对多关系发挥作用时遇到了一些问题。我有两个表,Beestje 和 Accessoire,我想显示它的内容。

这是我的桌子: 贝斯特杰:

public class Beestje

    public Beestje()
    
        this.Accessoires = new HashSet<Accessoire>();
    

    [Key]
    public int Id  get; set; 

    public String Naam  get; set; 

    public String Type  get; set; 

    public int Prijs  get; set; 

    public String Afbeelding  get; set; 

    public virtual ICollection<Accessoire> Accessoires  get; set; 

配饰:

public class Accessoire

    public Accessoire()
    
        this.Beestjes = new HashSet<Beestje>();
    

    [Key]
    public int Id  get; set; 

    public String Naam  get; set; 

    public double Prijs  get; set; 

    public String Afbeelding  get; set; 

    public virtual ICollection<Beestje> Beestjes  get; set; 

在我的控制器中,我从 Beestje 表中检索内容并将其返回给视图:

public ActionResult Beestjes()
    
        ViewBag.Message = "Your application beestjes page";

        List<Beestje> beestjes;

        using (var context = new MyContext())
        
            beestjes = context.Beestjes.ToList();

            return View(beestjes);
        
    

当我这样打印时没有问题:

@model IEnumerable<BeestjeOpJeFeestje.Models.Beestje>

<h2>@ViewBag.Message</h2>
<ul>
    @foreach (var a in Model)
    
        <li>@a.Naam</li>
    
</ul>

但是当我这样打印时出现错误:

@model IEnumerable<BeestjeOpJeFeestje.Models.Beestje>

<h2>@ViewBag.Message</h2>
<ul>
    @foreach (var a in Model)
    
        <li>@a.Naam</li>
        foreach (var b in a.Accessoires)
        
            <li>@b.Naam</li>
        
    
</ul>

在我调用 a.Accessoires 的部分出现问题。 错误是: "System.ObjectDisposedException: 'ObjectContext 实例已被释放,不能再用于需要连接的操作。'"

有人知道正确的方法,愿意提供正确的代码,或者给我一些指示吗?

提前致谢。

编辑:

我的上下文

public class MyContext : DbContext
    
        public MyContext() : base("name=Local")
        
            Database.SetInitializer(new MyContextInitializer());
        

        public DbSet<Beestje> Beestjes  get; set; 
        public DbSet<Accessoire> Accessoires  get; set; 

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        
            base.OnModelCreating(modelBuilder);
        
    

MyContextInitializer

public class MyContextInitializer : DropCreateDatabaseAlways<MyContext>
    
        protected override void Seed(MyContext context)
        
            base.Seed(context);

            context.Beestjes.Add(new Beestje()  Id = 1, Naam = "Aap", Type = "Jungle", Prijs = 150, Afbeelding = "Content/images/aap.png" );
            context.Beestjes.Add(new Beestje()  Id = 2, Naam = "Olifant", Type = "Jungle", Prijs = 250, Afbeelding = "Content/images/olifant.png" );
            context.Beestjes.Add(new Beestje()  Id = 3, Naam = "Zebra", Type = "Jungle", Prijs = 200, Afbeelding = "Content/images/zebra.png" );
            context.Beestjes.Add(new Beestje()  Id = 4, Naam = "Leeuw", Type = "Jungle", Prijs = 250, Afbeelding = "Content/images/leeuw.png" );
            context.Beestjes.Add(new Beestje()  Id = 5, Naam = "Hond", Type = "Boerderij", Prijs = 75, Afbeelding = "Content/images/doggo.png" );
            context.Beestjes.Add(new Beestje()  Id = 6, Naam = "Ezel", Type = "Boerderij", Prijs = 150, Afbeelding = "Content/images/donkey.png" );
            context.Beestjes.Add(new Beestje()  Id = 7, Naam = "Koe", Type = "Boerderij", Prijs = 100, Afbeelding = "Content/images/koe.png" );
            context.Beestjes.Add(new Beestje()  Id = 8, Naam = "Eend", Type = "Boerderij", Prijs = 50, Afbeelding = "Content/images/duck.png" );
            context.Beestjes.Add(new Beestje()  Id = 9, Naam = "Kuiken", Type = "Jungle", Prijs = 35, Afbeelding = "Content/images/kuiken.png" );
            context.Beestjes.Add(new Beestje()  Id = 10, Naam = "Pinguin", Type = "Sneeuw", Prijs = 175, Afbeelding = "Content/images/pingwing.png" );
            context.Beestjes.Add(new Beestje()  Id = 11, Naam = "IJsbeer", Type = "Sneeuw", Prijs = 300, Afbeelding = "Content/images/ijsbeer.png" );
            context.Beestjes.Add(new Beestje()  Id = 12, Naam = "Zeehond", Type = "Sneeuw", Prijs = 200, Afbeelding = "Content/images/zeehond.png" );
            context.Beestjes.Add(new Beestje()  Id = 13, Naam = "Kameel", Type = "Woestijn", Prijs = 175, Afbeelding = "Content/images/kameel.png" );
            context.Beestjes.Add(new Beestje()  Id = 14, Naam = "Slang", Type = "Sneeuw", Prijs = 125, Afbeelding = "Content/images/slang.png" );

            var accessoire1 = new Accessoire()  Naam = "Banaan", Prijs = 0.50 ;
            accessoire1.Beestjes.Add(context.Beestjes.Find(1));
            context.Accessoires.Add(accessoire1);

            var accessoire2 = new Accessoire()  Naam = "Zadel", Prijs = 4.50 ;
            accessoire2.Beestjes.Add(context.Beestjes.Find(3));
            context.Accessoires.Add(accessoire2);

            var accessoire3 = new Accessoire()  Naam = "Krukje", Prijs = 5 ;
            accessoire3.Beestjes.Add(context.Beestjes.Find(4));
            context.Accessoires.Add(accessoire3);

            var accessoire4 = new Accessoire()  Naam = "Zweep", Prijs = 2.50 ;
            accessoire4.Beestjes.Add(context.Beestjes.Find(4));
            context.Accessoires.Add(accessoire4);

            var accessoire5 = new Accessoire()  Naam = "Bal", Prijs = 2.50 ;
            accessoire5.Beestjes.Add(context.Beestjes.Find(5));
            accessoire5.Beestjes.Add(context.Beestjes.Find(12));
            context.Accessoires.Add(accessoire5);

            var accessoire6 = new Accessoire()  Naam = "Dansschoenen", Prijs = 3.00 ;
            accessoire6.Beestjes.Add(context.Beestjes.Find(10));
            context.Accessoires.Add(accessoire6);

            context.SaveChanges();
        
    

【问题讨论】:

ASP.NET MVC 是一个 Web 堆栈,而不是数据访问库。您使用的是 EF 还是 EF Core?哪个版本?请贴出MyContext的定义,就是配置关系的地方 是的,你是对的,我忘了包括那个。我正在使用 EF6。我现在在问题中包含了 MyContext。 至于错误本身,它没有说明关系。它说代码试图使用已经释放的 ObjectContext 实例。最新版本的 EF 使用 DbContext,而不是 ObjectContext。您是否在代码中的某处显式访问 ObjectContext?也许尝试使用 UDF? 我在我的项目中搜索了 ObjectContext,但我没有在任何地方使用它 【参考方案1】:

这很可能是由于对于每个BeestjeAccessoires 属性在您尝试在视图中访问它之前不会被加载,并且此时MyContext 已经被释放。

解决方案是使用.Include() 告诉 EF 立即加载它们,这就是所谓的“急切加载”:

using (var context = new MyContext())

    beestjes = context.Beestjes
        .Include("Accessoires")
        .ToList();

    return View(beestjes);

参考见https://docs.microsoft.com/en-us/ef/ef6/querying/related-data

【讨论】:

以上是关于如何使用 EF6 正确设置多对多关系?的主要内容,如果未能解决你的问题,请参考以下文章

如何在书架中建立自引用多对多关系

如何使用 Sunspot 设置具有多对多关系的构面搜索?

如何使用 SQLAlchemy 建立多对多关系:一个很好的例子

Spring,JPA:如何使用多对多关系桥表设置查询另一个实体下的实体

CoreData:如何建模循环多对多关系

如何使用多对多关系