2012-11-09 79 views
1

我很確定這屬於「UNION」場景下,但我真的只是尋找解決我的問題的最佳方法(即使它不是UNION )。LINQ - 合併兩個查詢並排除第一個查詢中的項目

我有一個查詢,看起來像這樣:

var query = context.AffiliateConfigurations.Where(x => x.AffiliateId == affiliateId).Select(config => new ViewModels.ConfigurationItem 
       { 
        ConfigurationId = config.AffiliateConfigurationId, 
        ConfigKey = config.ConfigKey, 
        ConfigValue = config.ConfigValue, 
        UpdatedDate = config.UpdatedDate, 
        ConfigurationType = ViewModels.ConfigurationType.Affiliate 
       }); 

我想要做的是一些結果添加到該查詢。我有另一個名爲SiteConfiguration的表,它具有EXACT相同的模式,但我只想添加那些ConfigKey在我的原始查詢中不存在的行中的行。

我有一些像目前是以下(和它的作品),但我正在尋找一個「純粹」的LINQ的方式來做到這一點:

var items = context.AffiliateConfigurations.Where(x => x.AffiliateId == affiliateId).Select(config => new ViewModels.ConfigurationItem 
    { 
     ConfigurationId = config.AffiliateConfigurationId, 
     ConfigKey = config.ConfigKey, 
     ConfigValue = config.ConfigValue, 
     UpdatedDate = config.UpdatedDate, 
     ConfigurationType = ViewModels.ConfigurationType.Affiliate 
     }).ToList(); 

var query = context.SiteConfigurations.Select(config => new ViewModels.ConfigurationItem 
{ 
    ConfigurationId = config.SiteConfigurationId, 
    ConfigKey = config.ConfigKey, 
    ConfigValue = config.ConfigValue, 
    UpdatedDate = config.UpdatedDate 
}); 

foreach (var item in query) 
{ 
    if (items.All(x => x.ConfigKey != item.ConfigKey)) 
    { 
     items.Add(item); 
    } 
} 
+0

你試過用Except()嗎? http://msdn.microsoft.com/en-us/library/system.linq.enumerable.except.aspx – Hardrada

回答

2

所以你的問題是"I have two collections and i want to merge them.how do i exclude items from the second collection,if the item's property is matching with another item's property on the first list."

是LINQ的聯盟,你在這樣的情況下需要什麼

所有你需要做的是寫一個簡單的比較器類(實現的IEqualityComparer接口)爲您ConfigurationItem

class ConfigEqualityComparer : IEqualityComparer<ConfigurationItem> 
{ 

    public bool Equals(ConfigurationItem a, ConfigurationItem b) 
    { 
     if (a.ConfigKey == b.ConfigKey) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 

    public int GetHashCode(ConfigurationItem a) 
    { 
      //do some hashing here 
      //int hCode = IntegerField1^IntegerField2; 
      return hCode.GetHashCode(); 
    } 

} 

這就是你need.You現在可以運行聯合查詢,讓你的預期輸出。

var comparer = new ConfigEqualityComparer(); 
var result = Enumerable.Union<ConfigurationItem>(items, query, comparer); 
1

我認爲LINQ聯盟運營商是你想要的。你只需要創建一個類來實現你的物品的接口IEqualityComparer<T>。這裏是一些演示代碼。嘗試使用沒有比較器的foreach以查看包含的模糊,或者將它們移除。我在LINQPad中運行代碼,如果您使用的是Visual Studio,則需要將Main方法移動到類中並調用它。

void Main() 
{ 
    List<DataObject> set1 = new List<DataObject>(); 
    List<DataObject> set2 = new List<DataObject>(); 

    set1.Add(new DataObject("a")); 
    set1.Add(new DataObject("b")); 
    set1.Add(new DataObject("c")); 
    set1.Add(new DataObject("d")); 
    set1.Add(new DataObject("e")); 

    set2.Add(new DataObject("c")); 
    set2.Add(new DataObject("d")); 
    set2.Add(new DataObject("e")); 
    set2.Add(new DataObject("f")); 
    set2.Add(new DataObject("g")); 
    set2.Add(new DataObject("h")); 

    // try as 
    // foreach (DataObject d in set1.Union(set2)) { 
    // and dupes will be present 

    foreach (DataObject d in set1.Union(set2, new DOComparer())) { 
     Console.WriteLine(d); 
    } 
} 

// Define other methods and classes here 
public class DataObject { 
    public DataObject(string value) { 
     Value = value; 
    } 
    public string Value {get;private set;} 

    public override string ToString() { 
     return Value; 
    } 
} 

public class DOComparer:IEqualityComparer<DataObject> { 
    public bool Equals(DataObject do1, DataObject do2) { 
     return do1.Value.Equals(do2.Value); 
    } 

    public int GetHashCode(DataObject d) { 
     return d.Value.GetHashCode(); 
    } 
}