Есть модель EF из C#-классов, допустим, с базовым типом и 100 наследников различной степени вложенности.
Маппинг "таблица на конкретный тип" (каждая таблица содержи только записи своего типа, и все поля всех предков).
Читаем в модель через DBSet все строки типа Base.
В некоторых случаях EF генерит простой sql "select ... from Base", а в других — огромный развесистый union всех наследных типов. (Размер sql-запроса может достигать сотен kb, и ползает всё это неприлично долго).
От чего зависит это поведение? Я пока обнаружил только что наследные типы включаются в запрос если в иерархии сущностей присутствуют абстрактные классы.
Можно ли данным поведением управлять не меняя модель, а в рантайме, по-разному для разных типов и навигационных свойств?
Друга ищи не того, кто любезен с тобой, кто с тобой соглашается, а крепкого советника, кто полезного для тебя ищет и противится твоим необдуманным словам.
Re: EF6 code first, загрузка наследников, огромный select union
Здравствуйте, Osaka, Вы писали:
O>Есть модель EF из C#-классов, допустим, с базовым типом и 100 наследников различной степени вложенности. O>Маппинг "таблица на конкретный тип" (каждая таблица содержи только записи своего типа, и все поля всех предков). O>Читаем в модель через DBSet все строки типа Base.
Очевидно это потребует чтения всех таблиц и union all
Как иначе получить все экземпляры, унаследованные от base?
O>В некоторых случаях EF генерит простой sql "select ... from Base", а в других — огромный развесистый union всех наследных типов. (Размер sql-запроса может достигать сотен kb, и ползает всё это неприлично долго). O>От чего зависит это поведение? Я пока обнаружил только что наследные типы включаются в запрос если в иерархии сущностей присутствуют абстрактные классы.
Покажи код запроса и какой sql он генеирует, пока непонятно является ли такой SQL избыточным или он генерирует ровно то, что нужно.
O>Можно ли данным поведением управлять не меняя модель, а в рантайме, по-разному для разных типов и навигационных свойств?
Можно, если сделать проекцию.
Re: EF6 code first, загрузка наследников, огромный select union
Здравствуйте, Osaka, Вы писали:
O>От чего зависит это поведение? Я пока обнаружил только что наследные типы включаются в запрос если в иерархии сущностей присутствуют абстрактные классы. O>Можно ли данным поведением управлять не меняя модель, а в рантайме, по-разному для разных типов и навигационных свойств?
OfType пробовал?
context.Set<Base>().OfType<Child2>().ToList();
Re[2]: EF6 code first, загрузка наследников, огромный select union
G>непонятно является ли такой SQL избыточным или он генерирует ровно то, что нужно.
Математически там всё верно, вытаскивает все наследные типы. Но мне это в одних задачах нужно, а в других недопустимо.
O>>Можно ли данным поведением управлять не меняя модель, а в рантайме, по-разному для разных типов и навигационных свойств? G>Можно, если сделать проекцию.
"Проекция" в данном контексте это что?
Друга ищи не того, кто любезен с тобой, кто с тобой соглашается, а крепкого советника, кто полезного для тебя ищет и противится твоим необдуманным словам.
Re[2]: EF6 code first, загрузка наследников, огромный select union
G>Слона не приметил... EF6 это же не EfCore6? G>Я бы от первого отказался в пользу второго.
Чем он лучше?
Читал что-то про это EF Core несколько лет назад, они обещали когда-нибудь научиться делать всё что умеет древний EF, но наследование таблиц не умели. Сдвинулось что-то с этим вопросом?
Друга ищи не того, кто любезен с тобой, кто с тобой соглашается, а крепкого советника, кто полезного для тебя ищет и противится твоим необдуманным словам.
Re[2]: EF6 code first, загрузка наследников, огромный select union
В некотором смысле работает. Позволяет ограничить вычитываемую иерархию указанным типом и его наследниками. Но только если модель такая, что sql union вообще генерится. Я этого достиг тем, что в иерархии есть абстрактные классы (каждый Child N наследуется от abstract ChildNBase:ChildN-1). А если абстрактные классы добавить в modelbuilder.Ignore, то sql union не генерится, OfType выдаёт ошибку DbOfTypeExpression requires an expression argument with a polymorphic result type that is compatible with the type argument.
По-прежнему непонятно, по какому признаку EF решает, что надо тащить через 1 sql всех наследников, а не только указанный тип.
Друга ищи не того, кто любезен с тобой, кто с тобой соглашается, а крепкого советника, кто полезного для тебя ищет и противится твоим необдуманным словам.
Re[3]: EF6 code first, загрузка наследников, огромный select union
Здравствуйте, Osaka, Вы писали:
G>>Слона не приметил... EF6 это же не EfCore6? G>>Я бы от первого отказался в пользу второго.
O>Чем он лучше? O>Читал что-то про это EF Core несколько лет назад, они обещали когда-нибудь научиться делать всё что умеет древний EF, но наследование таблиц не умели. Сдвинулось что-то с этим вопросом?
Лучше спроектирован, быстрее, запросы эффективнее. TPT есть, но и они же предупреждают что это очень неэффективной способ хранения данных.
Минус что для новых версии надо апдейтится к .NET 6
Re[3]: EF6 code first, загрузка наследников, огромный select union
O>В некотором смысле работает. Позволяет ограничить вычитываемую иерархию указанным типом и его наследниками. Но только если модель такая, что sql union вообще генерится. Я этого достиг тем, что в иерархии есть абстрактные классы (каждый Child N наследуется от abstract ChildNBase:ChildN-1). А если абстрактные классы добавить в modelbuilder.Ignore, то sql union не генерится, OfType выдаёт ошибку DbOfTypeExpression requires an expression argument with a polymorphic result type that is compatible with the type argument. O>По-прежнему непонятно, по какому признаку EF решает, что надо тащить через 1 sql всех наследников, а не только указанный тип.
Мой кристальный шар сегодня сломался. Могу гадать только по реальным LINQ запросам.
Re[3]: EF6 code first, загрузка наследников, огромный select union
Здравствуйте, Osaka, Вы писали:
G>>непонятно является ли такой SQL избыточным или он генерирует ровно то, что нужно. O>Математически там всё верно, вытаскивает все наследные типы. Но мне это в одних задачах нужно, а в других недопустимо.
O>>>Можно ли данным поведением управлять не меняя модель, а в рантайме, по-разному для разных типов и навигационных свойств? G>>Можно, если сделать проекцию. O>"Проекция" в данном контексте это что?
Проекция это когда выбрасываются Include и пишется хардкорный Select )
Re: EF6 code first, загрузка наследников, огромный select union
Здравствуйте, Osaka, Вы писали:
O>Есть модель EF из C#-классов, допустим, с базовым типом и 100 наследников различной степени вложенности. O>Маппинг "таблица на конкретный тип" (каждая таблица содержи только записи своего типа, и все поля всех предков). O>В некоторых случаях EF генерит простой sql "select ... from Base", а в других — огромный развесистый union всех наследных типов. (Размер sql-запроса может достигать сотен kb, и ползает всё это неприлично долго).
Разве не очевидно?
Первое: есть профит реальный от наследования? Если да, то лучше в одной таблице все держать.
Иначе, лучше использовать независимые типы или композицию один к одному.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[3]: EF6 code first, загрузка наследников, огромный select union
Здравствуйте, Osaka, Вы писали:
G>>Слона не приметил... EF6 это же не EfCore6? G>>Я бы от первого отказался в пользу второго. O>Чем он лучше?
Чуть менее чем всем
O>Читал что-то про это EF Core несколько лет назад, они обещали когда-нибудь научиться делать всё что умеет древний EF, но наследование таблиц не умели. Сдвинулось что-то с этим вопросом? https://docs.microsoft.com/en-us/ef/core/modeling/inheritance#table-per-type-configuration
Re[3]: EF6 code first, загрузка наследников, огромный select union
Здравствуйте, Osaka, Вы писали:
G>>непонятно является ли такой SQL избыточным или он генерирует ровно то, что нужно. O>Математически там всё верно, вытаскивает все наследные типы. Но мне это в одних задачах нужно, а в других недопустимо.
Так ты в каждой конкретной задаче указывай что нужно, то и будет вытаскивать.
O>>>Можно ли данным поведением управлять не меняя модель, а в рантайме, по-разному для разных типов и навигационных свойств? G>>Можно, если сделать проекцию. O>"Проекция" в данном контексте это что?
.Select с явным указанием нужных полей.