使用实体框架或自动映射器处理循环引用

问题描述 投票:0回答:1

我正在尝试学习和理解如何使用实体框架和自动映射器与关系。 也许更具体地说是循环引用。

假设我有 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() 并简单地将对象手动映射到匿名类型。但这是好的做法吗?

c# .net entity-framework-core automapper .net-7.0
1个回答
0
投票

在模型中:

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);
}
© www.soinside.com 2019 - 2024. All rights reserved.