EF:对象更新过程未更改一个属性的值 [英] EF: object update process is not changing value of one property

查看:160
本文介绍了EF:对象更新过程未更改一个属性的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序有2个类: PaymentMethod & Currency Currency PaymentMethod 的属性)。当我的应用程序确实更新了 PaymentMethod 且新值为 Currency 属性时(该值已存在于db中,但已分配给 PaymentMethod ),在 SaveCHanges 方法之后, Currency 属性仍然包含旧值。 为什么?:)

my application has 2 classes: PaymentMethod & Currency (Currency is property of PaymentMethod). When my app does update of PaymentMethod with new value of Currency propery (value already exists in db but it's being assigned to PaymentMethod), after SaveCHanges method, Currency property still contains old value. WHY?:)

这是我的应用替换货币对象值的方式:

this is how my application replaces Currency object value:

 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 & 货币类:

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定义的数据库上下文:

DB context defined by Autofac:

builder.RegisterType<MobileWalletContext>().As<IMwbeDbContext>().InstancePerRequest();

更新1
EF日志未显示货币字段更新:

Update 1: EF logs shows no currency field update:

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 属性?

Why there is not update for Currency property?

推荐答案

设置实体的状态(已添加除外)仅影响实体的标量属性,而不影响其导航属性,其 associations

Setting an entity's state (other than Added) only affects the entity's scalar properties, not its navigation properties, its associations.

因此,您有三个选择:

将货币附加到上下文。在您的 Edit 方法中:

Attach the currency to the context. In your Edit method:

Context.Entry(entityToUpdate).State = EntityState.Modified;
Context.Entry(entityToUpdate.Currency).State = EntityState.Unchanged;

现在EF知道分配给<$ c的货币 $ c> PaymentMethod ,因此它知道关联已更改,它将更新数据库中的外键。

Now EF knows the Currency that is assigned to PaymentMethod, so it knows the association changed, and it will update the foreign key in the database.

但是我不要以为这样对您有用。从您的问题陈述中,我了解到 currencyRepo paymentMethodRepository 不会共享相同的上下文,否则您将不会拥有首先遇到问题(货币已经附加)。您不能将一个实体附加到两个上下文中,因此 currencyRepo 的上下文应在此时处理,或者您首先应将货币与其分离。

But I don't think this is going to work for you just like that. From your problem statement I understand that currencyRepo and paymentMethodRepository don't share the same context, otherwise you wouldn't have had the problem in the first place (the currency would already be attached). You can't attach an entity to two contexts, so either currencyRepo's context should be disposed at that point, or you should detach the currency from it first. Pretty laborious.

currencyRepo paymentMethodRepository (以及该问题的所有存储库)在一个工作单元中共享同一上下文实例。无论如何,建议这样做,不仅是为了解决这个问题。

Let currencyRepo and paymentMethodRepository (and all repositories for that matter) share the same context instance within one unit of work. This is recommended anyway, not only to solve this problem.

不要设置货币属性,但添加原始外键属性 PaymentMethod.CurrencyId 并在币种更改时修改该属性。这是一个标量属性,因此它将响应设置 EntityState.Modified

Don't set the Currency property, but add a primitive foreign key property PaymentMethod.CurrencyId and modify that property if the currency changes. This is a scalar property, so it will respond to setting EntityState.Modified.

这篇关于EF:对象更新过程未更改一个属性的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆