【发布时间】: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