Преобразование SQL-запроса в LINQ или свободный синтаксис LINQ - PullRequest
1 голос
/ 08 июня 2019

У меня есть SQL-запрос, подобный этому

SELECT T.*
FROM 
(
SELECT ServiceRecords.DistrictId, Districts.Name as DistrictName, COUNT(Distinct(NsepServiceRecords.ClientRegNo)) AS ClientsServedCount 
FROM ServiceRecords
INNER JOIN Districts ON ServiceRecords.DistrictId = Districts.ID
INNER JOIN NsepServiceRecords ON NsepServiceRecords.ServiceRecordId = ServiceRecords.Id
WHERE ServiceRecords.CreatedAtUtc >= @StartDate
AND ServiceRecords.CreatedAtUtc <= @EndDate
AND ServiceRecords.DistrictId = @DistrictId
GROUP BY ServiceRecords.DistrictId, Districts.Name
) AS T
ORDER BY T.DistrictName ASC, T.DistrictId

Результаты запроса:

DistrictId                              DistrictName    ClientsServedCount
8d059005-1e6b-44ad-bc2c-0b3264fb4567    Bahawalpur      117
27ab6e24-50a6-4722-8115-dc31cd3127fa    Gujrat          492
14b648f3-4912-450e-81f9-bf630a3dfc72    Jhelum          214
8c602b99-3308-45b5-808b-3375d61fdca0    Lodhran         23
059ffbea-7787-43e8-bd97-cab7cb77f6f6    Muzafarghar     22
580ee42b-3516-4546-841c-0bd8cef04df9    Peshawar        211

Я пытаюсь преобразовать это в LINQ для запроса сущностей. Я хочу получить те же результаты (кроме столбца Идентификатор района), используя LINQ.

Я пытался так, но не работал, как ожидалось. Может кто-нибудь сказать мне, что я делаю не так?

_dbContext.ServiceRecords
.Include(x => x.District)
.Include(x=>x.NsepServiceRecords)
.GroupBy(x => x.DistrictId)
.Select(x => new DistrictClientsLookUpModel
{
    DistrictName = x.Select(record => record.District.Name).FirstOrDefault(),
    ClientsServedCount = x.Sum(t=> t.NsepServiceRecords.Count)
});

Классы моделей такие же

public class BaseEntity
{
    public Guid Id { get; set; }
}

public class NsepServiceRecord : BaseEntity
{
    public DateTime CreatedAtUtc { get; set; }

    public Guid ServiceRecordId { get; set; }

    public string ClientRegNo { get; set; }
    // other prop .......

    public virtual ServiceRecord ServiceRecord { get; set; }
}

public class ServiceRecord : BaseEntity
{
    public DateTime CreatedAtUtc { get; set; }
    public string DistrictId { get; set; }

    public virtual District District { get; set; }
    public virtual ICollection<NsepServiceRecord> NsepServiceRecords { get; set; }

}

public class DistrictClientsLookUpModel
{
    public string DistrictName { get; set; }
    public int ClientsServedCount { get; set; }
}

Я использую Microsoft.EntityFrameworkCore, Version 2.2.4

EDIT Я тоже так пробовал

var startUniversalTime = DateTime.SpecifyKind(request.StartDate, DateTimeKind.Utc);
var endUniversalTime = DateTime.SpecifyKind(request.EndDate, DateTimeKind.Utc);
return _dbContext.NsepServiceRecords
.Join(_dbContext.ServiceRecords, s => s.ServiceRecordId,
    r => r.Id, (s, r) => r)
.Include(i => i.District)
.Where(x => x.DistrictId == request.DistrictId
            && x.CreatedAtUtc.Date >= startUniversalTime
            && x.CreatedAtUtc.Date <= endUniversalTime)
.OrderBy(x => x.DistrictId)
.GroupBy(result => result.DistrictId)

.Select(r => new DistrictClientsLookUpModel
{
    DistrictName = r.Select(x=>x.District.Name).FirstOrDefault(),
    ClientsServedCount = r.Sum(x=>x.NsepServiceRecords.Count())
});

Еще одна попытка,

from s in _dbContext.ServiceRecords
join record in _dbContext.NsepServiceRecords on s.Id equals record.ServiceRecordId
join district in _dbContext.Districts on s.DistrictId equals district.Id
group s by new
{
    s.DistrictId,
    s.District.Name
}
into grp
select new DistrictClientsLookUpModel
{
    DistrictName = grp.Key.Name,
    ClientsServedCount = grp.Sum(x => x.NsepServiceRecords.Count)
};

Это занимает слишком много времени, я ждал две минуты, прежде чем убил запрос.

UPDATE

EF ядро ​​имеет проблемы перевод GroupBy запросов на сторону сервера

Ответы [ 2 ]

2 голосов
/ 10 июня 2019

Предполагая, что District имеет свойство навигации по коллекции в ServiceRecord, как и должно быть, например, что-то вроде

public virtual ICollection<ServiceRecord> ServiceRecords { get; set; }

Вы можете избежать GroupBy, просто запустив запрос с District и используя простую проекцию Select, следуя указаниям по навигации:

var query = _dbContext.Districts
    .Select(d => new DistrictClientsLookUpModel
    {
        DistrictName = d.Name,
        ClientsServedCount = d.ServiceRecords
            .Where(s => s.CreatedAtUtc >= startUniversalTime && s.CreatedAtUtc <= endUniversalTime)
            .SelectMany(s => s.NsepServiceRecords)
            .Select(r => r.ClientRegNo).Distinct().Count()
    });
0 голосов
/ 08 июня 2019

Вы, кажется, не выполняете объединение должным образом.

Посмотрите на это: Регистрация / Где с LINQ и Lambda

Вот начало запроса linq, я не уверен, даст ли это вамвполне то, что вы хотите, но это хорошее начало.

По сути, в методе .Join сначала необходимо указать сущность, к которой будет присоединено.Затем вам нужно решить, к чему они будут присоединены, в данном случае district => district.Id, serviceRecord => serviceRecord.Id.

_dbContext.ServiceRecords
.Join( _dbContext.District,district=> district.Id, serviceRecord=> serviceRecord.Id)
.Join(_dbContext.NsepServiceRecords, Nsep=> Nsep.ServiceRecord.Id,district=>district.Id)
.GroupBy(x => x.DistrictId)
.Select(x => new DistrictClientsLookUpModel
{
  DistrictName = x.Select(record => record.District.Name).FirstOrDefault(),
  ClientsServedCount = x.Sum(t=> t.NsepServiceRecords.Count)
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...