LINQ - 合并两个查询并从第一个查询中排除项目

时间:2012-11-09 04:35:36

标签: c# linq entity-framework

我很确定这属于“UNION”情景,但我真的只是寻找解决问题的最佳方法(即使它不是UNION)。

我有一个如下所示的查询:

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的表,它具有完全相同的模式,但我只想添加来自该表的行,而原始查询中尚不存在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);
    }
}

2 个答案:

答案 0 :(得分: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的UNION是您在这种情况下所需要的

您需要做的就是为ConfigurationItem

编写一个简单的Comparer类(实现IEqualityComparer接口)
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();
    }

}

这就是您所需要的。您现在可以运行UNION查询并获得预期的输出。

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

答案 1 :(得分:1)

我认为LINQ Union运算符就是你想要的。您只需要创建一个实现项目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();
    }
}