(代码已简化)
背景说明:
我有一个父类:
namespace Project_Name.Models
{
public class ParentRecord
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public virtual ICollection<ChildDetail> ChildDetails { get; set; }
}
}
和一个儿童班:
namespace Project_Name.Models
{
public class ChildDetail
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public string Value { get; set; }
public Guid ParentRecord_Id { get; set; }
[ForeignKey("ParentRecord_Id")]
public ParentRecord ParentRecord { get; set; }
}
}
我还有名称为<modelName>ViewModel
的ViewModel和几乎完全相同的结构,但没有数据注释,而virtual ICollection
只是List
他们一起形成一对多的关系。 ParentRecord
可以有多个ChildDetails
,ChildDetail
必须与ParentRecord
相关联。
T-SQL表结构如下:
dbo.ParentRecord
+-----------+
| Id |
+-----------+
| <cr_guid> |
+-----------+
dbo.ChildDetail
+-----------+-----------+-----------------+
| Id | Value | ParentRecord_Id |
+-----------+-----------+-----------------+
| <cd_guid> | Some Text | <cr_guid> |
+-----------+-----------+-----------------+
我的问题:
我需要能够根据我的ViewModel更新,添加和/或删除这些子对象。无论它有什么,我想成为最终的结果。
例如,我首先让3 ChildDetails
与ParentRecord
相关,然后在我的视图中更新第1 ChildDetail
,删除第2(或将值留空) ,并留下第三个。
我希望我的最终结果是ParentRecord
剩下两个ChildDetails
,第一个和第三个,第一个更新。
到目前为止我做了什么:
我可以添加和更新ChildDetails
这样做,但它不能处理任何删除:
// ... code related to UnrelatedGranParent model
ParentRecord parentRecord = context.ParentRecords.FirstOrDefault(x =>
x.Id == UnrelatedGrandParentViewModel.ParentViewModel.Id)
// ... code regarding ParentRecord's other not-shown-here properties
// Add or update each Child Detail from the View Model
foreach (var childDetailViewModel in ParentRecordViewModel
.ChildDetailViewModels
.Where(x => !x.Value.IsNullOrWhiteSpace()))
{
// Map the Child Detail View Model to a Model
var childDetail =
Mapper.Map<ChildDetail>(childDetailViewModel);
// Set the ParentRecord_Id property, since that doesn't get mapped
childDetail.ParentRecord_Id = parentRecord.Id;
// Add or update each Child Detail
context.ChildDetails.AddOrUpdate(childDetail);
}
context.ParentRecord.AddOrUpdate(parentRecord);
context.SaveChanges();
所以我希望parentRecord.ChildDetails
设置为传入的任何内容,假设它不为空或空格。
所以我必须删除其他所有内容。
我已尝试循环浏览每个现有ChildDetail
并在其上使用.Remove()
或设置context.Entry(childDetail).State = EntityState.Deleted
或EntityState.Detached
,然后循环显示来自的值视图模型将它们设置为EntityState.Added
或EntityState.Modified
,但在我改变状态或保存更改时,仍然会抛出错误。
我也可以将.Where(x => !x.Value.IsNullOrWhiteSpace())
移动到foreach循环中:
// map the childDetail
if (childDetail.Value.IsNullOrWhiteSpace())
{
context.Entry(childDetail).State = EntityState.Deleted;
continue;
}
context.ChildDetails.AddOrUpdate(childDetail);
但这并不能解释那些根本没有传入的人,而且我不知道直接设置EntityStates是否是一个好习惯。
答案 0 :(得分:0)
感谢DevilSuichiro的评论,我能够找到这个简单的解决方案,我只需检查上下文中的每个ChildDetail
是否存在于ViewModel的ChildDetails
列表中,如果不存在:delete它!
// Add or update each Child Detail from the View Model
foreach (var childDetailViewModel in callDetailsViewModel.ParentRecordViewModel
.ChildDetailViewModels)
{
// Map the Child Detail View Model to a Model
var childDetail =
Mapper.Map<ChildDetail>(childDetailViewModel);
// Set the ParentRecord_Id property, since that doesn't get mapped
childDetail.ParentRecord_Id = parentRecord.Id;
// Delete those that are null or whitespace
if (childDetail.Value.IsNullOrWhiteSpace())
{
context.Entry(childDetail).State = EntityState.Deleted;
continue;
}
// Add or update each Child Detail
context.ChildDetails.AddOrUpdate(childDetail);
}
// For each contextChildDetail in the context, where they have matching Parent Record Id...
foreach (var contextChildDetail in context.ChildDetail.Where(x => x.ParentRecord_Id == parentRecord.Id))
{
// ... and if we can't find it in the ViewModel list, then delete it
if (callDetailsViewModel.ParentRecordViewModel.ChildDetailViewModels.FirstOrDefault(
x => x.Id == contextChildDetail.Id) == null)
{
context.ChildDetail.Remove(contextChildDetail);
}
}