我有一对多关系,正在尝试更新但收到错误消息
数据库操作预期会影响1行,但实际上会影响0行。自加载实体以来,数据可能已被修改或删除。有关了解和处理乐观并发异常的信息,请参见http://go.microsoft.com/fwlink/?LinkId=527962。
已更新
只要受益人集合没有更改或更新,更新方法就可以使用。
代码类似于
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
private readonly List<Beneficiary> _beneficiaries;
public IEnumerable<Beneficiary> Beneficiaries => _beneficiaries;
public void AddBeneficiary(string name)
{
var beneficiary = new Beneficiary(Id, name);
_beneficiaries.Add(beneficiary);
}
}
public sealed class Beneficiary
{
public int Id { get; set; }
public int EmployeeId { get; private set; }
public string Name { get; private set; }
public Beneficiary(int employeeId, string name)
{
Name = name;
EmployeeId = employeeId;
}
}
//Extracted from repo method
public void Update(TEntity entity)
{
if (entity != null)
_dbSet.Update(entity);
}
// Extracted Actual update from application service
if (incomingEmployee.Beneficiaries.Any())
{
if (employeeFromStore.Beneficiaries.Any())
{
employeeFromStore.Beneficiaries.ToList()
.ForEach(existingBeneficiary =>
employeeFromStore.RemoveBeneficiary(existingBeneficiary)); //Method skipped for brevity
//Tried calling this too
//_employeeRepository.UnitOfWork.SaveChanges();
}
incomingEmployee.Beneficiaries.ToList().ForEach(beneficiary =>
{
employeeFromStore.AddBeneficiary(beneficiary.Name);
});
}
_employeeRepository.Update(employeeFromStore);
_employeeRepository.UnitOfWork.SaveChanges();
我觉得问题在于跟踪器如何处理导航属性集合的更新,但我可能是错的。
我还试图通过以下方法使用变更跟踪器进行更新
public void ApplyCurrentValues<TEntity>(TEntity original, TEntity current)
where TEntity : class
{
//if it is not attached, attach original and set current values
base.Entry<TEntity>(original).CurrentValues.SetValues(current);
}
有人知道怎么做吗?
答案 0 :(得分:0)
在阅读了有关更新的工作原理后,我终于取得了进展。基本上如上所述here ,以及此issue。调用Update方法时,整个实体的状态(包括所有通过导航属性可访问的实体)的状态都标记为已修改。 如果您试图将受益人添加到现有员工中,则SaveChanges()会抛出异常,因为它希望使用提供的主键来修改记录,但在数据库中找不到该记录。更新方法似乎不是最佳选择。
我选择使EmployeeRepository中的存储库库中的Update方法可重写,如下所示
//Update method in the repository base
//Made method virtual to enable overriding
public virtual void Update(TEntity entity)
{
if (entity != null)
_dbSet.Update(entity);
}
//Update method from EmployeeRepository
public override void Update(Employee employee)
{
var employeeFromStore = _unitOfWork.Employees.Where(p => p.Id == employee.Id)
.Include(p => p.Beneficiaries)
.SingleOrDefault();
if (employeeFromStore != null)
{
context.Entry(employeeFromStore).CurrentValues.SetValues(employee);
//Replacing the whole collection
foreach (var beneficiary in employeeFromStore.Beneficiaries)
{
if (employee.Beneficiaries.Any())
context.Entry(beneficiary).State = EntityState.Deleted;
}
//Adding new collection
foreach (var beneficiaryToAdd in employee.Beneficiaries)
{
var newBeneficiary = new Beneficiary(beneficiaryToAdd.EmployeeId, beneficiaryToAdd.Name);
employeeFromStore.AddBeneficiary(newBeneficiary.Name);
}
}
}
我相信,可以针对特定情况对这一答案进行改进或调整。例如,除了清除保留的收藏集之外,还可以选择更新