书籍和作者之间存在着许多典型的关系。 我尝试更新作者时遇到错误。错误的全名是" SqlException:违反PRIMARY KEY约束' PK_BookAuthor'。无法在对象' dbo.BookAuthor'中插入重复键。重复键值为(2,2)。"
如果我不使用UpdateAssociatedObject函数,一切都没问题。但是如果我使用它,当我尝试保存更改时会收到错误。
var parseBook = Mapper.Map<BookViewModel, Book>(viewModel);
Book viewModelBook = parseBook;
var book = db.Books.FindOne(viewModel.BookId);
book.BookId = viewModelBook.BookId;
book.BookName = viewModelBook.BookName;
book.Genre = viewModelBook.Genre;
book.Pages = viewModelBook.Pages;
book.Publisher = viewModelBook.Publisher;
db.SaveChanges();
UpdateAssociatedObject(book, viewModelBook);
}
public void UpdateAssociatedObject(Book bookForUpdate, Book book)
{
bookForUpdate.BookAuthors = book.BookAuthors;
//error is here
db.SaveChanges();
}
映射后viewModelBook的值: 模型(为简洁起见,删除了一些属性)
public class Book
{
public int BookId { get; set; }
public List<BookAuthor> BookAuthors { get; set; }
}
public class Author
{
public int AuthorId { get; set; }
public string AuthorName { get; set; }
public List<BookAuthor> BookAuthors { get; set; }
}
public class BookAuthor
{
public int BookId { get; set; }
public Book Book { get; set; }
public int AuthorId { get; set; }
public Author Author { get; set; }
}
public class BookViewModel
{
public int BookId { get; set; }
public virtual List<AuthorViewModel> Authors { get; set; }
}
public class AuthorViewModel
{
public int AuthorId { get; set; }
public string AuthorName { get; set; }
}
public class Library : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Author> Authors { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BookAuthor>().HasKey(sc => new { sc.BookId, sc.AuthorId });
}
}
映射器:
CreateMap<BookViewModel, Book>()
.ForMember(b => b.BookId, opt => opt.MapFrom(b => b.BookId))
.PreserveReferences()
.ForMember(b => b.BookAuthors, opt => opt.MapFrom(b => b.Authors
.Select(a => new BookAuthor { AuthorId = a.AuthorId })));
UPD: BookId在创建图书后跳转(步长为1000)。
将Include()添加到Find方法后,错误已更改
System.InvalidOperationException:&#39;实体类型的实例&#39; BookAuthor&#39;无法跟踪,因为已经跟踪了另一个具有相同键值的实例{&#39; BookId&#39;,#39; AuthorId&#39;}。附加现有实体时,请确保仅附加具有给定键值的一个实体实例。考虑使用&#39; DbContextOptionsBuilder.EnableSensitiveDataLogging&#39;查看冲突的键值。&#39;
答案 0 :(得分:1)
最后它有效!您可以在下面看到与原始代码的差异。
P.S也许你知道更好的删除方法算法,如果是这样你可以在评论中输入它然后我会改变答案。
BookRepository:
public Book Find(int id)
{
Book searchedBook = db.Books
.Include(b => b.BookAuthors)
.ThenInclude(b => b.Author)
.SingleOrDefault(b => b.BookId == id);
return searchedBook;
}
<强> bookService的:强>
public void UpdateObject(BookViewModel viewModel)
{
Book parsedBook = Mapper.Map<BookViewModel, Book>(viewModel);
//Book viewModelBook = parseBook;
var book = db.Books.Find(viewModel.BookId);
book.BookId = parsedBook.BookId;
book.BookName = parsedBook.BookName;
book.Genre = parsedBook.Genre;
book.Pages = parsedBook.Pages;
book.Publisher = parsedBook.Publisher;
UpdateAssociatedObject(book, parsedBook);
}
public void UpdateAssociatedObject(Book bookToUpdate, Book viewModelBook)
{
AddUpdatedAuthors(bookToUpdate, viewModelBook);
RemoveUpdatedAuthors(bookToUpdate, viewModelBook);
db.SaveChanges();
}
private void AddUpdatedAuthors(Book bookToUpdate, Book viewModelBook)
{
foreach (var authors in viewModelBook.BookAuthors)
{
var searchBookAuthor = bookToUpdate.BookAuthors.Find(b => b.AuthorId == authors.AuthorId);
if (searchBookAuthor == null)
{
bookToUpdate.BookAuthors.Add(authors);
}
}
}
private void RemoveUpdatedAuthors(Book bookToUpdate, Book viewModelBook)
{
int countOfAuthors = bookToUpdate.BookAuthors.Count;
for (int i = 0; i < countOfAuthors; i++)
{
BookAuthor searchBookAuthor = null;
foreach (var viewModelAuthors in viewModelBook.BookAuthors)
{
if (viewModelAuthors.AuthorId == bookToUpdate.BookAuthors[i].AuthorId)
{
searchBookAuthor = viewModelAuthors;
}
}
if (searchBookAuthor == null)
{
bookToUpdate.BookAuthors.Remove(bookToUpdate.BookAuthors[i]);
i--;
countOfAuthors--;
}
}
}
答案 1 :(得分:0)
问题在于使用db.SaveChanges()。您在
中多次调用具有相同上下文的db.SaveChangesdb.SaveChanges();
UpdateAssociatedObject(book, viewModelBook);
并在UpdateAssociatedObject(book, viewModelBook);
尝试删除一个db.SaveChanges()。