根据条件删除具有多个ID的记录

时间:2017-10-11 11:42:22

标签: c# entity-framework linq

以下是我的课程:

 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)?

5 个答案:

答案 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,它将逐个删除它。