Entity Framework 6 большой запрос в наследовании - PullRequest
0 голосов
/ 15 октября 2018

У меня есть стратегия наследования Table per Type (TPT) с абстрактным классом «Task» с множеством конкретных классов (например, 30 классов).Когда я пытаюсь показать рабочий список «для выполнения задач», например, запрашивая у EF абстрактный класс, или когда я пытаюсь получить обобщенную задачу по ID, EF делает запрос в 10000 строк, соединяющий каждый конкретный класс, что приводит к очень медленным результатам.Есть способ настроить EF, чтобы избежать большого запроса?В методе рабочего списка мне нужны только поля абстрактного класса.

Это мой код:

    public Task GetTaskById(int id) {
        return this.repository.Tasks.Where(t => t.ID == id).FirstOrDefault();
    }

    public IQueryable<Task> GetWorklist() {
        return this.repository.Tasks.Where(t => a.ActivitySate.Code == ActivitySateEnum.TO_DO);
    }

Спасибо

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Реляционные базы данных не очень хорошо справляются с концепцией наследования. Для структуры сущностей было изобретено несколько стратегий для имитации наследования.

Какая стратегия подходит вам больше всего, зависит от того, какие запросы и обновления вы выполняете чаще всего.

Предположим, выиметь класс Person и два конкретных вида Persons: Teachers и Students.Существуют две популярные стратегии реализации наследования

Таблица на тип (TPT)

Каждый класс представлен в отдельной таблице.В нашем примере создаются три таблицы: таблица Persons, таблица Teachers с внешним ключом к Person таковому и таблица Students с внешним ключом к данным Person Student.

Если вы спросите: «дайте мне Persons, что ...», необходимо проверить только одну таблицу.Однако, если вы спросите: «дайте мне Students who ...», тогда потребуется объединение между таблицей Persons и таблицей Students.

Если вы добавляете / обновляете / удаляетеодна Student, затем необходимо обновить две таблицы.

Если в будущем необходимо добавить один столбец к одному из классов, будет задействована только одна таблица.

Добавление нового видаPerson, как и Sponsors, легко, однако они должны быть Persons и наследовать все Person столбцы.Если позже вы решите, что Sponsor больше не является Person, у вас возникли проблемы.

Этот метод наиболее подходит, если вы гораздо чаще запрашиваете Persons, чем Students и * 1044.*.Это менее подходит, если вы часто спрашиваете Students with Person data.Также, если вы добавляете / удаляете / обновляете Students очень часто, не используйте этот метод.

Также используйте этот метод, если вам нужно создать Person, который не является ни Teacher, ни Student пока, но позже может стать одним из них, или может быть и Teacher и Student

Таблица для класса бетона (TPC)

Для * 1058 нет отдельной таблицы,Все свойства Person находятся в таблице Teachers, а также в таблице Students.

Запросы «Учащиеся, которые ...» или «Учителя, которые ...» будут включать только одну таблицу.Однако запрос «Лица, которые ...» будет включать в себя объединение данных, извлеченных из таблицы Students, с данными, извлеченными из таблицы Teachers.

Добавить / Удалить / Обновить Student всегда будет включатьодна таблица.

Добавление столбца в Student предполагает изменение одной таблицы.Однако добавление столбца к Person предполагает изменение таблиц Students и Teachers.

Добавление нового вида Person, скажем Janitors или Sponsors, очень просто.Это не будет проблемой, если в будущем Sponsor больше не будет Person.

Вы не можете создать Person, это всегда должно быть либо Teacher, либоStudent.Student никогда не может стать Teacher, он станет новым Person (что кажется немного ироничным :-).Нет Student также может быть Teacher.

Используйте этот метод, если вы редко запрашиваете Persons who ..., но чаще всего запрашиваете Students who ...

Заключение

Стратегия выбора наследства зависит от того, как вы будете использовать свои таблицы.

Кажется, у вас 30 типов Persons, реализованных как TPC (нет отдельной таблицы Persons).Если вы запрашиваете Persons who ..., ваша база данных должна объединить результаты из всех 30 таблиц.

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

0 голосов
/ 15 октября 2018

Проблема в том, что вы используете репозиторий ba, который не возвращает IQueryable, поэтому он не позволяет EF фактически использовать фильтры, которые у вас есть (да?), Где вы ограничиваете возвращаемые данные только некоторыми полями.

Итак, что нужно сделать, так это материализовать сущность (которая является стандартом SOOOO для хранилища антипаттерна).И вот вы идете .... для этого .... НУЖНО присоединиться к TPT.Это 30 классов, что означает более 30 таблиц.Во-первых, в запросе, скорее всего, нет 10 тыс. Строк.Во-вторых, это нормально и мало для действительно сложного SQL (который у вас есть).В-третьих, вы сами это настраиваете - да, это то, что нужно для извлечения всех данных.

Решение?Избавьтесь от suplus репозитория (вы знаете, DbContext - это репозиторий), а затем создайте фильтр на основе базового типа и убедитесь, что ТОЛЬКО необходимые поля проецируются в анонимный класс, поэтому EF МОЖЕТ выполнить оптимизацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...