我在插入具有多对多导航属性的记录时遇到问题,
我有这些模型
//ModelBase
public class ModelBase
{
[Key]
public long Id { get; set; }
}
//Book
public class Book : ModelBase
{
public string Title { get; set; }
public virtual ICollection<Author> Authors { get; set; }
public virtual ICollection<PublishedBook> PublishedBooks { get; set; }
}
//Author
public class Author : ModelBase
{
public string Name { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
DTO调用BookDto
和AuthorDto
来传输图层之间的数据
从控制器我将数据填充到DTO并调用Create
方法(位于单独的层中)以将数据保存到数据库,
BookDto bookDto = new BookDto()
{
Id = model.Id,
Title = model.Title,
Authors = model.AuthorIds.Select(c => new AuthorDto { Id = c }).ToList()
}
using (ServiceFactory facory = new ServiceFactory())
{
factory.Book.Create(bookDto);
}
在Create
方法中,我使用ValueInjector
public void Create(BookDto bookDTO)
{
Book book = new Book();
book.InjectFrom<DeepCloneInjection>(bookDTO);
bookRepository.Add(book);
unitOfWork.Commit();
}
它在Genaric Repository Base中调用Add
方法
public virtual void Add(T entity)
{
dbset.Add(entity);
}
这会适当地将数据插入Books
表和BookAuthors
表但是即使我通过Authors
现有Authors
,也会在AuthorIds
表中插入新记录来自控制器的Book.Authors
。
任何想法如何解决这个问题?
答案 0 :(得分:2)
您缺少将现有作者附加到上下文。你可以这样做:
public void Create(BookDto bookDTO)
{
Book book = new Book();
book.InjectFrom<DeepCloneInjection>(bookDTO);
foreach (var author in book.Authors)
authorRepository.Attach(author);
bookRepository.Add(book);
unitOfWork.Commit();
}
通常调用Attach
实现通用dbset.Attach(entity);
方法。我假设所有存储库(authorRepository
和bookRepository
)共享相同的上下文实例。否则上述情况将无效。
数据库中已存在AuthorId
并不重要。 EF不首先通过查询检查Id是否存在。如果在分离实体的对象图上调用Add
,它会尝试通过为父项和所有子项生成INSERT语句来插入整个图。通过附加子项,您可以有效地关闭INSERT语句。