Здравствуйте, cerebrate, Вы писали:
C>Иван, позволь уточнить, как именно ты проводишь эти эксперименты. Полагаю, у тебя есть edmx-модель, по которой сгенерирован код.
У меня нет модели и я вообще не хочу генерить код. Я просто создаю объект ручками, дешево и сердито, это и есть POCO )
C>Да, всё сказанное предполагает, что используется минимум EF v4 (VS 2010).
Я смотрел 4.5 и 5.
Здравствуйте, QrystaL, Вы писали:
QL>Здравствуйте, itslave, Вы писали: I>>Результат этой власти — в l2s нет и никогда не будет родных провайдеров под постгрес, оракл и прочие субд.
QL>http://www.devart.com/linqconnect/
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, itslave, Вы писали:
I>>Потому что серебряной пули не существуют. Они максимально точно повторили семантику запроса. Никто не запрещает грузить в 2 захода, ручками.
S>Текущий вариант отвратительно масштабируется, если нам нужно загружать несколько разных коллекций детей. Лучше уж загружать по умолчанию в несколько запросов, а если кому-то важна точная семантика — вперёд, ручками
Твое мнение против мнения команды разработчиков EF. Возможно ты прав, но очень маловероятно что поведение уже поменяют из-за совместимости...
Здравствуйте, itslave, Вы писали:
I>Еще раз. Если по команде "LL, Отключись" данные не грузятся при первом к ним обращении, то это значит что LL отключается.
Если на клетке слона написано "буйвол" — не верь глазам своим. Мне шашечки не важны, мне ехать надо.
LL отключается тогда и только тогда, когда я могу спокойно работать не подозревая о его существовании. К сожалению EF на это не способен. Поэтому — нет, в EF LL не отключается, не смотря на наличие соответствующей команды.
I>Не хошь — не юзай, тебя никто не заставляет. МОжно и без них жить, в чем то понятней и удобней, в чем то нет.
Без них и без EF, иначе туда вообще ничего не загрузишь.
I>Ышо рас. Генерируемый скл досаточно хорош для 80% случаев. Если он вдруг вышел кривой, этовсегда можно поправить костылями. Генерить оптимальный запрос который будет оптимальным всегда и везде невозможно, ваш кэп.
По кругу пойдем? Эти отмазки смотрятся жалко и нелепо, так как уже много лет есть инструмент, который в 90% случаев делает это лучше.
I>Как только провайдеры под большинство популярных субд допилят,
Могу привести тот же аргумент про 80% — в 80%, даже в 90% из под .Net используется MSSQL. Для всех остальных есть BLT.
I>Затем, что я тупо не хочу фиксить баги, мигрировать на новые фреймворки и допиливать BLT своими силами, если тебе вдруг надоест.
Я к BLT никакого отношения не имею )
I>И в 90х это было правильно мнение,
Нет )
I>Результат этой власти — в l2s нет и никогда не будет родных провайдеров под постгрес, оракл и прочие субд.
Ну и болт с ними...
I>Скажем так: на деле EF работает, но не соответствует твоему мировоззрению.
Работает вообще все — это не аргумент. Вопрос в количестве затраченных усилий на реализацию и поддержку + порог вхождения. И здесь, как я уже говорил, EF является редкостным отстоем.
I> Другому человеку напомнил бы пословицу про караван и собак, но в твоем случае надеюсь, что(в том числе) под влиянием BLT, в EF основные косяки поправят.
EF абсолютно беспрспективная технология, сколько бы сил и денег в нее не вкладывали бы. Хотя миллионы мух, по прежнему будут ошибаться. Поэтому я просто пойду с другим караваном. )
В общем, если подытожить — технология абсолютно кривая, как идеологически так и в реализации, и, к счастью, у меня альтернатива есть, поэтому за всем этим цирком я лучше понаблюдаю со стороны.
А дальше — все сами-себе буратины и не говорите, что я не предупреждал...
Здравствуйте, itslave, Вы писали:
IB>>Конечно не дождешься, если игнорировать будешь, я достаточно ясно написал — navigation property это не POCO. I>Не хошь — не юзай, тебя никто не заставляет. МОжно и без них жить, в чем то понятней и удобней, в чем то нет.
А хочется, чтобы в запросах оно все таки работало. Но только в запросах. К примеру, в BLT я запросто могу написать что то вроде:
db
.MyEntities
.Where(me => me.Details.Contains("XXX"))
.Select(me => me.Link.LinkProperty.LinkLinkProperty)
При этом реальные экземпляры будут созданы только для объектов — значений свойства LinkLinkProperty, все остальное превратится в SQL. И BLT гарантирует, что в SQL, а при невозможности будет исключение в момент генерации SQL для этого запроса, а не неявный переезд на клиента и выборка и инстанцирование всей промежуточной хрени для этого. Более того, я тип MyEntity и тех сущностей, на которые он ссылается могу сделать интерфейсами, чтобы уж с гарантией никто их экземпляры не поднял.
А что в случае EF?
I>Ышо рас. Генерируемый скл досаточно хорош для 80% случаев
А в остальных 20 что делать? Писать его руками?
I>Генерить оптимальный запрос который будет оптимальным всегда и везде невозможно, ваш кэп.
А всегда и везде и не нужно, нужно в данном конкретном случае. BLT часто весьма неочевидные запросы генерит, но когда потом проверяешь их план, то он оказывается практически самым оптимальным. И L2S тоже очень неплох в этом плане. А вот в EF все печально.
I>Затем, что я тупо не хочу фиксить баги, мигрировать на новые фреймворки и допиливать BLT своими силами, если тебе вдруг надоест.
Иногда возможность самому поправить в BLT багу и отослать ее авторам существенно лучше, чем ждать у моряМС погоды.
I>но в твоем случае надеюсь, что(в том числе) под влиянием BLT, в EF основные косяки поправят.
Не поправят. Основная проблема в базовой идеологии, и это уже не вылечить.
Здравствуйте, Sinix, Вы писали:
S>Чем плохи два последовательных select-а для мастера и detail--ов?
Слабо представляю как реализовать это на практике на "pure sql" не прибегая к временным таблицам в случае множественных details, особенно если в мастере использовать условия (наиболее часто встречающийся вариант)?
Здравствуйте, alexsoff, Вы писали:
A>Здравствуйте, Sinix, Вы писали:
S>>Чем плохи два последовательных select-а для мастера и detail--ов? A>Слабо представляю как реализовать это на практике на "pure sql" не прибегая к временным таблицам в случае множественных details, особенно если в мастере использовать условия (наиболее часто встречающийся вариант)?
Имелось в виду "1 мастер — несколько таблиц details"? Тогда конечно будет n+1 запросов, только n — это не число записей, а число таблиц detail-ов
Здравствуйте, Sinix, Вы писали:
S>Имелось в виду "1 мастер — несколько таблиц details"? Тогда конечно будет n+1 запросов, только n — это не число записей, а число таблиц detail-ов
Я имел ввиду немного другое, а именно оптимальность использования нескольких запросов вместо одного. например, предположим есть таблицы рабочих и проектов
Employee(ID, Name) Project(ID,EmployeeID, Title )
И есть два бизнес-объекта:
class Employee
{
int ID;
string Name;
ICollection<Project> Projects;
}
class Project
{
int ID;
string Title;
}
Вот как ORM должен сформировать два запроса sql, чтобы выбрать всех рабочих (коллекцию Employee включая в каждый коллекцию detailсов Project) имя у которых начинается на символ "А"?
A>[/c#] A>Вот как ORM должен сформировать два запроса sql, чтобы выбрать всех рабочих (коллекцию Employee включая в каждый коллекцию detailсов Project) имя у которых начинается на символ "А"?
"Имя у которых" — это имя проекта? Для проекта очевидно, для рабочих —
SELECT E.* FROM Employee E WHERE EXISTS (SELECT * FROM Project P WHERE P.Employee_ID = E.ID AND P.Name LIKE '%A%')
?
Если имя — это имя сотрудника, то (для сотрудников очевидно):
SELECT P.* FROM Project P INNER JOIN Employee E ON P.Employee_ID = E.ID WHERE E.Name LIKE '%A%'
Да, при выборке по нескольким спецификациям сложность запросов возрастёт, но это окупится тем, что в результате не будет nMaster * nDetail_1 * nDetail_2 строк
*(nDetail_1(2) — среднее число записей детейлов на одного мастера).
Здравствуйте, Sinix, Вы писали:
S>Если имя — это имя сотрудника, то (для сотрудников очевидно): S>
S> SELECT P.* FROM Project P INNER JOIN Employee E ON P.Employee_ID = E.ID WHERE E.Name LIKE '%A%'
S>
Т.е. по превому запросу проходим по таблице Employee и ищем всех сотрудников у которых имя начинается на 'А' (чтобы получить бизнес объекты типа Employee ) и второй раз — во втором запросе, но уже соединяя их с таблицей детализации Project, чтобы получить коллекцию проектов у каждого сотрудника, а далее в ядре ORM начинаем их агрегировать по признакам "ключ значение". неужели мне одному очевидна неэффективность такого подхода с двумя проходами по одинаковому условию одной и той же таблицы
S>Да, при выборке по нескольким спецификациям сложность запросов возрастёт, но это окупится тем, что в результате не будет nMaster * nDetail_1 * nDetail_2 строк S> *(nDetail_1(2) — среднее число записей детейлов на одного мастера).
Все что Вы выиграли данным подходом так это суммарный объем данных, но проиграли по времени выполнения.
PS
Поправьте, мои рассуждения если можно
Здравствуйте, alexsoff, Вы писали:
A>Т.е. по превому запросу проходим по таблице Employee и ищем всех сотрудников у которых имя начинается на 'А' (чтобы получить бизнес объекты типа Employee ) и второй раз — во втором запросе, но уже соединяя их с таблицей детализации Project, чтобы получить коллекцию проектов у каждого сотрудника, а далее в ядре ORM начинаем их агрегировать по признакам "ключ значение".
На практике запросы будут идти по индексированным столбцам и страницы для них будут уже в кэше, т.е стоимость "лишнего" джойна будет невелика (иначе один запрос или несколько — разницы никакой, мы уже попали). Данные для каждой таблицы выгребаются ровно один раз, стоимость "агрегирования" одной записи на клиенте в любом из вариантов будет ~O(1) (при использовании словарей).
>неужели мне одному очевидна неэффективность такого подхода с двумя проходами по одинаковому условию одной и той же таблицы
Если мы говорим о производительности, то аргументы "очевидно" не подходят, надо мерять. Если есть возможность — возьмите запрос, что генерит EF и сравните стоимость его плана выполнения и стоимость двух "простых" аналогичных запросов.
Здравствуйте, Sinix, Вы писали:
S>На практике запросы будут идти по индексированным столбцам и страницы для них будут уже в кэше,
С чего это вы взяли что в кеше? где гарантия что данные между двумя запросами не изменились? в OLAP мире возможно, а вот в реальных OLTP системах вовсе не гарантируется. И не забывайте, что в реальности СУБД имеют дело с не совсем оптимизированными базами (т.е. где нормально построены индексы и т.д.).
S>Если мы говорим о производительности, то аргументы "очевидно" не подходят, надо мерять. Если есть возможность — возьмите запрос, что генерит EF и сравните стоимость его плана выполнения и стоимость двух "простых" аналогичных запросов.
Ваше утверждение строится на "догадках" что данные будут в кеше, в остальном как-то не прозрачно. Да, если будет время, обязательно построю.
Здравствуйте, alexsoff, Вы писали:
S>>На практике запросы будут идти по индексированным столбцам и страницы для них будут уже в кэше, A>С чего это вы взяли что в кеше? где гарантия что данные между двумя запросами не изменились?
А с чего ты взял, что изменение страницы выкидывает ее из кеша?
A>И не забывайте, что в реальности СУБД имеют дело с не совсем оптимизированными базами (т.е. где нормально построены индексы и т.д.).
Тут такое дело — если делается джойн по полям, у которых нет индекса, то это не просто "не совсем оптимизированная база", это клиника и за такое надо яйца разработчикам и админам БД откручивать.
Здравствуйте, Ночной Смотрящий, Вы писали:
A>>С чего это вы взяли что в кеше? где гарантия что данные между двумя запросами не изменились?
НС>А с чего ты взял, что изменение страницы выкидывает ее из кеша?
А с чего ты взял, что я говорил про изменение страницы? речь шла вообще-то о результатах первой выборки.
НС>Тут такое дело — если делается джойн по полям, у которых нет индекса, то это не просто "не совсем оптимизированная база", это клиника и за такое надо яйца разработчикам и админам БД откручивать.
Опять двадцать пять, я говорил не про поля внешних и первичных ключей, а другие поля таблицы, например в моем примере было ФИО сотрудника. и уже тем более мне не надо доказывать, что на практике индексы нужно лепить повсюду и на каждое поле.
Здравствуйте, alexsoff, Вы писали:
НС>>А с чего ты взял, что изменение страницы выкидывает ее из кеша? A>А с чего ты взял, что я говорил про изменение страницы? речь шла вообще-то о результатах первой выборки.
Ну так изоляция транзакций вроде как. Если она достаточно слабая, надо быть готовым к колизиям вне зависимости от конкретно этого запроса.
НС>>Тут такое дело — если делается джойн по полям, у которых нет индекса, то это не просто "не совсем оптимизированная база", это клиника и за такое надо яйца разработчикам и админам БД откручивать. A>Опять двадцать пять, я говорил не про поля внешних и первичных ключей
Я тоже не говорил.
A>, а другие поля таблицы, например в моем примере было ФИО сотрудника
Sinix предложил простой и действенный вариант. Более того сказал — что в разных случаях — нужно всё равно включать голову и смотреть, что проще и эффективнее (если о эффективности вообще речь стоит — если это запросы UI — то эффективность идёт лесом, совсем не тот порядок нагрузки, в основном).
Я сталкивался в основном с такими ситуациями:
SELECT * FROM Master WHERE Id=XXXX
SELECT * FROM Details WHERE MasterId=YYYY
Заметьте — никакого потом маппинга на клиенте делать не надо — второй селект вообще существует исключительно потому, что реляционная модель. В другом случае это был бы один объект. Более того это предмет для жесткого (но очень заботливого кеширования). Да, в жизни это сложнее, чем я показал — но суть никапли не меняется.
При чём предложение Sinix-а в моём случае себя более чем оправдывает, потому что просто, потому что запросы делают именно то, что я от них я хочу. Да и не делают они никакой просадки. Там хоть сотню таких же навали — не сделают они просадку. А есть такие, которые как раз делают, и там ничего по ФИО не ищется.
Алекс же ж! Тут не хочет читать, что пишут — и пытается навязать своё видение, хотя вроде как и все согласны с тем, что оба варианта более чем применимы, если их применять разумно. Т.е. сделали решение -> имеем ли более-менее реальную базу -> пробуем -> радуемся. В контексте EF — проблема с EF в том, что EF, EF, EF просто таки нагло подталкивает сделать так как он захочет (EF). Особенно с транзакциями (точнее их отсутствием) было вообще не в тему — кто мешает читать в транзакции?
Здравствуйте, Ночной Смотрящий, Вы писали: НС>И ты по ФИО сотрудника делаешь джойн?
Ладно, разговор похож уже на глухого и немого. Мне для моих задач EF хватает за глаза, так где нужны именно эффективные запросы, я делаю ручками и не жалуюсь.
Здравствуйте, IB, Вы писали: E>>а что советуете? IB>Linq2SQL, ну или BLT.
Такой вопрос — как реализовать наследование Table Per Class? (Я так понимаю, поддерживается только Table Per Hierarchy, и соответственно какие-то workarounds нужны...)