Очень долгое выполнение запросов через DbContext

198
14 февраля 2018, 08:55

Стоит PostgreSQL. В ней таблица с чуть более, чем 300 тысяч строк.

Если я выполняю вот такой запрос в pgAdmin, то он выполняется за доли секунды (~300мс):

SELECT *
FROM public."Movies"
WHERE vote_count > 100
ORDER BY vote_average DESC
LIMIT 10;

Если же выполнить аналогичный запрос в приложении ASP.Net Core, то страница грузится почти минуту (~50c), но если не использовать БД, а просто дать готовую коллекцию аля new Movie[] { ... }, то загрузка практически мгновенная.

//в классе контроллера
private IMovieRepository repository;
public IActionResult Index()
{
    return View(repository.Movies
                            .Where(m => m.VoteCount > 100)
                            .OrderByDescending(m => m.VoteAverage)
                            .Take(10));
}
//класс для работы с данными
public class EFMovieRepository : IMovieRepository
{
    private TMDbContext context;
    public EFMovieRepository(TMDbContext context)
    {
        this.context = context;
    }
    public IEnumerable<Movie> Movies => context.Movies;
}
//класс контекста
public class TMDbContext : DbContext
{
    public TMDbContext() : base() { }
    public TMDbContext(DbContextOptions<TMDbContext> options) : base(options) { }
    public DbSet<Movie> Movies { get; set; }
}
//конфигурация в классе Startup
public Startup(IHostingEnvironment environment)
{
    Configuration = new ConfigurationBuilder()
                            .SetBasePath(environment.ContentRootPath)
                            .AddJsonFile("appsettings.json")
                            .Build();
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TMDbContext>(option =>
        option.UseNpgsql(
            Configuration["Data:Movies:ConnectionString"]));
    services.AddTransient<IMovieRepository, EFMovieRepository>();
    services.AddMvc();
}

Использую Npgsql.EntityFrameworkCore.PostgreSQL

В чём кроется проблема? Может у меня с конфигурацией что-то не так или может запрос надо составлять более правильно? Почему SQL запрос в pgAdmin во столько раз быстрее запроса через провайдера?

UPD: Изменил код метода на:

public string Index()
{
    var startTime = DateTime.Now;
    var movies = repository.Movies
                            .Where(m => m.VoteCount > 100)
                            .OrderByDescending(m => m.VoteAverage)
                            .Take(10).ToList();
    return (DateTime.Now - startTime).TotalSeconds.ToString();
}

Возвращает в среднем 17 секунд.

Answer 1
public IEnumerable<Movie> Movies => context.Movies; 

При обращении к этому свойству и получении результатов запроса сначала загрузится весь Movies, а потом будет применена фильтрация.

Интерфейс IEnumerable находится в пространстве имен System.Collections. Объект IEnumerable представляет набор данных в памяти и может перемещаться по этим данным только вперед. Запрос, представленный объектом IEnumerable, выполняется немедленно и полностью, поэтому получение данных приложением происходит быстро.

При выполнении запроса IEnumerable загружает все данные, и если нам надо выполнить их фильтрацию, то сама фильтрация происходит на стороне клиента.

https://metanit.com/sharp/entityframework/1.4.php

Замените IEnumerable на IQueryable. Тогда отбор будет произведён на стороне БД.

READ ALSO
C# Ribbon сохранение и восстановление Quick Acces ToolBar item&#39;ов

C# Ribbon сохранение и восстановление Quick Acces ToolBar item'ов

Я работаю с элементом Microsoft Ribbon WPF 2010

223
Как правильно принимать файлы в Angular c ASP.NET Core Web API?

Как правильно принимать файлы в Angular c ASP.NET Core Web API?

У меня есть файл на сервере, который я хочу отправить клиентуЯ отправлю его так

306
сериализация xml

сериализация xml

При сериализации xml выкидывает ошибку !

217
Xamarin. Как из ViewModel передавать данные в Model?

Xamarin. Как из ViewModel передавать данные в Model?

Доброе время сутокНе могу победить одну задачку:

210