Entity Framework возвращает отчет об ошибке - PullRequest
12 голосов
/ 02 апреля 2012

У меня есть PC Enity, у которого есть некоторые свойства, я хотел бы вернуть список отдельных объектов (ПК или сложный тип или что-либо еще) на основе свойства, чтобы связать его с серверными элементами управления, такими как DropDownList. И так как мой метод находится в BLL, я не могу вернуть анонимный тип, поэтому я создал BranchTortType, который имеет две характеристики.

Я написал так, но у него есть повторяющиеся записи:

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 ]

11 голосов
/ 02 апреля 2012

это вернет различные строки для всех столбцов в операторе выбора.Если вам нужны отдельные строки для определенного столбца, просто укажите этот конкретный столбец

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(); 
3 голосов
/ 02 апреля 2012

Я не могу воспроизвести проблему (протестировано с 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 для обоих столбцов, и я получаю ожидаемый отчетливый результат - нетдубликаты в BranchId и BranchName.

2 голосов
/ 02 апреля 2012

Вы получаете дубликаты, потому что Distinct () не может распознать два ваших сложных объекта Branch как идентичные по их свойствам. Он будет просто сравнивать на предмет равенства, который вернет false (потому что вы создаете два разных объекта, но с одинаковыми значениями).

Вы можете использовать Distinct (IQueryable, IEqualityComparer) , чтобы предоставить свой собственный Comparer или реализовать интерфейс IEquatable .

1 голос
/ 04 января 2014

Это работает для меня.

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()
...