gpt4 book ai didi

c# - 插入一对多记录

转载 作者:行者123 更新时间:2023-11-30 17:45:29 25 4
gpt4 key购买 nike

我遇到了有关 Entity Framework 插入的问题。

我的应用程序有以下两个实体:

  • 备忘录
  • 员工

一个备忘录可以与多个员工链接。
一个员工可以链接多个备忘录。

这意味着多对多关系。我读了几篇文章向我解释应该创建联结表,我认为这是显而易见的。

文章让我学会了让 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; }

当使用包管理器控制台更新我的数据库时,已在数据库中创建了一个联结表。我使用以下行完成此操作:
更新数据库-force -verbose

我有一个创建新备忘录的 View 。可以在此处选择员工列表并将他们添加到备忘录中。然而,填充这个联结表并没有按计划进行。我认为这与我的存储库的设置有关。我创建了一个 MemoRepository 和一个 EmployeeRepository。

我的 Controller 处理备忘录创建如下:

内存 Controller

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:

An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

更新时出现的错误2:

The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.

我该如何解决这个问题,我阅读了一些主题,有人说它与使用不同的上下文有关,其他人说它与 Attach() 有关,但我不知道如何解决在我的应用程序中解决这个问题。

如果您需要更多信息,请告诉我。

注意:为了便于阅读,我省略了一些代码。如果需要,当然可以添加代码。

最佳答案

您收到第一个错误是因为您正在添加传入上下文的 Memo 对象。但是添加到 Controller 内备忘录对象的员工对象是使用另一个 dbContext 检索的。要解决这个问题,您必须在两个操作之间共享数据库上下文,或者您必须明确地将 Employee 对象附加到当前上下文。

选项 1: Controller 代码

[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 或类似的东西。

有什么不清楚的就大声说

关于c# - 插入一对多记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27564802/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com