【发布时间】:2015-04-28 15:28:08
【问题描述】:
我想修改实体支付对象,包含未修改的现有货币对象并将其保存到 EF 数据库:
public Payment()
{
int Id {get;set;}
public int Value {get;set;}
public Currency SelectedCurrency{get;set;}
}
public Currency()
{
int Id {get;set;}
string Name;
}
我的 Edit 方法如下所示:
public override void Edit(MwbePaymentMethod payment)
{
if (payment.Currency != null && payment.Currency.Id != 0 && Context.Entry(payment.UserData).State != EntityState.Unchanged)
{
Context.Entry(payment.Currency).State = EntityState.Unchanged;
}
Context.Entry(payment).State = EntityState.Modified;
}
关于 Edit 方法的几句话:它将包含的子实体 Currency 更改为 Unchanged,因为它不会被更新。但是当行
Context.Entry(payment).State = EntityState.Modified;
被调用,显示错误:
附加“付款”类型的实体失败,因为同一类型的另一个实体已经具有相同的主键值。这个可以 使用“附加”方法或设置状态时发生 如果图中的任何实体具有,则实体为“未更改”或“已修改” 键值冲突。这可能是因为一些实体是新的并且 尚未收到数据库生成的键值。在这种情况下使用 'Add' 方法或 'Added' 实体状态来跟踪图形和 然后将非新实体的状态设置为“未更改”或“已修改”为 合适。
我也尝试使用DbSet.Attach(payment) 方法,但也报错。
添加1: 这是我调用 Edit 方法的外部方法。它调用 Context.Save 并按 Id 读取支付实体。
public void UpdateMwbePaymentMethod(MwbePaymentFilter filter, MwbePaymentDtoInOut mwbepayment)
{
var currentPayment = paymentMethodRepository.FindBy(x => x.UserData.Id == filter.userId && x.Id == filter.id);
if (currentPayment==null || currentPayment.Count() != 1)
{
throw new DBConcurrencyException();
}
var mwbePayment = Mapper.Map<MwbePayment>(mwbepayment);
mwbePayment.UserData = userRepository.Get(filter.userId).Data;
paymentRepository.Edit(mwbePayment);
paymentRepository.SaveChanges();
}
添加2: 我在两个 Find 查询中都添加了 AsNoTracking。我被报告为补救措施。但是现在标记为已分离的其他实体,当调用方法 DbSet.Attach(payment) 时,它会给出错误
附加类型为“MobileWallet.Common.Repository.MwbeAddress”的实体失败,因为同一类型的另一个实体已经具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新实体,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图形,然后将非新实体的状态设置为“未更改”或“已修改”。
添加 3: 添加方法 FindBy:
public IEnumerable<TEntity> FindBy(Expression<Func<TEntity, bool>> predicate, params Expression<Func<TEntity, object>>[] includes)
{
IQueryable<TEntity> query = DbSet.AsNoTracking().Where(predicate);
if (null != includes)
{
foreach (var include in includes)
{
query = query.AsNoTracking().Include(include);
}
}
IEnumerable<TEntity> result = query.AsEnumerable();
return result;
}
【问题讨论】:
-
这背后的原因是什么?如果你不主动修改货币,它不会改变?!
-
你使用oracle DB吗?
-
@Technovation:我正在使用 MS SQL Express 2013。
-
@Mario The Spoon:我想更新支付对象而不更新现有的货币子对象。 :)
-
只需执行 context.SaveChanges() - EF 将自行检测任何更改。此外,在比较的第二部分中,您使用 payment.UserData - 此属性甚至不会出现在您的代码中
标签: c# entity-framework