C# 在实体框架中更新多对多关系
情况:我有一个类似于标签的东西:用户可以更改某个实体的标签列表。实体和标记具有多对多关系 问题:用户可以添加一些新标签,删除一些旧标签,保留一些标签,而无需更改。例如:C# 在实体框架中更新多对多关系,c#,entity-framework,many-to-many,C#,Entity Framework,Many To Many,情况:我有一个类似于标签的东西:用户可以更改某个实体的标签列表。实体和标记具有多对多关系 问题:用户可以添加一些新标签,删除一些旧标签,保留一些标签,而无需更改。例如: 之前:a、b、c 在:b,c,d之后 标签a已删除,标签d已添加。通过最小化SQL查询的数量,最有效的方法是什么 可能的解决方案: 我找到了两种解决方案,但我认为它们并不好 删除所有旧标记并添加新标记 // entityId - editing entity's id // tagIds - new tags ids
- 之前:a、b、c
- 在:b,c,d之后
a
已删除,标签d
已添加。通过最小化SQL查询的数量,最有效的方法是什么
可能的解决方案:
我找到了两种解决方案,但我认为它们并不好
// entityId - editing entity's id
// tagIds - new tags ids
var entity _entityRepository.GetAll()
.Include(x => x.Tags)
.FirstOrDefault(x => x.Id == entityId);
entity.Tags.RemoveAll();
// Add new tags
entity.Tags = _tagsRepository.GetAll()
.Where(x => tagIds.Contains(x.Id)); //Yes, this .Contains works
_entityRepository.Update(entity);
// entityId - editing entity's id
// tagIds - new tags ids
var entity _entityRepository.GetAll()
.Include(x => x.Tags)
.FirstOrDefault(x => x.Id == entityId);
// Add tags which not exists in entity.Tag
foreach (var tagId in tagIds)
{
if (!entity.Tags.Any(x => x.Id == tagId))
{
//A lot of queiries!
var newTag = _tagsRepository.GetAll()
.FirstOrDefault(x => x.Id == tagId);
entity.Tags.Add(newTag);
}
}
// Remove tags whic not exists in tagIds
// Assuming Tags is IList<T> and we can use []
int i = 0;
while (i < entity.Tags.Count)
{
if (!tagIds.Contains(entity.Tags[i].Id))
entity.Tags.RemoveAt(i);
else
i++;
}
_entityRepository.Update(entity);
//entityId-编辑实体的id
//标记ID-新标记ID
var实体_entityRepository.GetAll()
.Include(x=>x.Tags)
.FirstOrDefault(x=>x.Id==entityId);
//添加实体.Tag中不存在的标记
foreach(tagId中的var tagId)
{
if(!entity.Tags.Any(x=>x.Id==tagId))
{
//很多地方!
var newTag=_tagsRepository.GetAll()
.FirstOrDefault(x=>x.Id==tagId);
实体.Tags.Add(newTag);
}
}
//删除标记ID中不存在的标记
//假设标签是IList,我们可以使用[]
int i=0;
而(i
- 很少有SQL查询
- 移除所有关系并创建新关系,无论它们是否发生变化
- 使用
加载所有Include
标记
- 否全部删除
- 为加载每个新标记进行了大量查询
- 使用
加载所有Include
标记
这个问题的最佳解决方案是什么?不要比较任何东西,不要实现检查哪些标志被删除,哪些标志被添加的“逻辑”
相反,只需为实体指定一个新的标记列表,并告诉实体框架保存对象。它将自行确定哪些必须删除,哪些需要添加。出于好奇,当您只有
tagid
列表时,这是如何工作的?如何获得分配给实体*的新标记列表?如果您创建了一个包含新标记对象的列表,并且只分配了Id属性,那么我的测试显示EF尝试插入标记记录和链接记录。我做了一些测试,知道这一点:1。您加载标签集合并分配新集合-它可以工作。2-您没有加载旧集合并分配新集合-结果将是两个集合的关联。@Alexeymarov为完整起见,您是否可以使用基于此答案的工作实现(例如选项3)更新您的帖子(或发布自我答案),并进行与1和2相同的分析/比较。