C# 如何使用LINQ(.NET 4)执行不同的查询?

C# 如何使用LINQ(.NET 4)执行不同的查询?,c#,linq,entity-framework,.net-4.0,C#,Linq,Entity Framework,.net 4.0,我有一个objectset,希望对集合执行一个DISTINCT。返回的对象每个都有大约10个属性。我想使用属性,所以投影实际上不是一个选项。在10个属性中,我只希望将DISTINCT应用于其中两个字段(DistrictId和ContactId)。如何做到这一点?您需要编写自己的或获得一个DistinctBy方法的实现,该方法允许您在保留序列类型的同时对序列内容的投影信息执行区分 提供。由于您只需要在DistrictId和ContactId组合方面不同的元素,因此可以使用GroupBy,然后决定如

我有一个objectset,希望对集合执行一个DISTINCT。返回的对象每个都有大约10个属性。我想使用属性,所以投影实际上不是一个选项。在10个属性中,我只希望将DISTINCT应用于其中两个字段(DistrictId和ContactId)。如何做到这一点?

您需要编写自己的或获得一个
DistinctBy
方法的实现,该方法允许您在保留序列类型的同时对序列内容的投影信息执行区分


提供。

由于您只需要在DistrictId和ContactId组合方面不同的元素,因此可以使用
GroupBy
,然后决定如何处理重复项。本例中的每个组表示属于一个不同组合的项目

var results = context.MyCollection
                     .GroupBy( x=> new { x.DistrictId, x.ContactId })
                     .Select(...)

您可以尝试构造匿名类型来处理此情况。 假设有10个属性的类是元素

public class Element
    {
        public int FirstProp { get; set; }
        public int SecondProp { get; set; }

       //others 8 cool properties
    }
使用linq中的扩展方法提取所需内容的查询:

IList<Element> element = new List<Element>();


            var result = new { P1 = element
                                .Select(X => X.FirstProp).Distinct()
                            ,
                               P2 = element
                                    .Select(X => X.SecondProp).Distinct()
                            ,
                                element
                               // do projections here over others 8 properties


            };
IList元素=新列表();
var结果=新的{P1=元素
.Select(X=>X.FirstProp).Distinct()
,
P2=元素
.Select(X=>X.SecondProp).Distinct()
,
要素
//在其他8个属性上做投影
};

我们可以定义一个扩展方法,对T的IEnumerable执行如下操作:

public static class EnumerableExtensions
        {

            /// <summary>
            /// Returns a ienumerable which is distinct by a given property key selector. If a custom equality 
            /// comparer is to be used, pass this in as the comparer. By setting the comparer default to null,
            /// the default comparer is used. 
            /// </summary>
            /// <typeparam name="T">The item type in the ienumerable</typeparam>
            /// <typeparam name="TKey">The type of the key selector (property to disinct elements by)</typeparam>
            /// <param name="coll">The source ienumerable</param>
            /// <param name="keySelector">The key selector, use a member expression in a lambda expression</param>
            /// <param name="comparer">Custom comparer to use, pass in null here to specify that default comparer is used,
            /// however, this is default set to null and not required parameter</param>
            /// <returns></returns>
            public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> coll, Func<T, TKey> keySelector,
                IEqualityComparer<TKey> comparer = null)
            {
                if (coll == null)
                    throw new ArgumentNullException("coll");
                if (keySelector == null)
                    throw new ArgumentNullException("keySelector");

                var result = coll.GroupBy(keySelector, comparer).Select(g => g.First()).ToList();
                return new List<T>(result).AsEnumerable();
            }

        }
然后输出为:

Model: Audi, Make: A4, Color: Black
Model: Audi, Make: A8, Color: Red
Model: Volvo, Make: XC90, Color: Black
Model: Ferrari, Make: F500, Color: Yellow
Model: Ferrari, Make: F500, Color: Red
Model: Lada, Make: Limousine, Color: Rusty
Press any key to continue ...

我们没有得到项目“奥迪TT黑色”,因为我们已经有一辆黑色奥迪。我们没有得到“沃尔沃S90黑色”,因为我们已经得到了一辆黑色沃尔沃。我们都买了法拉利F500,因为它们有不同的颜色。可悲的是,我们被困在“拉达轿车生锈”,因为它是唯一的组合模式和颜色

。。。并使用
Tuple.Create(x.DistrictId,x.ContactId)
作为键选择器,如果只需要每组中的一个,请使用
Select(g=>g.First())
Model: Audi, Make: A4, Color: Black
Model: Audi, Make: A8, Color: Red
Model: Volvo, Make: XC90, Color: Black
Model: Ferrari, Make: F500, Color: Yellow
Model: Ferrari, Make: F500, Color: Red
Model: Lada, Make: Limousine, Color: Rusty
Press any key to continue ...