C# 正在加载引用另一个表中相关数据的数据列表

C# 正在加载引用另一个表中相关数据的数据列表,c#,asp.net-mvc,entity-framework,C#,Asp.net Mvc,Entity Framework,已解决 我试图找出如何在实体框架中从表中检索相关数据的集合,但还没有解决这个问题 这是两个表之间的多对多关系,如下图所示: 我的问题是,我想检索与作者相关的书籍,这是BOOK表的ICollection,但当我返回时,它会给我一个空列表。 我已尝试使用显式加载解决此问题: public AUTHOR Read(int Aid) { using(var db = new LibraryDBEntities1()) { var author = db.AUTHORs

已解决

我试图找出如何在实体框架中从表中检索相关数据的集合,但还没有解决这个问题

这是两个表之间的多对多关系,如下图所示:

我的问题是,我想检索与作者相关的书籍,这是BOOK表的ICollection,但当我返回时,它会给我一个空列表。 我已尝试使用显式加载解决此问题:

public AUTHOR Read(int Aid)
{
    using(var db = new LibraryDBEntities1())
    {
        var author = db.AUTHORs.Find(Aid);
        db.Entry(author).Collection(a => a.BOOKs).Load();

        return author;
    }
}
我也尝试过使用渴望加载来解决它

return db.AUTHORs.Where(a => a.Aid == Aid).Include("BOOKs").FirstOrDefault();
但它也不起作用。我试图按照microsoft文档的说明进行操作,但我一直无法找出我做错了什么。 谁能帮我解决这个问题,也许能解释一下我哪里做错了

编辑1 这就是OnModelCreating的外观。我应该在这里更改/添加代码吗?我一直在使用数据库优先的方法


protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    throw new UnintentionalCodeFirstException();
}
编辑2

数据库连接应如下所示:

编辑3

我忘了提到我正在使用一个三层架构,包括一个表示层(MVC)、一个业务逻辑层和一个数据访问层。还有一个包含数据库的数据层,如下图所示

解决方案

所以我终于解决了!所以问题并不是我第一次想到的问题,而是我如何使用我的地图绘制工具。 我必须在我的模型中添加以下代码才能使其正常工作:

authorObj.BooksList = Mapper.Map<List<BOOK>, List<Book>>(aauthor.BOOKs.ToList());
authorbj.BooksList=Mapper.Map(aauther.BOOKs.ToList());

现在它可以正常工作了

由于是数据库优先的方法,请尝试将下面的映射添加到您的
OnModelCreating
函数中

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

     modelBuilder.Entity<BOOKs>()
        .HasMany<AUTHORs>(b => b.AUTHORs)
        .WithMany(a => a.BOOKs)
        .Map(m => m.ToTable("BOOK_AUTHOR")
        .MapLeftKey("ISBN")
        .MapRightKey("Aid"));

// or like below
       /* modelBuilder.Entity<BOOKs>()
         .HasMany<AUTHORs>(s => s.AUTHORs)
         .WithMany(c => c.BOOKs)
         .Map(cs =>
         {
              cs.MapLeftKey("ISBN");
              cs.MapRightKey("Aid");
              cs.ToTable("BOOK_AUTHOR"); // Use the correct junction table name here. and correct key names
         });*/
    }

或者简单地说,在FirstOrDefault中直接使用谓词,而不使用WHERE子句

db.AUTHORs.Include(a => a.BOOKs).FirstOrDefault(a => a.Aid == Aid); // Same as above two queries.
更新

var query = db.AUTHORs.Include(a => a.BOOKs).Where(a => a.Aid == Aid);
var firstBook = query.FirstOrDefault(); // Have a break point here. Please see what is in query via quick watch.
在QuickWatchforQuery(不是firstBook)中,您应该看到如下所示的Sql:

请在SSMS中直接执行SQL语句并在此处发布您的观察结果,如

  • 您是否在查询中看到图书的联接
  • 结果集是否包含书本中的列

由于是数据库优先的方法,请尝试将下面的映射添加到您的
OnModelCreating
函数中

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

     modelBuilder.Entity<BOOKs>()
        .HasMany<AUTHORs>(b => b.AUTHORs)
        .WithMany(a => a.BOOKs)
        .Map(m => m.ToTable("BOOK_AUTHOR")
        .MapLeftKey("ISBN")
        .MapRightKey("Aid"));

// or like below
       /* modelBuilder.Entity<BOOKs>()
         .HasMany<AUTHORs>(s => s.AUTHORs)
         .WithMany(c => c.BOOKs)
         .Map(cs =>
         {
              cs.MapLeftKey("ISBN");
              cs.MapRightKey("Aid");
              cs.ToTable("BOOK_AUTHOR"); // Use the correct junction table name here. and correct key names
         });*/
    }

或者简单地说,在FirstOrDefault中直接使用谓词,而不使用WHERE子句

db.AUTHORs.Include(a => a.BOOKs).FirstOrDefault(a => a.Aid == Aid); // Same as above two queries.
更新

var query = db.AUTHORs.Include(a => a.BOOKs).Where(a => a.Aid == Aid);
var firstBook = query.FirstOrDefault(); // Have a break point here. Please see what is in query via quick watch.
在QuickWatchforQuery(不是firstBook)中,您应该看到如下所示的Sql:

请在SSMS中直接执行SQL语句并在此处发布您的观察结果,如

  • 您是否在查询中看到图书的联接
  • 结果集是否包含书本中的列

EF 6包括多对多关系的默认约定。您需要在两端包含集合导航属性。因此,您的模型类定义非常好。您应该做的是更新
OnMOdalCreating
,如下所示

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
}
return db.AUTHORs.Where(a => a.Aid == Aid).Include(a => a.BOOKs).FirstOrDefault();
[Table("BOOK_AUTHOR")]
public class BookAuthor
{
    public int ISBN { get; set; }
    public int AId { get; set; }
    public virtual Book Book { get; set; }
    public virtual Author Author { get; set; }
}
然后你可以像下面那样使用它

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
}
return db.AUTHORs.Where(a => a.Aid == Aid).Include(a => a.BOOKs).FirstOrDefault();
[Table("BOOK_AUTHOR")]
public class BookAuthor
{
    public int ISBN { get; set; }
    public int AId { get; set; }
    public virtual Book Book { get; set; }
    public virtual Author Author { get; set; }
}
附言:我强烈建议您为连接类型创建一个模型类

编辑 使用数据库优先的方法,基本上必须为数据库中的每个表创建一个模型类

因此,不要更改您的
OnMOdalCreating
方法。添加一个新类,如下所示

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
}
return db.AUTHORs.Where(a => a.Aid == Aid).Include(a => a.BOOKs).FirstOrDefault();
[Table("BOOK_AUTHOR")]
public class BookAuthor
{
    public int ISBN { get; set; }
    public int AId { get; set; }
    public virtual Book Book { get; set; }
    public virtual Author Author { get; set; }
}
然后,您需要通过属性或fluentapi将属性绑定到主键属性。在那之后,你将能够找到一位拥有如下书籍的作者

var authorWithBooks = context.Authors
    .Include(a => a.BookAuthors.Select(ba => ba.Book))
    .Where(...)
    .ToList();

EF 6包括多对多关系的默认约定。您需要在两端包含集合导航属性。因此,您的模型类定义非常好。您应该做的是更新
OnMOdalCreating
,如下所示

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
}
return db.AUTHORs.Where(a => a.Aid == Aid).Include(a => a.BOOKs).FirstOrDefault();
[Table("BOOK_AUTHOR")]
public class BookAuthor
{
    public int ISBN { get; set; }
    public int AId { get; set; }
    public virtual Book Book { get; set; }
    public virtual Author Author { get; set; }
}
然后你可以像下面那样使用它

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
}
return db.AUTHORs.Where(a => a.Aid == Aid).Include(a => a.BOOKs).FirstOrDefault();
[Table("BOOK_AUTHOR")]
public class BookAuthor
{
    public int ISBN { get; set; }
    public int AId { get; set; }
    public virtual Book Book { get; set; }
    public virtual Author Author { get; set; }
}
附言:我强烈建议您为连接类型创建一个模型类

编辑 使用数据库优先的方法,基本上必须为数据库中的每个表创建一个模型类

因此,不要更改您的
OnMOdalCreating
方法。添加一个新类,如下所示

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
}
return db.AUTHORs.Where(a => a.Aid == Aid).Include(a => a.BOOKs).FirstOrDefault();
[Table("BOOK_AUTHOR")]
public class BookAuthor
{
    public int ISBN { get; set; }
    public int AId { get; set; }
    public virtual Book Book { get; set; }
    public virtual Author Author { get; set; }
}
然后,您需要通过属性或fluentapi将属性绑定到主键属性。在那之后,你将能够找到一位拥有如下书籍的作者

var authorWithBooks = context.Authors
    .Include(a => a.BookAuthors.Select(ba => ba.Book))
    .Where(...)
    .ToList();

你是如何在你的c#模型中定义多对多关系的(你能从你的上下文文件的OnModelCreating@sam谢谢你的评论!我是实体框架新手,所以我不知道我应该更改上下文文件中的任何内容。我已经编辑了这个问题,并在OnModelCreatingwhat EF version you using?@ilkerkaran我使用的是EF version 6.4。0@JulijusE你不应该做任何事。我认为你的
。Include(“book”)
有问题。你能试试
Include(a=>a.BOOKs)
吗?你是如何在你的c模型中定义很多关系的(你能从你的上下文文件的OnModelCreating@sam谢谢你的评论!我是实体框架新手,所以我不知道我应该更改上下文文件中的任何内容。我已经编辑了这个问题,并在OnModelCreatingwhat EF version you using?@ilkerkaran我使用的是EF version 6.4。0@JulijusE你不应该做任何事。我认为你的
有问题。包括(“书籍”)
你能试试
包括(a=>a.BOOKs)吗
?谢谢你的回答!我试过了,但没有成功。你认为我应该先迁移到代码而不是数据库,然后为连接表创建一个模型类,还是可以立即使用我正在采取的方法添加它?先迁移到代码取决于项目的需要。但我也会为连接添加一个模型这样,我的工作就更灵活了opinion@ilkerkaran据我所知,如果连接表