我遇到有关使用实体框架进行插入的问题。
我的应用程序有以下两个实体:
备忘录可以与多名员工联系
员工可以与多个备忘录链接。
这意味着多对多的关系。 我读了一些文章向我解释应该创建一个联结表,我认为这是显而易见的。
文章让我学会了让Entity Framework自动为我创建一个联结表。所以我按照以下方式做到了这一点:
备注
public Guid MemoId { get; set; }
public String Message { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
员工
public Guid EmployeeId { get; set; }
public String Name { get; set; }
public virtual ICollection<Memo> Memos { get; set; }
使用程序包管理器控制台更新数据库时,已在数据库中创建联结表。我使用以下行来做到这一点:
update-database -force -verbose
我有一个创建新备忘录的观点。 可以在此处选择Employees列表并将其添加到备忘录中。 但是,填写此联结表并不按计划进行。我认为它与我的存储库的设置有关。我创建了一个MemoRepository和一个EmployeeRepository。
处理备忘录创建的我的控制器如下:
的 MemoController
public class MemoController : Controller
{
private IMemoRepository _memoRepository;
private IEmployeeRepository _employeeRepository;
public MemoController(IMemoRepository memoRepository, IEmployeeRepository employeeRepository) {
_memoRepository = memoRepository;
_employeeRepository = employeeRepository;
}
public ViewResult Create() {
//Initializes MemoCreateViewModel here
return View(model);
}
[HttpPost]
public ActionResult Create(MemoCreateViewModel model) {
if(!ModelState.IsValid)
return RedirectToAction("Create");
Guid employeeId;
List<Guid> employeeIds = new List<Guid>();
foreach (var id in model.SelectedEmployeeIds) {
if (!Guid.TryParse(id, out employeeId)) {
continue;
}
employeeIds.Add(employeeId);
}
var employees = _employeeRepository.GetEmployeesByIds(employeeIds);
model.Memo.Employees = employees.ToList<Employee>();
_memoRepository.SaveMemo(model.Memo);
return RedirectToAction("List");
}
}
MemoRepository
public class EFMemoRepository : IMemoRepository
{
private EFDbContext context;
public EFMemoRepository(EFDbContext _context) {
context = _context;
}
public IQueriable<Memo> Memos {
return context.Memos;
}
public void SaveMemo(Memo memo) {
if(memo.MemoId == Guid.Empty) {
memo.MemoId = Guid.NewGuid();
context.Memos.Add(memo); //error 1 here
} else {
Memo dbEntry = context.Memos.Find(memo.MemoId);
if(dbEntry != null) {
dbEntry.Message = memo.Message;
dbEntry.Employees = memo.Employees;
}
}
context.SaveChanges(); //error 2 here
}
}
错误1我在插入时得到:
实体对象不能被多个实例引用 IEntityChangeTracker。
错误2我在更新时得到:
无法定义两个对象之间的关系,因为 它们附加到不同的ObjectContext对象。
我如何解决这个问题,我阅读的主题是关于人们说它与使用不同的上下文有关,其他人说它与Attach()
有关,但我不知道如何在我的内容中解决这个问题。应用
如果您需要更多信息,请告诉我。
注意:我遗漏了一些代码,以便于阅读。如果要求,当然可以添加代码。
答案 0 :(得分:1)
您收到第一个错误,因为您要添加传递给上下文的Memo对象。但是使用另一个dbContext检索添加到控制器内的memo对象的employee对象。要解决此问题,您必须在两个操作之间共享db上下文,或者必须将Employee对象显式附加到当前上下文。
选项1: 控制器代码
[HttpPost]
public ActionResult Create(MemoCreateViewModel model) {
if(!ModelState.IsValid)
return RedirectToAction("Create");
Guid employeeId;
List<Guid> employeeIds = new List<Guid>();
foreach (var id in model.SelectedEmployeeIds) {
if (!Guid.TryParse(id, out employeeId)) {
continue;
}
employeeIds.Add(employeeId);
}
EFDbContext dbContext = new EFDbContext();//Note
var employees = _employeeRepository.GetEmployeesByIds(dbContext, employeeIds);//Note the extra parameter
model.Memo.Employees = employees.ToList<Employee>();
_memoRepository.SaveMemo(dbContext,model.Memo);//Note the extra parameter
return RedirectToAction("List");
}
EFMemoRepository CLASS CODE:
public void SaveMemo(EFDbContext dbContext, Memo memo)
{
if(memo.MemoId == Guid.Empty)
{
memo.MemoId = Guid.NewGuid();
context.Memos.Add(memo); //error 1 here
} else
{
Memo dbEntry = dbContext.Memos.Find(memo.MemoId);
if(dbEntry != null)
{
dbEntry.Message = memo.Message;
for (int i = 0; i < dbEntry.Employees.Count; i++)/*Please note that if lazy loading is not True then this reference must explicitly be loaded*/
{
dbEntry.Employees.Remove(dbEntry.Employees.First());
}
foreach (var item in memo.Employees)
{
dbEntry.Employees.Add(item);
}
context.Entry(dbEntry).State = EntityState.Modified;
}
}
dbContext.SaveChanges(); //error 2 here
}
OR
选项2:
public void SaveMemo(Memo memo)
{
if(memo.MemoId == Guid.Empty)
{
memo.MemoId = Guid.NewGuid();
context.Memos.Add(memo); //error 1 here
} else
{
Memo dbEntry = context.Memos.Find(memo.MemoId);
if(dbEntry != null)
{
dbEntry.Message = memo.Message;
for (int i = 0; i < dbEntry.Employees.Count; i++)/*Please note that if lazy loading is not True then this reference must explicitly be loaded*/
{
dbEntry.Employees.Remove(dbEntry.Employees.First());
}
foreach (var item in memo.Employees)
{
dbEntry.Employees.Add(item);
}
context.Entry(dbEntry).State = EntityState.Modified;
}
}
context.SaveChanges(); //error 2 here
}
我个人会选择选项1或类似的东西。
如果有什么不清楚就喊出来