我遇到有关实体框架插入的问题。
我的应用程序具有以下两个实体:
备忘录可以与多个雇员链接。
一个雇员可以与多个备忘录链接。
这意味着多对多关系。我读了几篇文章,向我解释说应该创建一个联结表,这很明显。
这些文章使我了解到,让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; }
使用Package Manager控制台更新数据库时,已在数据库中创建一个联结表。我使用以下代码行:
update-database -force -verbose
我有一个用于创建新备忘录的视图。可以在此处选择一个员工列表并将其添加到备忘录中。但是,填写此联结表并没有按计划进行。我认为这与我的存储库的设置有关。我创建了一个MemoRepository和一个EmployeeRepository。
我处理Memo创建的控制器如下:
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");
}
}
备注存储库
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()
,但是我不知道如何在我的应用程序中解决这个问题。
请告诉我您是否需要更多信息。
注意:我省略了一些代码,以使其更易于阅读。当然可以根据需要添加代码。
您收到第一个错误,因为要添加传递到上下文的Memo对象。但是,使用另一个dbContext检索了添加到控制器内部备注对象中的雇员对象。要解决此问题,必须在两个操作之间共享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类别代码:
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
}
或者
选项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或类似的方式。
喊不清楚
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句