Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在数据库上下文中更新复杂对象失败_C#_Entity Framework - Fatal编程技术网

C# 在数据库上下文中更新复杂对象失败

C# 在数据库上下文中更新复杂对象失败,c#,entity-framework,C#,Entity Framework,我只想更新对象MwbePaymentMethod的简单属性,而不更新复杂属性(最后4个属性是复杂的),因此它将这4个复杂属性更改为未更改。但方法编辑失败: Context.Entry(payment.BillingAddress).State = EntityState.Unchanged; 有误: 附加“MobileWallet.Common.Repository.MWebAddress”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在

我只想更新对象MwbePaymentMethod的简单属性,而不更新复杂属性(最后4个属性是复杂的),因此它将这4个复杂属性更改为未更改。但方法编辑失败:

  Context.Entry(payment.BillingAddress).State = EntityState.Unchanged;
有误:

附加“MobileWallet.Common.Repository.MWebAddress”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”

模型对象:

 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; }
    }
增补1:

我稍微修改了一下代码,我正在读取所有导航字段/对象,尤其是账单地址,它并没有完全填充数据库中的相同数据

 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();
        }
不管

1)
Context.Entry(payment.BillingAddress).State=EntityState.Unchanged

2)
Context.Entry(payment.BillingAddress).State=EntityState.Modified


仍然显示相同的错误。对于我来说,如果我没有从db附加所有属性,那么第2点)应该可以工作,但它不工作。

复杂类型不是实体,因此它们不会被跟踪。他们所属的实体是

要理解为什么这样做有意义,请以这种方式思考: 您的MwbePaymentMethod有一个复杂类型的地址。在数据库中,它们将存储在一个表中,(默认)列名为: 编号,MwbeAddress\u行1,MwbeAddress\u行2,MwbeAddress\u PostalCode

如果更改地址的第1行,则需要更新数据库中整个MwbePaymentMethod表的行。事实上,如果更改属于实体MwbePaymentMethod的任何复杂属性的任何值,将导致整个实体的更新(因为最终它们都属于数据库中的同一个表)

这就是为什么“只更新对象MwbePaymentMethod的简单属性,而不更新复杂属性”是没有意义的

您只能更改上下文中DbSet中实体的状态(Context.Entry(Entity.state=…)(即上下文类中DbSet中的所有X)


看。特别是编辑代码第一行中名为:复杂类型:跨多个类型拆分表的部分将实体附加到上下文:

DbSet.Attach(payment);
注意:
DbSet
没有静态的
Attach
方法。它应该是上下文中定义的
DbSet
属性

完成后,将付款状态设置为“已修改”:

Context.Entry(payment).State = EntityState.Modified;
然后设置所有其他实体的状态。请注意,当您将树附加到上下文时,它将以未更改的状态附加。从MSDN附加文档:

Attach用于使用已知已存在于数据库中的实体重新填充上下文。因此,SaveChanges不会尝试将附加的实体插入数据库,因为假定该实体已经存在。请注意,已经处于其他状态的上下文中的实体将其状态设置为“未更改”。如果实体已处于未更改状态的上下文中,则“附加”为“无操作”

因此,您必须附加到上下文,然后在必要时将状态更改为smetingelse,如added。你在做相反的事


最后验证
payment
对象是否具有正确的id。如果该对象不存在,则必须将其包含在隐藏字段或任何其他表单输入中,以便将其发回服务器。

我已经回答了您在尝试更改复杂类型状态时遇到问题的原因。我刚刚注意到你的代码有另一个问题。执行此操作时,
Context.Entry(payment.State=EntityState.Modified
您有效地将下面的
if(Context.Entry(payment.State==EntityState.Detached)
行设置为始终为false。一个实体不能同时处于两种状态(您正在测试同一个属性,即您刚刚更改的属性)。请参见,其中的共识是“不,他们不应该”!感谢您的回答:):1)在真实即时通讯中使用内部DbSet DbSet,因此DB set是强类型的。2) 我不理解,我附加了修改过的对象,但错误是子对象MwbeAddress已经在系统中。但我没有改变它,只是想把它改成不变的。。。。在数据库中不使用此对象。。。。我不明白你的解释
DbSet.Attach(payment);
Context.Entry(payment).State = EntityState.Modified;