EF Core 6.0 导航属性未加载

Posted

技术标签:

【中文标题】EF Core 6.0 导航属性未加载【英文标题】:EF Core 6.0 navigation property not loading 【发布时间】:2022-01-04 11:16:53 【问题描述】:

我正在尝试构建一个简单的基于 ASP.NET Core 6 的 Web API。我从遵循 Microsoft 的最小 Web API 教程 https://docs.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-6.0 开始,它有效。然后我添加了我自己的带有导航属性的数据模型,使用https://docs.microsoft.com/en-us/ef/core/modeling/relationships 作为指导,但是当我执行查询时,该属性为空。

这是我的模型:

public class Author 
  public int Id  get; set; 
  public string Name  get; set; 
  public List<Book> Books  get; set; 


public class Book 
  public int Id  get; set; 
  public string Title  get; set; 
  public Author Author  get; set; 

我的 DbContext 如下:

public class LibraryDb : DbContext 
  public LibraryDb(DbContextOptions<LibraryDb> options) : base(options) 
  public DbSet<Author> Authors => Set<Author>();
  public DbSet<Book> Books => Set<Book>();

还有我的申请:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSqlite<LibraryDb>("Data Source=Library.db");
var app = builder.Build();
app.MapGet("/authors", async (LibraryDb db) => await db.Authors.ToListAsync());
app.MapGet("/books", async (LibraryDb db) => await db.Books.ToListAsync());
app.Run();

运行“ef migrations add”和“ef database update”命令后,数据库结构如下:

CREATE TABLE "Authors" (
    "Id" INTEGER NOT NULL CONSTRAINT "PK_Authors" PRIMARY KEY AUTOINCREMENT,
    "Name" TEXT NOT NULL
)
CREATE TABLE "Books" (
    "Id" INTEGER NOT NULL CONSTRAINT "PK_Books" PRIMARY KEY AUTOINCREMENT,
    "AuthorId" INTEGER NOT NULL,
    "Title" TEXT NOT NULL,
    CONSTRAINT "FK_Books_Authors_AuthorId" FOREIGN KEY ("AuthorId") REFERENCES "Authors" ("Id") ON DELETE CASCADE
)
CREATE INDEX "IX_Books_AuthorId" ON "Books" ("AuthorId")

我已经用几行填充了数据库(每本书都分配了一个 AuthorId),但这是调用我的“/authors”API 时的结果:

["id":1,"name":"Clive Barker","books":null,"id":2,"name":"Stephen King","books":null]

对于“/books”:

["id":1,"title":"Weaveworld","author":null,"id":2,"title":"The Stand","author":null]

“书籍”和“作者”字段为空。生成的 SQL 语句似乎没有进行任何连接 - 我做错了什么?如果我按照我在其他地方看到的建议将路由代码更改为 b.Authors.Include(x =&gt; x.Books).ToListAsync(),我会收到检测到对象循环的 JsonException。

【问题讨论】:

EF Core 使用延迟加载。仅在访问时加载相关实体。如果您想急切地加载相关实体,请使用Include 【参考方案1】:

Include 是正确的方法(至少其中之一 - 请参阅loading related data 文档)。所以添加回你的包含:

b.Authors
    .Include(x => x.Books)
    .ToListAsync()

下一个问题是由 EF 自动填充引用属性(称为关系修复)引起的,这将引入默认情况下序列化程序不处理的循环。您可以使用下一个设置更改序列化程序的行为:

builder.Services.Configure<JsonOptions>(options =>

    options.SerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
);

我个人通常更喜欢从端点返回一些 DTO 而不是实体本身,这可以让您对返回进行更精细的控制,因此将查询结果映射到一些 DTO 也可以解决问题。

【讨论】:

谢谢,我以后可能会使用 DTO,但这暂时有效。

以上是关于EF Core 6.0 导航属性未加载的主要内容,如果未能解决你的问题,请参考以下文章

EF 导航属性未加载

EF Core 2.0 Identity - 添加导航属性

EF Core 2 如何在 IdentityUser 上包含角色导航属性?

Ef core LazyLoading - 访问集合类型的嵌套导航属性引发 DetachedLazyLoadingWarning 错误

如何在 EF Core 5 中为自定义 SQL 配置导航属性

无法使用 OData、EF Core 和 AutoMapper 映射 List<> 导航属性