以下是我的课程:
public partial class Ads
{
public int Id { get; set; }
public int RegionId { get; set; }
public string Name { get; set; }
public int Group { get; set; }
}
记录:
Id Name Group
1 abc 1
2 xyz 1
3 lmn 1
4 xxx 2
5 ppp 2
6 ttt 3
7 ggg 3
现在我想删除所有记录/仅针对某些ID删除具有相同组ID的记录。
代码:
public void Delete(int[] ids,bool flag = false)
{
using (var context = new MyEntities())
{
context.Ads.RemoveRange(
context.Ads.Where(t => (flag ?
(context.Ads.Any(x => ids.Contains(x.Id) && x.Group == t.Group)) : false)));
context.SaveChanges();
}
}
我想做的事情如下:
If flag is false with ids=3,5 then
I want to delete only records with Id=3,5
Else if flag is true with ids=3,5 then
I want to delete records with Id=3,5 but all other records too of the group to which ids=3,5 belong to.
Here id=3 belongs to group 1 so I want to delete all records of group1 i.e id=1,2 like wise ids=5 belongs to
group 2 so I want to delete all records of group 2 i.e id=4.
最后一种情况的预期输出(flag = true):
Id Name Group
6 ttt 3
7 ggg 3
但我认为我没有这样做是一种正确的方法,并且查询中有一些改进的来源。
注意: ids []将始终包含来自不同组的ID以及来自不同组的最高ID。
如何改善对这两种情况的查询(flag = true和false)?
答案 0 :(得分:2)
怎么样?
var removeRecs=context.Ads.where(t => ids.contains(t.id))
if(flag)
removeRecs.AddRange(context.Ads.where(t=> removeRecs.Any(r =>t.groupId==r.Id)))
Ads.RemoveRange(removeRecs);
答案 1 :(得分:1)
不要让自己太难,不是必须/可以在查询的where语句中完成所有事情。循环中的一般经验法则试图将所有常量值和检查分解出来。所以试试这个:
public static void Delete(int[] ids, bool flag = false)
{
using (var context = new MyEntities())
{
var query = context.Ads.AsQueryable();
query = flag
? query.Where(x => context.Ads
.Where(i => ids.Contains(i.Id))
.Select(i => i.Group)
.Contains(x.Group))
: query.Where(x => ids.Contains(x.Id));
context.Ads.RemoveRange(query);
context.SaveChanges();
}
}
答案 2 :(得分:1)
你应该分开你的任务......
if (flag)
{
groupIds = db.Ads.Where(x => ids.Contains(x.Id)).Select(x => x.Group).ToList();
db.Ads.RemoveRange(db.Ads.Where(x => groupIds.Contains(x.Group)).ToList());
}
else
{
db.Ads.RemoveRange(db.Ads.Where(x => ids.Contains(x.Id)).ToList());
}
答案 3 :(得分:1)
public void Delete(int[] ids, bool flag = false)
{
using (var context = new MyEntities())
{
var items = context.Ads.Where(x => ids.Any(a => x.Id == a));
if (!flag)
{
//flag=false --> delete items with Id in ids[]
context.Ads.RemoveRange(items);
}
else
{
var groups = items.GroupBy(a => a.Group).Select(a => a.Key);
//flag=true --> delete all items in selected groups
context.Ads.RemoveRange(context.Ads.Where(x => groups.Any(a => x.Group == a)));
}
context.SaveChanges();
}
答案 4 :(得分:1)
对我来说,这里看起来有两个不同的删除。
在第一种情况下,您只是删除具有指定ID的广告,这非常简单。
在第二种情况下,您要删除包含指定ID的广告以及包含最近删除的广告组的所有其他广告。因此,在这种情况下,不要首先删除具有给定Id的广告,为什么不实际为这些ID-s获取不同的组,而不仅仅是删除组。
修改强>
你可以这样做。
using (var context = new TestEntities())
{
if (!flag)
context.Ads.RemoveRange(context.Ads.Where(a => ids.Contains(a.Id)));
else
context.Ads.RemoveRange(context.Ads.Where(a => context.Ads.Where(g => ids.Contains(g.Id)).Select(x => x.Group).Distinct().Contains(a.Group)));
context.SaveChanges();
}
对于更复杂的情况,我试图获得给定id-s的不同组。所以对于ID-s 3和5,我选择的是组,而不是我在组上做区别,因为可能发生id-s具有相同的组。我正在获取所有包含这些组的广告。因此,对于3和5的传递值,我将获得第1组和第2组,我将使用它来获取具有该组的所有广告。反过来,这将产生id-s 1,2,3,4和5,我将删除它。
编辑2
如果第二个Linq查询的复杂性比编写SQL查询困扰你。
context.Database.ExecuteSqlCommand(
"DELETE Ads WHERE Group IN (SELECT Group FROM Ads WHERE Id IN(@p1, @p2))", new SqlParameter("@p1", ids[0]), new SqlParameter("@p2", ids[1]));
这应该是额外的性能,而不是依赖于EF,它将逐个删除它。