![](/img/trans.png)
[英]Deleting parent-child relation with Entity Framework or Entity Framework Core
[英]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.