我想只更新对象MwbePaymentMethod的简单属性,没有复杂属性(最后4个属性很复杂),因此它将这4个复杂属性更改为不变。但是方法编辑失败了:
Context.Entry(payment.BillingAddress).State = EntityState.Unchanged;
有错误:
附加“MobileWallet.Common.Repository.MwbeAddress”类型的实体失败,因为同一类型的另一个实体已具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新的并且尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图表,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。
模型对象:
public class MwbePaymentMethod : BaseEntity
{
public enum MethodTypeEnum
{
Creditcard,
Virtualcard,
Wallet
};
public MethodTypeEnum MethodType { get; set; }
public string Number { get; set; }
public DateTime? ExpirationDate { get; set; }
public double Balance { get; set; }
public bool IsPending { get; set; }
public bool IsDefault { get; set; }
public MwbeAddress BillingAddress { get; set; }
public MwbeCurrency Currency { get; set; }
public MwbeUserData UserData { get; set; }
public DateTime? PaymentDate { get; set; }
[JsonIgnore]
public virtual ICollection<MwbePayment> Payments { get; set; }
}
编辑方法:
public override void Edit(MwbePaymentMethod payment)
{
if (payment.Currency != null && payment.Currency.Id != 0)
{
Context.Entry(payment.Currency).State = EntityState.Unchanged;
}
if (payment.UserData != null && payment.UserData.Id != 0)
{
Context.Entry(payment.UserData).State = EntityState.Unchanged;
}
if (payment.BillingAddress != null && payment.BillingAddress.Id != 0)
{
Debugger.Break();
Context.Entry(payment.BillingAddress).State = EntityState.Unchanged;
}
Context.Entry(payment).State = EntityState.Modified;
if (Context.Entry(payment).State == EntityState.Detached)
{
DbSet.Attach(payment);
}
}
ADDED1:
我稍微更改了代码,我正在读取所有导航字段/对象,特别是对于帐单地址而言,该地址未完全填充与数据库中相同的数据。
public void UpdateMwbePaymentMethod(MwbePaymentMethodFilter filter, MwbePaymentMethodDtoInOut mwbepaymentmethod)
{
var currentPaymentMethod = paymentMethodRepository.FindBy(x => x.UserData.Id == filter.userId && x.Id == filter.id);
if (currentPaymentMethod == null || currentPaymentMethod.Count() != 1)
{
throw new DBConcurrencyException();
}
var mwbePaymentPethod = Mapper.Map<MwbePaymentMethod>(mwbepaymentmethod);
//load existing user data
mwbePaymentPethod.UserData = userRepository.Get(filter.userId).Data;
//load existing address with subproperties
mwbePaymentPethod.BillingAddress = addressRepository.FindBy(x => x.Id == mwbePaymentPethod.BillingAddress.Id, x=>x.Merchants, x=>x.PaymentMethods, x=>x.Deliveries, x=>x.UserDatas).SingleOrDefault();
if (mwbePaymentPethod.BillingAddress == null)
{
throw new DBConcurrencyException();
}
paymentMethodRepository.Edit(mwbePaymentPethod);
paymentMethodRepository.SaveChanges();
}
编辑方法:
public override void Edit(MwbePaymentMethod payment)
{
if (payment.Currency != null && payment.Currency.Id != 0)
{
Context.Entry(payment.Currency).State = EntityState.Unchanged;
}
if (payment.UserData != null && payment.UserData.Id != 0)
{
Context.Entry(payment.UserData).State = EntityState.Unchanged;
}
if (payment.BillingAddress != null && payment.BillingAddress.Id != 0)
{
Debugger.Break(); // tutaj byl ostatnio problem
Context.Entry(payment.BillingAddress).State = EntityState.Unchanged;
}
Context.Entry(payment).State = EntityState.Modified;
}
无论是否
1)Context.Entry(payment.BillingAddress).State = EntityState.Unchanged;
或
2)Context.Entry(payment.BillingAddress).State = EntityState.Modified;
仍然显示相同的错误。对我来说,如果我没有从db附加所有属性,那么应该可以工作,但它不起作用。
答案 0 :(得分:0)
复杂类型不是实体,因此不会跟踪它们。他们所属的实体是。
要理解为什么这样做是有道理的: 您的MwbePaymentMethod有一个复杂类型的地址。在数据库中,它们将存储在一个表中,(默认)列名称将为: Number,MwbeAddress_Line1,MwbeAddress_Line2,MwbeAddress_PostalCode,...
如果更改地址的Line1,则需要更新数据库中的整个MwbePaymentMethod表的行。实际上,如果您更改属于实体MwbePaymentMethod的任何复杂属性的任何值,这将导致对整个实体的更新(因为它们最终都属于数据库中的同一个表)。
这就是为什么只更新对象MwbePaymentMethod的简单属性没有意义,没有[更新]复杂属性&#34;
您只能更改上下文中DbSets中实体的状态(Context.Entry(Entity).State = ...)(即Context类中DbSet中的所有X)
见this。特别是名为“复杂类型:跨多个类型拆分表”的部分
答案 1 :(得分:0)
在编辑代码的第一行,将实体附加到上下文:
DbSet.Attach(payment);
注意: DbSet
没有静态Attach
方法。它应该是您在上下文中定义的DbSet<MwbePaymentMethod >
属性。
完成后,请将付款状态设置为已修改:
Context.Entry(payment).State = EntityState.Modified;
然后设置所有其他实体的状态。考虑到,当您将树附加到上下文时,它将以未更改的状态附加。来自MSDN附加文档:
Attach用于使用已知存在于数据库中的实体重新填充上下文。因此,SaveChanges不会尝试将附加实体插入数据库,因为假定它已经存在。请注意,已处于某个其他状态的上下文中的实体的状态将设置为“未更改”。如果实体已处于Unchanged状态的上下文中,则Attach是无操作。
因此,您必须附加到上下文,然后在必要时将状态更改为其他内容。你正在做相反的事情。
最后验证payment
对象是否具有正确的ID。如果不存在,则必须将其包含在隐藏字段或任何其他表单输入中,以便将其发回服务器。