Я действительно пытаюсь преобразовать следующий SQL в запрос LINQ. Кто-нибудь может помочь?
select invoice, date, amount, Name
from payments
where invoice in (select invoice
from payments
where invoicelike 'EVENT%'
and status = 3
and date >= '2023-11-01 00:00'
group by invoice
having count(*) > 1)
order by invoice, date desc
Попробуйте это, дело в том, что мы можем использовать dbContext внутри метода Where, который превращается в подзапрос:
var date = new DateTime(2023, 11, 1);
var result = await dbContext.Payments
.Where(p => dbContext.Payments /*Here is the sub query*/
.Where(sub => sub.Invoice.StartWith("EVENT")
&& sub.Status == 3
&& sub.Date >= date)
.GroupBy(sub => sub.Invoice)
.Where(g => g.Count() > 1)
.Select(g => g.Key)
.Contains(p.Invoice)/*This will be translated to IN query*/)
.OrderBy(p => p.Invoice)
.ThenByDescending(p => p.Date)
.Select(p => new
{
p.Invoice,
p.Date,
p.Amount,
p.Name
})
.ToListAsync();
Это будет всего один запрос к базе данных :)
Да, этот запрос можно перевести на LINQ:
var date = new DateTime(2023, 11, 1);
var forFilter = context.Payments
.Where(x => x.Invoice.StartsWith("EVENT") && x.Status == 3 && x.Date > date)
.GroupBy(x => x.Invoice)
.Where(x => x.Count() > 1)
.Select(x => x.Key);
var data = await context.Payments
.Where(x => forFilter.Contains(x.Invoice))
.ToArrayAsync(cancellationToken);
Пример: я реализовал простой пример, используя свою базу данных:
app.MapGet("/get-special", async (ExampleWebApiContext context, CancellationToken cancellationToken) =>
{
var forFilter = context.Movies
.Where(x => x.ReleaseYear > 1000)
.GroupBy(x => x.Id)
.Where(x => x.Count() > 1)
.Select(x => x.Key);
var data = await context.Movies
.Where(x => forFilter.Contains(x.Id))
.ToArrayAsync(cancellationToken);
return data;
});
который произвел запрос по желанию:
@AndrewMorton Хороший улов, исправлено :)
Согласно вашему сценарию, вы можете разбить этот запрос на две части в linq. В первой части выставляйте счет по событию, а затем фильтруйте платежи, чтобы включить только те, чей счет находится в ранее отфильтрованных счетах в первой части.