Entity Framework Table для каждого типа производительности - PullRequest
6 голосов
/ 10 января 2011

Получается, что я последний, кто обнаружил фундаментальный уровень, который существует в Microsoft Entity Framework при реализации наследования TPT (Table Per Type).

Создав прототип с 3 подклассами,Базовая таблица / класс, состоящий из 20+ столбцов и дочерние таблицы, состоящие из ~ 10 столбцов, все работало прекрасно, и я продолжил работу над остальной частью приложения, доказав эту концепцию.Теперь пришло время добавить 20 других подтипов и OMG, я только начал просматривать генерируемый SQL на простом select, хотя мне интересен только доступ к полям базового класса.

Эта страница содержит прекрасное описание проблемы.

Кто-нибудь пошел в производство, используя TPT и EF, есть ли какие-либо обходные пути, которые будут означать, что я выиграл?Не нужно: a) Преобразовать схему в TPH (что противоречит всему, чего я пытаюсь достичь с помощью моей конструкции БД - urrrgghh!)?б) переписать с другим ORM?

Как я вижу, я должен иметь возможность добавить ссылку на хранимую процедуру из EF (возможно, с использованием EFExtensions), в которой есть TSQL, который выбирает только те поля, которые янеобходимость, даже использование кода, сгенерированного EF для монстра UNION / JOIN внутри SP, предотвратит генерирование SQL при каждом вызове - не то, что я намеревался бы сделать, но вы поняли идею.

Убийца, которого я обнаружил, заключается в том, что при выборе списка сущностей, связанных с базовой таблицей (но выбранная сущность не является таблицей подкласса), и я хочу отфильтровать поpk Базовой таблицы, и я делаю .Include("BaseClassTableName"), чтобы разрешить мне фильтровать, используя x=>x.BaseClass.PK == 1 и получить доступ к другим свойствам, здесь также выполняется генерация исходного SQL.

Я не могу использовать EF4, так как я ограничен средами выполнения .net 2.0 с установленным 3.5 SP1.

У кого-нибудь есть опыт выхода из этого беспорядка?

Ответы [ 2 ]

2 голосов
/ 14 января 2011

Мы столкнулись с этой же проблемой и рассматриваем возможность переноса нашего DAL с EF4 на LLBLGen из-за этого.

Тем временем мы использовали скомпилированные запросы, чтобы облегчить некоторые изболь:

скомпилированные запросы (LINQ to Entities)

Эта стратегия не предотвращает гигантские запросы, но время, необходимое для генерации запроса (что можетбыть огромным) выполняется только один раз.

Вы можете использовать скомпилированные запросы с Include (), например:

static readonly Func<AdventureWorksEntities, int, Subcomponent> subcomponentWithDetailsCompiledQuery = CompiledQuery.Compile<AdventureWorksEntities, int, Subcomponent>(
       (ctx, id) => ctx.Subcomponents
            .Include("SubcomponentType")
            .Include("A.B.C.D")
            .FirstOrDefault(s => s.Id == id));

    public Subcomponent GetSubcomponentWithDetails(int id)
    {
        return subcomponentWithDetailsCompiledQuery.Invoke(ObjectContext, id);
    }
1 голос
/ 10 января 2011

Это кажется немного запутанным.Вы говорите о TPH, но когда вы говорите:

С моей точки зрения, я могу добавить ссылку на хранимую процедуру из EF (возможно, с использованием EFExtensions), которая имеетTSQL, который выбирает только те поля, которые мне нужны, даже используя код, сгенерированный EF для монстра UNION / JOIN внутри SP, предотвратит генерирование SQL при каждом вызове - не то, что я намеревался бы сделать, но вы получитеидея.

Что ж, это отображение таблицы на конкретный класс (используется метод, а не таблица, но все же отображение - TPC ...).EF поддерживает TPC, но дизайнер - нет. Вы можете сделать это сначала в коде, если получите CTP .

Ваше предпочтительное решение использования процедуры вызовет проблемы с производительностью, если вы ограничите запросы, например:

var q = from c in Context.SomeChild
        where c.SomeAssociation.Foo == foo
        select c;

Оптимизатор БД не может видеть реализацию proc, поэтому вы получаете полное сканирование результатов.

Итак, прежде чем сказать себе, что это исправит ваши результаты, перепроверьте это предположение.

Обратите внимание, что вы всегда можете указать пользовательский SQL для любой стратегии сопоставления с ObjectContext.ExecuteStoreQuery .

Однако, прежде чем делать что-либо из этого,Учтите, что, как указывает RPM1984, ваш дизайн, по-видимому, злоупотребляет наследованием.Мне нравится эта цитата из NHibernate в действии

[A] задайте себе вопрос, не лучше ли переделать наследование как делегирование в объектной модели.Сложного наследования часто лучше избегать по разным причинам, не связанным с постоянством или ORM.[Ваш ORM] действует как буфер между объектной и реляционной моделями, но это не значит, что вы можете полностью игнорировать проблемы постоянства при проектировании вашей объектной модели.

...