我正在尝试学习和理解如何使用实体框架和自动映射器与关系。 也许更具体地说是循环引用。
假设我有 3 个物体:
public class Author
{
public string id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public IEnumerable<Book>? Books { get; set; }
}
public class Book
{
public string id { get; set; }
public string Name { get; set; }
public Author Author { get; set; }
public IEnumerable<Page>? Pages { get; set; }
}
public class Page
{
public string id { get; set; }
public string Text { get; set; }
public Book Book { get; set; }
public Author Author { get; set; }
}
当获取作者时,我希望我的回复是这样的:
{
"id": "author1",
"firstName": "famous",
"lastName": "author",
"books": [
{
"id": "book1",
"name": "famousBookName",
"pages": [
{
"id": "page1",
"text": "..."
},
{
"id": "page2",
"text": "..."
}
]
}
]
}
但是在取书时我想要这样的回复:
{
"id": "book1",
"name": "famousBookName",
"author": {
"id": "author1",
"firstName": "famous",
"lastName": "author"
},
"pages": [
{
"id": "page1",
"text": "..."
},
{
"id": "page2",
"text": "..."
}
]
}
当获取页面时,我希望得到如下响应:
{
"id": "page1",
"text": "...",
"book": {
"id": "book1",
"name": "famousBookName"
},
"author": {
"id": "author1",
"firstName": "famous",
"lastName": "author"
}
}
但是,我最终得到的是这样的:
{
"id": "author1",
"firstName": "famous",
"lastName": "author",
"books": [
{
"id": "book1",
"name": "famousBookName",
"pages": [
{
"id": "page1",
"text": "...",
"book": {
"id": "book1",
"name": "famousBookName",
"author": {
"id": "author1",
"firstName": "famous",
"lastName": "author",
"books": [...]
},
"pages": [...]
},
"author": {
"id": "author1",
"firstName": "famous",
"lastName": "author",
"books": [...]
}
}
]
}
]
}
有办法解决这个问题吗?要么告诉实体框架跳过填充循环引用,要么通过自动映射器设置?
或者是添加我映射到的多个 DTO 的唯一方法? 一种是给有书的作者,一种是给没有书的作者 一种用于没有作者和页码的书籍,一种用于带有作者和页码的书籍 一种用于没有书籍和作者的页面,一种用于带有页面和作者的书籍
我觉得随着项目的发展,这样做最终会产生绝对大量的类
解决方案可能是使用 .select() 并简单地将对象手动映射到匿名类型。但这是好的做法吗?
在模型中:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("Author")]
public class AuthorModel
{
public string id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<BookModel>? Books { get; set; }< -- here
}
public class BookModel
{
public string id { get; set; }
public string Name { get; set; }
public virtual ICollection<PageModel>? Pages { get; set; } < -- here
}
public class PageModel
{
public string id { get; set; }
public string Text { get; set; }
[ForeignKey("Book")] <- I dont think you really need FK declaration if hooked up in DBContext class
public int BookId { get; set; }< -- here
public virtual BookModel Book { get; set; }
[ForeignKey("Author ")] < -- here
public int AuthorId { get; set; }< -- here
public virtual AuthorModel Author { get; set; }
}
在 DBContext 类中:
public virtual DbSet<BookModel> Books { get; set; }
public virtual DbSet<AuthorModel> Authors { get; set; }
public virtual DbSet<PageModel> Pages{ get; set; }
并告诉 DbContext 中的 EF 它们是如何链接的。比如:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<AuthorModel>()
.HasMany(p => p.Books)
.WithMany(p => p.Authors);
modelBuilder
.Entity<PageModel>()
.HasOne(p => p.Book)
.WithMany(p => p.Pages);
}