首页 > 解决方案 > 更新实体框架中的多级属性

问题描述

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

在此处输入图像描述

我需要获取与 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);

这就是我得到的:

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

我尝试了此页面中建议的一些解决方案,例如添加复合键等。它也没有用。给出一个例外,如:

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

这是示例数据结构:

"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 的数据和来自数据库的实体以应用更改。我不确定我是否搞砸了一些非常简单的事情。

提前致谢。

标签: c#asp.net-mvcentity-frameworklinqmultiple-tables

解决方案


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

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


推荐阅读