2017-10-11 84 views
1

下面是我的課:刪除基於狀態的多個ID記錄

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. 

預計產量爲這最後的情況下(標誌=真):

Id  Name Group 
6  ttt  3 
7  ggg  3 

但是我認爲我沒有這樣做是一種正確的方式,並且查詢中有一些改進的來源。

注意: ids []將始終包含來自不同組的id和來自不同組的最高ID。

我該如何改善我的查詢兩種情況(標誌= true和false)?

+1

嗨學習。請回顧一下[我之前提供的]建議(https://stackoverflow.com/questions/46450952/how-to-delete-child-automatically-based-on-parent-deletion-for-database-first-ap#comment79865111_46450952) ,即:當提及自己時,請始終使用大寫字母「I」。英語母語讀者通常覺得它很容易閱讀「我」,而輕微的挫折反應可能會影響到你的幫助._你會記得在你的下一篇文章中解決這個問題嗎? – halfer

回答

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); 
+0

Upvoted爲您的善良努力,幫助我:) –

+0

:)是否有效? – jitender

+0

我沒有得到這個addRange方法 –

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(); 
     } 
    } 
+0

Upvoted爲您的善意而努力,幫助我:) –

+0

可以告訴我關於此行的一些信息:var query = context.Ads.AsQueryable( ); –

+1

也許AsQueryable可以被替換爲像'IQueryable '這樣的轉換。或者不使用'var query = ...',你可以使用'IQueryable query = ...'。 目標是確保下一條語句可以重用相同的變量。當這個語句返回一個IQueryable時,我們不能將DbSet作爲類型來啓動。 如何編寫它取決於您,取決於您希望代碼的可讀性。最後編譯器會優化這個語句。 – verbedr

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()); 
} 
+0

爲什麼你在查詢中使用distinct? –

+0

@Learning讓我們假設'ids'包含1000個屬於同一個groupId的ID。爲什麼我會在「groupIds」中保留重複項? – grek40

+0

這不會是像ids總是會包含來自不同組別的id,並且來自每個組的最高ids –

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(); 
      } 
+1

您應該在其他部分包含該組行,因爲當標誌將是虛假的時, 行將不必執行。 –

+0

Upvoted爲您的慈善努力,幫助我:) –

1

對我來說,它看起來像你有兩個不同的刪除這裏。

在第一種情況下,您只是刪除了具有給定ID的廣告,這非常簡單。

在第二種情況下,你要刪除給定ID的廣告和含有該組的最近刪除的廣告的所有其他廣告。因此,在這種情況下,而不是刪除與指定ID的廣告第一次爲什麼不actualy得到不同的羣體,這些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。

EDIT 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將它逐一刪除。

+0

Upvoted爲您的善良努力,幫助我,但你不認爲更少的linq功能等於更有效率 –

+0

該規則適用於任何地方 - 少功能=效率更高。我描述的僞代碼非常簡單,它缺乏簡單性。 – Rob