【问题标题】:Updating multiple level properties in Entity Framework更新实体框架中的多级属性
【发布时间】:2020-03-06 08:11:40
【问题描述】:

我有一个具有多级属性的实体结构,每个头表条目都有多个子表条目,并且关系经过多个级别。表图如下:

我需要获取与 ECNEntries 表中的一个条目相关的所有数据以显示在网格中。用户可以在所有级别编辑条目、删除一些条目、添加更多条目。

我可以像这样获取特定条目的所有数据:

var ECNEntryInDb = ECNEntriesRepo.FindAll(f => f.ECNStages
                                .Select(i => i.ECNComponentDetails
                                    .Select(j => j.ECNMaterialReferenceDetails
                                        .Select(k => k.ECNComponentDetails))))
                                        .Where(x => x.Id == ECNEntriesData.Id).FirstOrDefault();

但我找不到将这些数据更新回数据库的方法。

当我这样尝试时:

var xx = Mapper.Map<DAL.Entities.ECNEntries>(ECNEntriesData);
ECNEntriesRepo.Update(xx);

我遇到了一个异常:

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

当我尝试这个时:

var ECNEntryInDb = ECNEntriesRepo.FindAll(f => f.ECNStages
                                    .Select(i => i.ECNComponentDetails
                                        .Select(j => j.ECNMaterialReferenceDetails
                                            .Select(k => k.ECNComponentDetails)))).Where(x => x.Id == ECNEntriesData.Id).FirstOrDefault();
                                //var ECNEntryInDb = ECNEntriesRepo.FindById(ECNEntriesData.Id);

Mapper.Map<BL.DTO.ECN.ECNEntries, DAL.Entities.ECNEntries>(ECNEntriesData, ECNEntryInDb);
ECNEntriesRepo.Update(ECNEntryInDb);

这是我得到的:

操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

我尝试了page 中建议的一些解决方案,例如添加复合键等等。它也没有用。 给出如下异常:

添加与处于已删除状态的实体的关系是 不允许

这是示例数据结构:

"EcnEntries": [
                {
                    "Id": 49,
                    "ECNHeaderId": 11,
                    "ECNVersionId": 8,
                    "ECNVersion": null,
                    "ECNPartNumber": "280384-01/01M",
                    "ECNStages": [
                        {
                            "Id": 25,
                            "ECNEntriesId": 49,
                            "OperationNo": "006",
                            "WorkCenterId": 198,
                            "ChangesRequired": "asxa",
                            "ReasonForChanges": "erte",
                            "ECNComponentDetails": [
                                {
                                    "Id": 31,
                                    "ECNStagesId": 25,
                                    "CurrentBOMPartNumber": "jhjhk",
                                    "ReplacementComponentPartnumber": "uyuyuy",
                                    "ECNMaterialReferenceDetails": [
                                        {
                                            "Id": 38,
                                            "ECNComponentDetailsId": 31,
                                            "MaterialReferenceNumber": "323"
                                        },
                                        {
                                            "Id": 39,
                                            "ECNComponentDetailsId": 31,
                                            "MaterialReferenceNumber": "12"
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]

编辑

这就是存储库实现中的更新功能所做的。如何更改引用子表对象的状态?

public void Update(T entity)
        {
            contextFactory.GetDataContext().Entry(entity).State = EntityState.Modified;
        }

谁能建议一种更新这些数据的方法?我是否需要遍历每个孩子并更新数据?在那种情况下,我也很困惑如何同时遍历来自 UI 的数据和来自数据库的实体以应用更改。我不确定我是否搞砸了一些非常简单的事情。

提前致谢。

【问题讨论】:

  • Mapper.Map 指令是否失败?我认为不需要。
  • 我认为问题在于维护实体的状态。但我不知道如何更改引用子表条目的状态。
  • 当使用实体完成查询时,每个对象都有一个属性 ISChanged 设置为 false。当对象发生更改时,IsChanged 属性设置为 true。然后,当更新完成时,数据库中的所有 IsChanged 值都会更新。
  • @jdweng 所以,如果我有一个引用子对象的数据集,并且还更新了子对象中的一些属性值,那么在更新对象时,子对象的状态也会改变?这里似乎不会发生。我可以以某种方式显式设置所有更改的子对象的状态吗?在我的情况下,可以有多个级别的父子关系,如上述示例数据中给出的那样。所以我应该遍历每个级别并更改属性价值观?
  • 你使用的是什么类型的数据库?

标签: c# asp.net-mvc entity-framework linq multiple-tables


【解决方案1】:

正如@jdweng 所说,问题出在Automapper 上。 发现这个link 有用。

自动映射器正在替换引用子表对象,最终将引用设置为空。它触发了错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    相关资源
    最近更新 更多