对象更新过程没有改变一个属性的值
本文关键字:一个 属性 更新过程 改变 对象 | 更新日期: 2023-09-27 18:02:17
我的应用程序有2个类:PaymentMethod
&Currency
(Currency
是PaymentMethod
的性质)。当我的应用程序用Currency
属性的新值更新PaymentMethod
时(值已经存在于db中,但它被分配给PaymentMethod
),在SaveCHanges
方法之后,Currency
属性仍然包含旧值。为什么?:)
这是我的应用程序如何替换货币对象的值:
if (String.Compare(existingPaymentMethod.Currency.Code, mwbepaymentmethod.CurrencyCode, true) !=0)
{
var readCurrency = currencyRepo.FindByCode(mwbepaymentmethod.CurrencyCode);
existingPaymentMethod.Currency = readCurrency;
}
paymentMethodRepository.Save(ref existingPaymentMethod);
return true;
PaymentMethod
&Currency
类:
public class PaymentMethod : BaseEntity
{
public enum MethodTypeEnum
{
Creditcard,
Virtualcard,
Wallet
};
public MethodTypeEnum MethodType { get; set; }
public int VendorId { get; set; }
public virtual Address BillingAddress { get; set; }
public virtual Currency Currency { get; set; }
}
public class Currency : BaseEntity
{
[JsonProperty("code")]
[Key]
public string Code { get; set; }
[JsonProperty("symbol")]
public string Symbol { get; set; }
[JsonIgnore]
public virtual ICollection<Payment> Payments { get; set; }
[JsonIgnore]
public virtual ICollection<PaymentMethod> PaymentMethods { get; set; }
}
编辑方法:public override void Edit(MwbePaymentMethod entityToUpdate)
{
DbSet.Attach(entityToUpdate);
Context.Entry(entityToUpdate).State = EntityState.Modified;
//manual update of properties
//Context.Entry(entityToUpdate.BillingAddress).State = EntityState.Modified;
//Context.Entry(entityToUpdate.Currency).State = EntityState.Unchanged;
}
OnModelCreating
方法:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MobileWalletContext>());
...
modelBuilder.Entity<MwbePaymentMethod>().HasRequired(e => e.Currency).WithMany(e => e.PaymentMethods);
base.OnModelCreating(modelBuilder);
}
Autofac定义的数据库上下文:
builder.RegisterType<MobileWalletContext>().As<IMwbeDbContext>().InstancePerRequest();
更新1 :EF日志显示没有货币字段更新:
UPDATE [dbo].[MwbeAddress] SET [Street] = @0, [City] = @1, [ZipCode] = @2, [Country] = @3 WHERE ([Id] = @4)
-- @0: 'FFFF12' (Type = String, Size = -1)
-- @1: 'GlasgowSSSS' (Type = String, Size = -1)
-- @2: 'B33 8TH' (Type = String, Size = -1)
-- @3: 'England' (Type = String, Size = -1)
-- @4: '2' (Type = Int32)
-- Executing at 2015-07-13 07:35:48 +02:00
-- Completed in 39 ms with result: 1
UPDATE [dbo].[MwbePaymentMethod] SET [MethodType] = @0, [VendorId] = @1, [Number] = @2, [ExpirationDate] = @3, [Balance] = @4, [IsPending]
= @5, [IsDefault] = @6 WHERE ([Id] = @7)
-- @0: '1' (Type = Int32)
-- @1: '0' (Type = Int32)
-- @2: '4444 4444 4444 4450' (Type = String, Size = -1)
-- @3: '2015-10-10 00:00:00' (Type = DateTime2)
-- @4: '0' (Type = Double)
-- @5: 'True' (Type = Boolean)
-- @6: 'False' (Type = Boolean)
-- @7: '3' (Type = Int32)
-- Executing at 2015-07-13 07:35:48 +02:00
-- Completed in 7 ms with result: 1
为什么没有更新Currency
属性?
设置实体的状态(Added
除外)只影响实体的标量属性,不影响其导航属性,也不影响其关联。
你有三个选择:
选项1
将货币附加到上下文。在你的Edit
方法中:
Context.Entry(entityToUpdate).State = EntityState.Modified;
Context.Entry(entityToUpdate.Currency).State = EntityState.Unchanged;
现在EF知道Currency
被分配给PaymentMethod
,所以它知道关联改变了,它将更新数据库中的外键。
但是我不认为这样对你有用。从你的问题陈述中,我了解到currencyRepo
和paymentMethodRepository
不共享相同的上下文,否则你一开始就不会有问题(货币已经附加)。你不能将一个实体附加到两个上下文,所以currencyRepo
的上下文应该在那一点上被处理,或者你应该首先将货币从它分离出来。相当费力。
选项2
让currencyRepo
和paymentMethodRepository
(以及所有存储库)在一个工作单元中共享相同的上下文实例。无论如何,这都是推荐的,不仅仅是为了解决这个问题。
选项3
不设置Currency
属性,但添加一个原始外键属性PaymentMethod.CurrencyId
,并在货币变化时修改该属性。这是一个标量属性,因此它将响应设置EntityState.Modified
。
DbSet.Attach
不是递归的。您需要附加所有涉及的实体:
public override void Edit(MwbePaymentMethod entityToUpdate)
{
DbSet.Attach(entityToUpdate);
Context.Entry(entityToUpdate).State = EntityState.Modified;
if(entityToUpdate.BillingAddress != null)
{
DbSet.Attach(entityToUpdate.BillingAddress);
Context.Entry(entityToUpdate.BillingAddress).State = EntityState.Modified;
}
if(entityToUpdate.Currency != null)
{
DbSet.Attach(entityToUpdate.Currency);
Context.Entry(entityToUpdate.Currency).State = EntityState.Modified;
}
//manual update of properties
//Context.Entry(entityToUpdate.BillingAddress).State = EntityState.Modified;
//Context.Entry(entityToUpdate.Currency).State = EntityState.Unchanged;
}
这个问题是因为PaymentMethod类中没有定义外键关系。这需要被指定,以便特定的列将用于更新,如果货币是新的,那么将插入相同的代码,并将根据currencycode保存。
public class PaymentMethod : BaseEntity
{
public enum MethodTypeEnum
{
Creditcard,
Virtualcard,
Wallet
};
public MethodTypeEnum MethodType { get; set; }
public int VendorId { get; set; }
public virtual Address BillingAddress { get; set; }
public string CurrencyCode {get;set;} //Replace with actual column name
[ForeignKey("CurrencyCode ")]
public virtual Currency Currency { get; set; }
}