繁体   English   中英

实体核心中的一对多关系删除子表中的先前记录作为父子更新的一部分

[英]One to many relationship in Entity core deleting the previous records in child table as part of parent-child update

我有 3 个实体,如 Book、Author 和 BookAuthor(联结表),我有 Author 的主数据,一本书可以有多个 Author,因此 BookAuthor 将存储 BookId 和 AuthorId。

在这里,问题是我最初创建了 2 个作者的书籍记录,因此它将一条记录保存到 Book 表中,将 2 条记录保存到 BookAuthor 表中。 在下一个请求中,我又添加了一位作者,期望它应该在 BookAuthor 表中再插入一条记录,并且它应该包含 3 条记录。 但是正在发生的事情是作为更新的一部分,它正在删除前两条记录并将新记录插入 BookAuthor 表中。

图书.cs

    private string _name;
    private int _pageCount;
    private List<BookAuthor> _bookAuthors = new List<BookAuthor>();

    public Book()
    {
            
    }

    public Book(string name, int pageCount)
    {
        _name = name;
        _pageCount = pageCount;
    }

    public int Id { get; set; }
    public string Name => _name;
    public int PageCount => _pageCount;

    public IEnumerable<BookAuthor> BookAuthors => _bookAuthors;

作者.cs

    private string _name;
    private int _age;
    private List<BookAuthor> _bookAuthors = new List<BookAuthor>();

    public Author()
    {

    }

    public Author(string name, int age)
    {
        _name = name;
        _age = age;
    }
    public int Id { get; set; }
    public string Name => _name;
    public int Age => _age;

    public IEnumerable<BookAuthor> BookAuthors => _bookAuthors;

BookAuthor.cs

    private int _bookId;
    private int _authorId;

    private Book _book;
    private Author _author;

    public BookAuthor()
    {

    }

    public BookAuthor(int bookId, int authorId)
    {
        _bookId = bookId;
        _authorId = authorId;
    }
    public int Id { get; set; }
    public int BookId => _bookId;
    public int AuthorId => _authorId;

    public Book Book => _book;
    public Author Author => _author;

使用上面创建的实体配置。

 public class AuthorConfiguration : IEntityTypeConfiguration<Author>
   {
    public void Configure(EntityTypeBuilder<Author> builder)
    {
        builder.HasKey(b => b.Id);
        builder.Property(b => b.Name).HasField("_name");
        builder.Property(b => b.Age).HasField("_age");
        builder.HasMany(t => t.BookAuthors).WithOne(t => 
         t.Author).HasForeignKey(t => t.AuthorId);
  builder.Metadata.FindNavigation(nameof(Book.BookAuthors)).SetPropertyAccessMode(PropertyAccessMode.Field);
    }
}


  
  public class BookConfiguration : IEntityTypeConfiguration<Book>
{
    public void Configure(EntityTypeBuilder<Book> builder)
    {
        builder.HasKey(b => b.Id);
        builder.Property(b => b.Name).HasField("_name");
        builder.Property(b => b.PageCount).HasField("_pageCount");
        builder.HasMany(t => t.BookAuthors).WithOne(t => t.Book).HasForeignKey(t => t.BookId);

        builder.Metadata.FindNavigation(nameof(Book.BookAuthors)).SetPropertyAccessMode(PropertyAccessMode.Field);
    }
}


  public class BookAuthorConfiguration : IEntityTypeConfiguration<BookAuthor>
{
    public void Configure(EntityTypeBuilder<BookAuthor> builder)
    {
        builder.HasKey(b => b.Id);
        builder.Property(b => b.BookId).HasField("_bookId");
        builder.Property(b => b.AuthorId).HasField("_authorId");
        builder.HasOne(a => a.Book).WithMany(a => a.BookAuthors).HasForeignKey(a => a.BookId);
        builder.HasOne(a => a.Author).WithMany(a => a.BookAuthors).HasForeignKey(a => a.AuthorId);
    }
}

更新代码

  public async Task<Result> UpdateReference(BookDto bookDto)
    {
        var bookresult = await _bookRepository.GetById(bookDto.Id);
        bookresult.Value.Update(bookDto.Name, bookDto.PageCount, bookDto.AuthorIds);

        var result = await _bookRepository.Update(bookresult.Value);
        if (!result.IsSucceeded)
            return Result.Fail(result.GetErrorString());

        return Result.Ok();

    }

    public void Update(string name, int pageCount, List<int> authersId)
    {
        _name = name;
        _pageCount = pageCount;
        UpdateAutherId(authersId);
    }

    private void UpdateAutherId(List<int> authersId)
    {
        if (authersId.Any())
        {
            var bookAuthors = GetBookAuthors(authersId);
            var newBookAuthors = bookAuthors.Except(_bookAuthors).ToList();
            var deletedBookAuthors = _bookAuthors.Except(bookAuthors).ToList();
            if (newBookAuthors.Any())
            {
                _bookAuthors.AddRange(newBookAuthors);
            }
            if (deletedBookAuthors.Any())
            {
                foreach (var bookAuthor in deletedBookAuthors)
                {
                    _bookAuthors.Remove(bookAuthor);
                }
            }
        }
        else
        {
            _bookAuthors.RemoveRange(0, _bookAuthors.Count);
        }
    }

   public override async Task<Result<Book>> GetById(int id)
    {
        var result = await _bookAuthorContext.Books
            .Include(a => a.BookAuthors)
            .FirstOrDefaultAsync(a => a.Id == id);

        if (result == null)
            return Result.Fail<Book>("no Data found", ApplicationResponseCode.BadRequest, ApplicationResponseCode.BadRequest);

        return Result.Ok<Book>(result);
    }

在我看来,问题是因为当您从数据库检索特定书籍时,您没有获取 BookAuthor 实体。

您可以在这里依赖 EF 并简单地从 db 中检索Book实体,但不要忘记Include BookAuthor实体。

然后您需要调用的只是将现有BookAuthor集合替换为另一个集合,保存更改后,EF 将自动执行插入/删除

var myBook = db.Books.Include(b => b.BookAuthors).SingleOrDefalut(b => b == ...);
myBook.BookAuthors = newBookAuthors;
db.SaveChanges();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM