Полный набор данных, а не Top 1000 EF Core - PullRequest
3 голосов
/ 16 мая 2019

Я пытаюсь вернуть первые 1000 строк из таблицы, однако, используя EF Core, я получаю полный набор данных до запуска .Take (1000).

API

[HttpGet("MyThing/{id}")]
public List<MyObj> ItemsReport(long id)
{
    response = new List<MyObj>();
    response = _reporting.GetNewEntries(id);
    return response;
}

Отчетность

public virtual List<MyObj> GetNewEntries(long id)
{
    var newEntries = new List<MyObj>();

    var entries = _DbContext.ReportNewEntries
                            .OrderBy(a => long.Parse(a.Id))
                            .Where(a => long.Parse(a.Id) > id)
                            .Take(1000);

    newEntries.AddRange(entries);

    return newEntries;
}

DbContext

DbSet<MyObj> ReportNewEntries{ get; set; }

Мой желаемый запрос выглядит примерно так:

SELECT TOP (1000) * 
FROM dbo.ReportNewEntries 
WHERE CONVERT(bigint, Id) > 0 
ORDER BY CONVERT(bigint, Id)

Мой текущий запрос, согласно профилировщику SQL:

SELECT * FROM dbo.ReportNewEntries 

Таблицамонолитный, поэтому я хочу получить доступ к 1000 строк одновременно.Любые предложения о том, какую ошибку я делаю?

Ответы [ 2 ]

0 голосов
/ 16 мая 2019

Какую базу данных вы используете?Какая версия .NetCore?Какой дб провайдер?У некоторых провайдеров БД могут возникнуть проблемы с переводом некоторых операторов linq в sql.В этом случае запустит другой запрос в базе данных (обычно получит все данные) и выполнит linq в памяти.

0 голосов
/ 16 мая 2019

Когда вы используете List, вы используете Linq-To-Object , который работает на IEnumerable.

И, действительно, IEnumerable сначала загрузитвсе данные в памяти перед применением Возьмите к нему.

То, что вы хотите использовать, это IQueryable, то есть Linq-to-Sql .

Так что либо изменитеваши методы для возврата IQueryable<MyObj> или вызова вашей цепочки Linq с AsQueryable() следующим образом:

var entries = _DbContext.ReportNewEntries.AsQueryable()
    .OrderBy(a => long.Parse(a.Id)).Where(a => long.Parse(a.Id) > id).Take(1000);
...