实体框架返回不同的记录问题

时间:2012-04-02 16:05:21

标签: c# asp.net entity-framework distinct complextype

我有一个PC Enity,它有一些属性,我想基于属性返回一个不同的Object(PC或Complex Type或其他)的列表,以便将它绑定到像DropDownList这样的服务器控件。因为我的方法位于BLL我不能返回匿名类型,所以我创建了一个具有两个peroperties的Branch ComplexType。

我是这样写的,但它有重复的记录:

List<Branch> result = ( from p in _context.PCs
                        where p.UserId== userId
                        select new Branch()
                                   {
                                      BranchId= p.BranchId,
                                      BranchName=p.BranchName
                                   }).Distinct().ToList();

修改: 谢谢大家,这很有效:

List<PC> result = _context.PCs
                  .GroupBy(p=>p.BranchName , p.BranchId})
                  .select(g=>g.First())
                  .ToList();

4 个答案:

答案 0 :(得分:11)

这将为select语句中的所有列返回不同的行。如果您想要特定列的不同行,请指定该特定列

List<Branch> result = ( from p in _context.PCs
                        where p.UserId== userId
                        select new Branch()
                                   {
                                      BranchId= p.BranchId,
                                    }).Distinct().ToList();

如果要基于多个列获取不同的值,则必须创建一个组,然后从该组中选择第一个值。在这种情况下,您不会使用Distinct,例如

List<Branch> distinctResult = _context.PCs
  .GroupBy(p => new Branch {p.BranchId, p.BranchName} )
  .Select(g => g.First())
  .ToList(); 

答案 1 :(得分:3)

我无法重现该问题(使用SQL Server 2008 R2和EF 4.1 / DbContext进行测试)。您问题中的查询...

List<Branch> result = ( from p in _context.PCs
                        where p.UserId== userId
                        select new Branch()
                        {
                            BranchId = p.BranchId,
                            BranchName = p.BranchName
                        })
                        .Distinct()
                        .ToList();

...生成以下SQL:

SELECT 
[Distinct1].[C1] AS [C1],
[Distinct1].[BranchId] AS [BranchId],
[Distinct1].[BranchName] AS [BranchName]
FROM ( SELECT DISTINCT 
       [Extent1].[BranchId] AS [BranchId], 
       [Extent1].[BranchName] AS [BranchName], 
       1 AS [C1]
       FROM [dbo].[PCs] AS [Extent1]
) AS [Distinct1]

这两列都是DISTINCT,我得到了预期的不同结果 - BranchIdBranchName没有重复。

答案 2 :(得分:2)

您得到重复项,因为Distinct()无法将两个复杂的Branch对象识别为与其属性相同。它只是比较对象相等性,它将返回false(因为你创建了两个不同的对象,但具有相同的值)。

您可以使用Distinct(IQueryable, IEqualityComparer)提供自己的Comparer或实现IEquatable界面。

答案 3 :(得分:1)

这适合我。

<强> 1

class RolBaseComparer:IEqualityComparer<RolBase>
{
    public RolBaseComparer()
    {

    }

    public bool Equals(RolBase x, RolBase y)
    {
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
        {
            return false;
        }

        if (Object.ReferenceEquals(x, y))
        {
            return true;
        }

        return x.Id.Equals(y.Id) &&
                x.Nombre.Equals(y.Nombre);
    }

    public int GetHashCode(RolBase obj)
    {
        return obj.Id.GetHashCode() ^ obj.Nombre.GetHashCode();
    }
}

<强> 2

var ResultQuery = (from ES in DbMaster.Estudiantes
                               join I in DbMaster.Inscripciones on ES.strCedula equals I.strCedEstud
                               join C in DbMaster.Carreras on I.strCodCarrera equals C.strCodigo
                               where ES.strCedula.Equals(Cedula)
                               select new RolBase { Id = "EST", Nombre = "Estudiante" }).ToList();

第3

return ResultQuery.Distinct(new RolBaseComparer()).ToList()