【发布时间】:2017-10-05 15:19:17
【问题描述】:
我有以下 sn-p 代码,几个月来我一直在使用它来更新 Client 的数据模型,其值通过 ViewModel 传回。
我正在使用 LINQ 过滤从客户端传递的电子邮件 CC 值集合,这是一个字符串列表,并使用指定的电子邮件地址创建 EmailCC 对象的新实例,然后将其分配给客户端 EmailCCs 是一对多的关系映射。我期望的正确行为是打破先前输入的电子邮件抄送之间的关系,然后使用新输入的值。
更新到最新版本的 EF Core 后,我在尝试更新时收到以下异常,我相信我理解这是由于在同一上下文中删除和修改 EmailCCs 集合所致。
InvalidOperationException:无法跟踪实体类型“EmailCC”的实例,因为已经在跟踪具有相同键的该类型的另一个实例。添加新实体时,对于大多数键类型,如果未设置键(即,如果键属性为其类型分配了默认值),则会创建一个唯一的临时键值。如果您为新实体显式设置键值,请确保它们不会与现有实体或为其他新实体生成的临时值发生冲突。附加现有实体时,请确保只有一个具有给定键值的实体实例附加到上下文。
我的 EmailCC 主键列是数据库生成的。
Post方法代码是
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(
[Bind("Id,FirstName,LastName,Email,EmailCc")] ClientEditViewModel clientEditViewModel)
{
if (!ModelState.IsValid) return View(clientEditViewModel);
Client client =
_dbContext.Client.Include(p => p.EmailCCs).SingleOrDefault(p => p.Id == clientEditViewModel.Id);
client.FirstName = clientEditViewModel.FirstName;
client.LastName = clientEditViewModel.LastName;
client.Email = clientEditViewModel.Email;
client.EmailCCs =
clientEditViewModel.EmailCc.Where(p => !string.IsNullOrWhiteSpace(p))
.Select(p => new EmailCC { Email = p }).ToList();
await _dbContext.SaveChangesAsync();
return RedirectToAction(nameof(Edit), new { id = client.Id });
}
EmailCC 类是
public class EmailCC
{
[Column("ID")]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public int Id { get; set; }
public string Email { get; set; }
}
客户端类:
public class Client
{
[Column("ID")]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public virtual ICollection<EmailCC> EmailCCs { get; set; }
}
我是否以错误的方式解决这个问题,如果是这样,如果我不关心该集合中的值,只要它们被新值覆盖,替换集合的正确方法是什么?
【问题讨论】:
-
你能发
EmailCC类吗 -
@IvanStoev 更新为包括
EmailCC和Client类 -
您的
EmailCCPK 列不是数据库生成的。可能应该删除[DatabaseGenerated(DatabaseGeneratedOption.Computed)]或使用[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
标签: c# asp.net-core entity-framework-core