Re[3]: LINQ to SQL. первые разочарования.
От: Igor Trofimov  
Дата: 11.12.07 20:13
Оценка:
Немножко отвлекаемся от общей темы дискуссии, но хочется еще немножко побеседовать про наследование.

С>Стоимость соединения я прикидываю на реальных данных в ходе внедрения или эксплуатации.

С>И если оно, соединение, становится слишком дорогим, то я легко рефакторю "тяжелые" таблицы ко второму варианту реализации наследования, когда атрибуты предка дублируются в атрибутах потомка.

Оно конечно, вариант. Но когда вам потребуется выборка экземпляра некоторого базового типа — придется воротить несколько UNION'ов...
Ограничения, заданные на уровне СУБД для унаследованных колонок — также придется дублировать и синхронизировать. Дубляж данных, дубляж индексов...
Внешние ключи из других таблиц на таблицу базового типа... ну тут наверное нормально, но только если сохраняется связь один-к-одному.

Я это к тому, что такая схема тоже далеко не идеальна, далека от нормальной, и поиск компромисса вполне может закончиться в конкретном случае признанием модели SingleTableInheritance наиболее подходящей

С>На первоначальном этапе анализа и проектирования я никогда не заменяю наследование на атрибут-признак типа, так как с большой вероятностью на этом этапе может что то ускользнуть от твоего взгляда и при этом легко допустить ошибку проектирования.

С>Я всегда смогу вернуться к рефакторингу в направлении создания атрибута-признака типа на завершающих этапах, если это решение действительно окажется удовлетворительным. Яркий пример когда введение атрибута-признака типа очень часто является ошибкой — это "Физические лица и Юридические лица".

На этапе анализа и проектирования концептуальной модели нет и не может быть никаких признаков типа. Мы говорим про ситуацию, когда такой признак — это не часть модели, а просто способ отличать типы объектов при хранении. Это отражает всего-лишь способ хранения, скрытый от прикладного кода.
Вас же пугает, что у любого объекта в памяти есть некий признак типа TypeHandle?

С>А рассуждая так, что в потомках отличающихся свойств раз два и обчелся, недолго дойти и до решения когда всю базу можно уложить в одну таблицу. Хотя я конечно же уверен что к такому маразму ты никогда не стремился


К хранению иерархии в одной таблице я тоже никогда не стремился. Было бы странно к этому стремиться.
А вот использовать как один из самых простых и эффективных способов хранения — приходилось, равно как и другие.
Re[5]: LINQ to SQL. первые разочарования.
От: Igor Trofimov  
Дата: 11.12.07 20:35
Оценка: +1
С>Я тоже не сторонник "авто-запросов", поэтому если и интересовался какими-либо ORM-ами и Mapping-Helper-ами, всегда в первую очередь смотрел на возможность пустить их CRUD-логику через использование хп, а на прямые обращения к таблицам и вьюхам вообще права отбираю всегда.

Обратите внимание, что CRUD — это совсем даже не Select
Подход с процедурами может быть хорош, если у вас малое число различных запросов в системе.
А если большое число разных запросов? Ну вот задача такая!

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

Совершенно очевидно, что ВСЕГДА (это значит ВСЕГДА) будет некоторый процент таких запросов, которые надо писать и пускать руками, в которых вылизан каждый хинт и который не напишет ни один генератор и не соптимизирует ни один железный оптимизатор. Ну так и пускайте его руками! Но процент таких запросов обычно очень невелик! Если у вас не так, можно только посочуствовать (или поздравить — у вас нестандартные проекты!).

А LINQ (и иже с ним) можно пробовать использовать в той огромной массе кода, где корректность гораздо важнее оптимальности (по крайней мере на начальном этапе).
LINQ за счет удобства использования и статического контроля снижает вероятность ошибок, повышает читаемость и именно в этом его плюс.
Не надо искать в нем лекарство от всех болезней!

С>Но я, так же как и ты, никогда не буду работать с сервером посредством вот такой вот тупой авто-генерации запросов, будь то EDF,LINQ или NHibernate или еще что-либо.


Дело, конечно, ваше. В любом случае, странно, если вам не нравятся запросы NHibernate, то чего вы такого волшебного ждали от LINQ?

А я вот например, с удовольствием поиспользую LINQ в своих проектах.
Конечно, не со стандартным LINQ-to-SQL, а со своим back-end'ом
Куда я напишу такую генерацию SQL, которая мне нужна.
И который сможет делать выборки в памяти по возможности.
И что еще там мне потребуется.

Тут же все как обычно — M$ сделал фичу в языке и парочку референсных штук, использующих эту фичу.
И часто лучшей практикой оказывается выкинуть этот референс и используя фичу, сделать все так, как тебе надо
Re[5]: LINQ to SQL. первые разочарования.
От: снежок Россия  
Дата: 11.12.07 20:43
Оценка:
S>А чем конкретно код не понравился?
S>Недавно, кстати прочитал где то в блогах что в команду EF специально откомандировали лучших спецов по оптимизации запросов из SQL Server core team.

То то весь код кишит LEFT OUTER JOIN — ами.
Т.е. почти везде подразумеваем справа NULL-ы по ключам при соединении, да?
А всегда ли это справедливо в этих запросах? Или может маппинг где недокрутили? Теперь закрученные отверткой шурупчики будем под микроскопом пинцетиком поправлять?
Хотя конечно по логике LINQ-запроса нужно смотреть, но вот только непонятно сразу откуда это идет из кода, стояло бы exec GetOrderDetail @p1, @p2 ... совсем другое дело.

Меня на самом деле вот что настораживает — как бы каждый "индус по призванию" не начал LINQ-запросы лепить везде где не попади в целях сверхбыстрого создания кода "сверхнового поколения". И как бы не получить откат к размазыванию запросов (пусть linq-запросов) по слоям. Ведь "удобно" же становится... навесил сразу же на OnClick linq-запрос и готово, зачем нам знать всякие MVC, Front- и ApplicationConntoller, DynamicProxy и прочую лабудень из паттернов?
И сервисы свои в сторону, Astoria всех спасет
Только потом куча этих индусских проектов качует бравым парням из Дубны... Но ничего, они могучие, все отрефакторят как надо.
Не смешно?
Re[4]: LINQ to SQL. первые разочарования.
От: снежок Россия  
Дата: 11.12.07 21:16
Оценка:
iT>Оно конечно, вариант. Но когда вам потребуется выборка экземпляра некоторого базового типа — придется воротить несколько UNION'ов...
Да, так оно и есть, рефакторится лишь соответствующая базовая view и select f from BaseTable заменяется
select f from BaseTable
union all
select f from Child1
union all
select f from Child2

iT>Ограничения, заданные на уровне СУБД для унаследованных колонок — также придется дублировать и синхронизировать. Придется, но такова природа данного типа наследования.

Дублировать и синхронизировать индексы и ограничения приходится и при разнесении тяжелых таблиц по partition-ам (partitioned view), ну и что, теперь из-за этого не использовать partitioned view/table?

iT>Я это к тому, что такая схема тоже далеко не идеальна, далека от нормальной, и поиск компромисса вполне может закончиться в конкретном случае признанием модели SingleTableInheritance наиболее подходящей

Модель SingleTableInheritance ведет только к одному — к появлению NULL-ов и денормализации, которая впринципе подходящий вариант в OLAP, но ни как не в оперативной БД.
Хотя лишний раз и не хочется поднимать флеймогонных тем, но всегда когда есть искушение заюзать NULL-ы я отношусь к этому как к потенциальной ошибке проектирования, хоть компромисы и возможны.
Обычно искусственно ставлю себе в этом случае планку — одно-два поля, не более, иначе — выделять в нормальных потомков. И то, такое решение (SingleTableInheritance) принимается на заключительных стадиях/витках проектирования.

iT>На этапе анализа и проектирования концептуальной модели нет и не может быть никаких признаков типа. Мы говорим про ситуацию, когда такой признак — это не часть модели, а просто способ отличать типы объектов при хранении. Это отражает всего-лишь способ хранения, скрытый от прикладного кода.

iT>Вас же пугает, что у любого объекта в памяти есть некий признак типа TypeHandle?
Нет, как раз признак типа меня не пугает, он как раз таки обычно присутствует во всех типах наследования, хотябы как информационное поле. Меня пугает то, что творится внутри этой таблицы, и кстати, невозможность на уровне таблицы построить constaraint по полю потомка, который должен быть применим только для одного типа. Т.е. в случае SingleTableInheritance применяем constraint либо ко всем типам, либо вообще его не создаем и контролируем его в другом месте.

iT>К хранению иерархии в одной таблице я тоже никогда не стремился. Было бы странно к этому стремиться.

iT>А вот использовать как один из самых простых и эффективных способов хранения — приходилось, равно как и другие.
В любом подходе должна быть мера и здравый смысл, не так ли?
Re[5]: LINQ to SQL. первые разочарования.
От: Sinix  
Дата: 12.12.07 02:05
Оценка: :)
Эть... вот за что я люблю РСДН) Стоит от души пожаловаться на жизнь, и тут же тебя все поддержат)

Вежливо отпишемся по пунктам. Если начну срываться в холивар — пинайте)

Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Sinix, Вы писали:


S>>Ну и мои 5 копеек. Сразу, чтоб не флеймить. Сам по себе LINQ — забавная идея. Но вот реализация...


S>>Она дико сырая.


VD>Идея старше тебя и очень продумана. Ты наврено даже не подозреваешь, что базис этой идеи нзывается "Лямбда исчисления Чёрча".


Идея — да, да и ещё раз да. Я не собираюсь про это спорить. Я про конкретную реализацию. Я наверно даже не подозреваю, что тот кто её делал, слышал про "Лямбда исчисления Чёрча") Тут уже была куча холиваров... есть лямбды в 3-м шарпе, не есть лямбды... сколько можно?)

S>> Безумно раздражает, что вместо того, чтобы работать с сиквелом, который я знаю и понимаю, я должен работать с какой-то финтифлюшкой, которая изображает из себя сиквел, как его видят разработчики финтифлюшки.


VD>Проблема в том, что создатели "финтифлюшки" считают тебя и дугих C#-разработчиков быдлокодерами которым бессмысленно давать суровую мат.модель лежащую под их решением. Они считают, что большинство C#-разработчиков — это индусы (по призванию, а не по национальности), и они тупо не поймут мудренного обоснования. Меж тем основание у Линк-а очень серьезное. SQL — это только форма.


Про обоснование согласен. Про быдлокодеров — отдельный холивар.

S>> Плохо видят кстати. Меня задолбало пытаться написать LINQ-запрос так, чтоб он хотя бы примерно соответствовал тому, что должно быть и угадывать, как поведёт себя SelectMany в сочетании с GroupBy и GroupJoin (да, кстати, Left Join'a нет. Потомучта.).


VD>Это проблема абстрагирования. Запрос в Линк — это абстракция которая преобразуется в SQL в случае LINQ to SQL. Понятно, что "не идеальные оптимизаторы" БД могут воспринять получающийся запрос не очень адекватно. Но над СУБД и их оптимизаторами будут работать, и рано или поздно даже самые не оптимальные запросы будут выполняться оптимально, и эта проблема уйдет сама собой. А пока что мы вльны химичит с вьюхами и другими косвенными структурами СУБД, чтобы заставить СУБД воспринимать "линкованные" запросы.


Тоже согласен. Но вот насчёт будущей доработанности LINQ for SQL сиильна сомневаюсь. Чтобы не быть голословным. Есть такой дяденька, Frans Bouma. Один из команды разработчиков платного ормаппера LLBLGen Pro. И вот в его блоге есть чудная-чудная история в девяти частях про прикручивания LINQ к их мапперу. Очень советую осилить, перед тем, как холиварить на тему LINQ.

S>> Задолбало разбираться, почему я должен править что-то в xml-х кишках этого чудо-монстра, чтобы наконец заработали хранимые процедуры, а потом материться и переписывать параметризованные функции на вьюхи, чтобды эта падла нормально загружала details'ы.


VD>Большинство действительно новых решений не совершенно. Можешь потрахаться пару лет с O/R-маперами пока Линк не доведут до ума. Вот только по мне так это убитое время.


И о чём мы спорим?)

S>>Ндя. Обещал же. 5 копеек про LINQ for SQL.


S>>1. Отсутствие отсоединённого режима работы.

S>>Я до сих пор не могу понять, почему либо я использую SqlQuery<T> (или как его там...) и терплю непрекращаюшиеся обращения к серверу на каждый чих,
S>> либо пытаюсь использовать EaferLoad с копированием загруженных элементов типа .ToBindingList() и натыкаюсь на весёлые грабли... Потому что EagerLoad тоже через попу работает))) Самое большее, что с его помощью можно добиться — чтобы загружались дети при обращении к родителю. В результате, если у вас 15 родительских записей, вам потребуется обратиться к серверу всего 15 раз. Мило, да?)

VD>Мило. Именно по этому лучше вобще не заморачиваться на идею O/R-мапинга, а делать реальные запросы к реальным данным.


Угу.

S>>2. Производительность. На эту тему даже рыдать не хочется. Я не могу понять, почему жалкие полтыщи master/details строк должны загружаться по три-пять секунд? Аналогичный штук с датаадаптером на порядок шустрее.


VD>Ну, а 0.5-1 секунда — это нормально? А если клиентов 1000, то ждем 16 сек. на запрос (1 000 / 60)?

VD>Не надо тянуть ненужные данные. Это ответ на все вопросы.
VD>Проблема у вас в головах. Вы привыкли к ООП. А данные — это данные. Берите нужные вам 20 строк и не ентитите себе и окружающим мозги разными master/details-ами.
VD>Нужны данные по заказу вместе с деталировкой? Ну, так напиши запрос соеденяющий заказ и его деталировку. Нужен список заказов? Так тяни только его. А уж детали по отдельным заказам вытянишь потом отдельным запросом.

Ээть. Ну как сказать. У нас тестовый сервер тогда крутился на Cel 1.8/512 (не помню уже, зачем так извращались). И там ещё мноого чего запущено. В общем для тех условий и полсекунды — нереально много. Потому как там не тупой select from where был.
Почему я привык к ООП? я как не странно не стараюсь написать свой "бизнес-объект" на каждый чих. До сих пор по старинке датасетами пользуемся)
Ну и насчёт нужных мне 20 строк. Если бы всё так просто было... Вы считаете что утянуть полтыщи строк за один раз и изредка их рефрешить куда медленнее, чем пихать при каждом скроле сервер тем же самым запросом, да ещё и с сортировкой (пусть и ограниченной с помощью top)?
И что вы все так сразу к мастер-детайлсам цепляетесь?) Если я скажу, что там не совсем мастер-детайлсы, это вас успокоит?)

S>>3. Lazy load. Ну вот раздражает меня тот факт, что результатом любого запроса могут быть устаревшие данные (не забываем, что все сущности весьма весело кэшируются внутри контекста). Даже если мне надо будет показывать лишь часть данных, я предпочту постраничную выборку. Потому что буду уверен, что все данные согласованы. И не буду гадать, сколько времени назад и что загрузилось.


VD>Разражают? На то есть уровни изоляции. Хотя разумнее не раздражаться, а расчитывать на это. Программы будут более мастабируемыми.


Таак. То есть, то, что клиент одновременно видит и устаревшие, и свежие данные — это уже преимущество?) Ну и про уровни изоляции. Вы надеюсь не предлагаете держать serialized транзакцию, пока пользователь не проскролит по списку?)

S>>4. Невозможность сериализации данных. Точнее так. Сериализовать их можно. А вот восстановить и определить какие данные надо вставить в БД, а какие не изменялись — хрен те. Официальный совет: восстанавливайте оригинальные версии и вносите все изменения заново. Опупеть, да?


VD>Ага. Если думашь шаблонами O/R-маперов. И нормально если думашь о списках данных как о... э... списках данных.


Угк. В общем я даже комментировать не хочу особо. Никогда не требовалось организовать удалённую обработку данных с последующим внесением изменений?) Так вот. LINQ for SQL в своём текущем состоянии этого не позволяет.

S>>5. Убогий сгенеренный код. Если начальство увидит, что код в продакшне обращается к серверу вот так (это для одного (!) родителя):...


VD>А на что оптимизатор у СУБД?


S>>В общем, если шеф такое увидит, я не знаю, что со мной будет. Ясно одно — будет больно и недолго.


VD>Если шев дурак, то будет больно. Если умный, то он поймет и осознает тот факт, что неоптимальность запросов соптимизирует умный сервер, а вот выигрышь в контроле типов и интелесенсе будет напрямую увеличивать качество и скорость разработки прикладного кода. В итоге дурка заставит писать код самостоятельно. Умные воспользуется приемуществами ЛИНК-а.


Гм. Шеф как раз не дурак. И он понимает, что ни один оптимайзер не способен вас защитить от идиота, который пихает left join'ы и сортировку где надо и не надо. А контроль типов и интеллисенс худо-бедно обеспечивают те же типизированные датасеты.

S>>Удачи вам в освоении новых технологий)


VD>Во. Во. И пока ее как следует не освоят не стоит выражать сильных негодований. Иначе потом стыдно удет. Ведь болшинство негодований вызвано не реальными недостатками, а банальными штампами мышления навязанными испоьзуемыми до этого технологиями.


А я не негодую. Я делюсь наболевшим. Приятного холивара)
Re[5]: LINQ to SQL. первые разочарования.
От: Sinix  
Дата: 12.12.07 02:43
Оценка: +1 :)
Здравствуйте, stump, Вы писали:

S>Здравствуйте, Sinix, Вы писали:


S>>Ну и мои 5 копеек. Сразу, чтоб не флеймить. Сам по себе LINQ — забавная идея. Но вот реализация...

S>>Она дико сырая. Безумно раздражает, что вместо того, чтобы работать с сиквелом, который я знаю и понимаю, я должен работать с какой-то финтифлюшкой,

S>... которую ты не знаешь и не понимаешь.


Гм, а хамить обязательно?)

S>Увидел дизайнер в новой студии, ух ты — таблички мапятся на классы, значит новый ORM. А как сюда свои родные хранимки прикрутить? Не прикручиваются? Полный отстой! Гвозди забивать не удобно, а так похоже на молоток...


Гм. Ну как ни странно, мне казалось, что если "таблички мапятся на классы" — то эту уже нечто с претензией на ормапистость. И если что, с дизайнером как-то не игрались, всё честно — классы плюс attribute-mapping.


S>LINQ это интегрированый в язык механизм запросов для работы с наборами данных. А LINQ2SQL это всго лишь один из интерфейсов для этого механизма (наряду с LINQ2Entity, LINQ2XML, LINQ over dataset etc.)

S>LINQ вовсе не "изображает из себя сиквел", семантика похожая, но больше ничего общего. По идеалогии LINQ гораздо ближе к XSLT чем к SQL.

Угу.

S>>В общем жопа всё это. Впрочем, не меньшая, чем EF. Последнее вообще, по-моему, бред полный, ибо трактуется как средство для выноса концептуальной модели на сторону клиента.


S>Это где же ты такого наслушался? EF предлагает отделить концептуальную модель данных от физической. И для этого у него есть довольно развитый механизм маппинга. Это, кстати, помогает решить проблему, о которой ты говоришь далее:

S>>А теперь учтите, что у нас не одно приложение базу юзает. И каждое должно видеть эту базу по-своему, и не лезть куда не положено... У каждого приложения должна быть своя концептуальная модель, да?)))

Например, такая весёлая агитационная дока "Админам СУБД про entity framework" где английским по белому идёт следующее:

The above LINQ query looks a lot like something you would write in T-SQL (odd syntax notwithstanding), but actually, you are writing to the conceptual model. What does this mean? This means that you now have more control over the database!

S>Твоя база — это физическая модель, а каждое приложение как раз может иметь свою концептуальную модель, которые мапятся на одну физическую.


ГГГ. Читайте умных людей. Дейта для начала. Или стандарты. Например, древняя-древняя архитектура ИС, придложенная ANSI/SPARC в восемдесят лохматом году.
Упошлённо:
Есть 3 уровня: физическая реализация, концептуальная модель и пользовательские представления.
Есть маппинги между этими уровнями.
Любое пользовательское представление основывается на маппинге к концептуальной модели и (или) на маппинге к другим пользовательским представлениям.
Любой клиент обращается к системе только через пользовательское представление.

Не находите, что это чуть-чуть отличается от вашей трактовки?)

S>>В общем от лукавого всё это...

S>В общем, поменьше надо сосредотачиваться на том, что, куда и как проинсталирует тебе начальник, а побольше на сути изучаемых технологий.
S>Тогда бы стало очевидно, что за отложенной загрузкой, отсоединенным режимом работы с данными, сериализацией и прочими вещами надо идти в Entity Framework а не кувыркаться с Linq2Sql.

Гм. А зачем тогда оно там есть? Для Галочки?)

S> Выгружать тысячи записей master/details было модно и нужно в давние времена клиент серверных архитектур (которые по этим причинам и почили в бозе), а для масштабируемых приложений так делать не принято. и т.д и т.п.


Ы) мы почили в бозе, мы почили в бозе, мы почили в бозе...
Вы с файл-серверными приложениями не путаете часом? Хотя и они ещё живы. Та же 1С...

S>>5. Убогий сгенеренный код. Если начальство увидит, что код в продакшне обращается к серверу вот так (это для одного (!) родителя):


S>А чем конкретно код не понравился?


Не настораживает сортировка по всем полям и захардкоденная последовательность соединений из-за лефтжойнов???

S>Недавно, кстати прочитал где то в блогах что в команду EF специально откомандировали лучших спецов по оптимизации запросов из SQL Server core team.


Ссылку.

Удачи. И не хамите, пожалуйста. Читать неприятно)
Re[6]: LINQ to SQL. первые разочарования.
От: stump http://stump-workshop.blogspot.com/
Дата: 12.12.07 07:08
Оценка: 23 (1)
Здравствуйте, Sinix, Вы писали:

S>>>Она дико сырая. Безумно раздражает, что вместо того, чтобы работать с сиквелом, который я знаю и понимаю, я должен работать с какой-то финтифлюшкой,


S>>... которую ты не знаешь и не понимаешь.


S>Гм, а хамить обязательно?)


Хамить? На "ты" обиделся, или на то что я упрекаю тебя в недостаточном знании предмета? Хорошо, перейду на вы.
Я (и не только я один) просто констатирую факт того, что вы не достаточно разобравшись с предметом пытаетесь использовать его не по назначению и при этом делаете категорические выводы.
Вы пытаетесь молотком забивать шурупы и при этом отчаянно ругаетесь на то, что они не похожи на гвозди.


S>Например, такая весёлая агитационная дока "Админам СУБД про entity framework" где английским по белому идёт следующее:


S>The above LINQ query looks a lot like something you would write in T-SQL (odd syntax notwithstanding), but actually, you are writing to the conceptual model. What does this mean? This means that you now have more control over the database!


Я читал это. Редкостный бред...

S>>Твоя база — это физическая модель, а каждое приложение как раз может иметь свою концептуальную модель, которые мапятся на одну физическую.


S>ГГГ. Читайте умных людей. Дейта для начала. Или стандарты. Например, древняя-древняя архитектура ИС, придложенная ANSI/SPARC в восемдесят лохматом году.

S>Упошлённо:
S>Есть 3 уровня: физическая реализация, концептуальная модель и пользовательские представления.
S>Есть маппинги между этими уровнями.
S>Любое пользовательское представление основывается на маппинге к концептуальной модели и (или) на маппинге к другим пользовательским представлениям.
S>Любой клиент обращается к системе только через пользовательское представление.

S>Не находите, что это чуть-чуть отличается от вашей трактовки?)


Ну, так это не моя трактовка, а тех кто делает EF. Можете их урекать, что они в детстве мало Дейта читали
Эти ребята оперируют треминами "The Conceptual Model" и "The Storage Model". Чего флеймить? Откройте help по EF и почитайте. Они разрабатывают фрэймворк кторым мы пользуемся, и поэтому они диктуют терминологию а не мы. Вы создайте собственный движок и можете оределять там термины, как вам нравится.


S>>Тогда бы стало очевидно, что за отложенной загрузкой, отсоединенным режимом работы с данными, сериализацией и прочими вещами надо идти в Entity Framework а не кувыркаться с Linq2Sql.


S>Гм. А зачем тогда оно там есть? Для Галочки?)


В точку, только пожалуй "галочка" — с маленькой буквы . Но, я заюзал бы System.Data.Linq вместо System.Data.Entity в каком нибудь небольшом web приложении или интерактивном прототипе. Очень удобные там вещи есть, вроде выведения типов и строгой типизации в запросах.

S>> Выгружать тысячи записей master/details было модно и нужно в давние времена клиент серверных архитектур (которые по этим причинам и почили в бозе), а для масштабируемых приложений так делать не принято. и т.д и т.п.


S>Ы) мы почили в бозе, мы почили в бозе, мы почили в бозе...

S>Вы с файл-серверными приложениями не путаете часом? Хотя и они ещё живы. Та же 1С...
Живы конечно. У бизнес приложений долгая жизнь. Я говорил об архитектуре а не оприложениях. Разницу улавливаете?

S>>>5. Убогий сгенеренный код. Если начальство увидит, что код в продакшне обращается к серверу вот так (это для одного (!) родителя):


S>>А чем конкретно код не понравился?


S>Не настораживает сортировка по всем полям и захардкоденная последовательность соединений из-за лефтжойнов???

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

S>>Недавно, кстати прочитал где то в блогах что в команду EF специально откомандировали лучших спецов по оптимизации запросов из SQL Server core team.


S>Ссылку.

Найду, скину.

S>Удачи. И не хамите, пожалуйста. Читать неприятно)

Ваши пассажи тоже читать не очень приятно. В исходном сообщении вы в достаточно хамской форме упрекаете разработчиков LINQ в непонимании SQL, а когда в непонимании LINQ упрекают вас, то вы вспоминаете об этикете. Ведите себя соответственно и не будет поводов для обид.
Понедельник начинается в субботу
Re[6]: LINQ to SQL. первые разочарования.
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.12.07 08:14
Оценка: +2
Здравствуйте, Sinix, Вы писали:


S>Тоже согласен. Но вот насчёт будущей доработанности LINQ for SQL сиильна сомневаюсь. Чтобы не быть голословным. Есть такой дяденька, Frans Bouma. Один из команды разработчиков платного ормаппера LLBLGen Pro. И вот в его блоге есть чудная-чудная история в девяти частях про прикручивания LINQ к их мапперу. Очень советую осилить, перед тем, как холиварить на тему LINQ.

Я вот начал читать, и как-то мне кажется, что чувак там в основном мимо тазика мечет. Нет, он тоже MVP, все дела, но первый же SQL, который он приводит для обоснования убогости Linq, заставляет меня сомневаться в очевидном:
-- TSQL, using '*' for simplicity
SELECT E.* FROM Employees E LEFT JOIN Orders O
ON E.EmployeeID = O.EmployeeID
WHERE O.OrderID IS NULL

Это для решения задачи "построить список сотрудников, у которых нет заказов".
Ну кто так пишет? Индусы? Надо полагать, для построения сотрудников, у которых есть заказы, пацан напишет что-то вроде
-- TSQL, using '*' for simplicity
SELECT E.* FROM Employees E LEFT JOIN Orders O
ON E.EmployeeID = O.EmployeeID
WHERE O.OrderID IS not null

Потом он, ясен пень, исправит это на
SELECT distinct E.* FROM Employees E LEFT JOIN Orders O
ON E.EmployeeID = O.EmployeeID
WHERE O.OrderID IS not null

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

Лично мне при словах "построить список сотрудников, у которых нет заказов" left join в голову не приходит. А приходит что-то вроде
-- TSQL, using '*' for simplicity
SELECT E.* FROM Employees E
where not exists (select OrderId from orders o where E.EmployeeID = O.EmployeeID)

Это несколько точнее отражает намерения разработчика, вы не находите?
Излишне говорить, что этот подход находит мгновенное отражение в Linq to SQL:
var q = from e in ds.Employees
    where ! e.Orders.Any()
    select e;

Ну и где все эти ужоснахи, про которые рассказывает нам дяденька Bouma?
Может, сгенерируется монструозный SQL? Вот он:
SELECT [t0].[Id], [t0].[Name]
FROM [dbo].[Employees] AS [t0]
WHERE NOT (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM [dbo].[Orders] AS [t1]
    WHERE [t1].[EmployeeID] = [t0].[Id]
    ))

Какие проблемы-то?
Про его рассуждения типа "как нам загрузить граф объектов, да не простой, а с подвыподвертом" — это всё мимо кассы. Все рассказы про то, что "это я мог и в своем O/R маппере" тоже, похоже, от избытка интеллекта. Ну вот мы у себя гоняем O/R маппер, Genome называется. Нормальный чисто текстовый OQL, с полным отсутствием компайл-тайм проверки; с кучей ограничений на предикаты и прочее. С нетерпением ждем возможности перейти на линк и выкинуть это как страшный сон.

S>Гм. Шеф как раз не дурак. И он понимает, что ни один оптимайзер не способен вас защитить от идиота, который пихает left join'ы и сортировку где надо и не надо. А контроль типов и интеллисенс худо-бедно обеспечивают те же типизированные датасеты.

Ну так не будьте идиотами, не пихате left join куда не надо.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: LINQ to SQL. первые разочарования.
От: снежок Россия  
Дата: 12.12.07 08:35
Оценка:
S>Ну так не будьте идиотами, не пихате left join куда не надо.
Дык как раз мало таких идиотов, дело в том что пихает их генератор, а пихает их потому, что девелопер сделал неоптимальный LINQ-запрос (или не естественно выглядящий для генератора), в то же время девелопер не дурак, и он на T-SQL конечно же использовал бы exists.
Сейчас же выходит, что девелопер должен хорошо знать и писать и LINQ-запросы, и запросы на T-SQL, и не только знать, но и хорошо сопоставлять их, предугадывая что LINQ там может нагенерить.
Re[6]: LINQ to SQL. первые разочарования.
От: IB Австрия http://rsdn.ru
Дата: 12.12.07 08:59
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Тоже согласен. Но вот насчёт будущей доработанности LINQ for SQL сиильна сомневаюсь. Чтобы не быть голословным. Есть такой дяденька, Frans Bouma. Один из команды разработчиков платного ормаппера LLBLGen Pro.

У Франса — рыльце в пушку. Он отчаянно пиарит свой LLBLGen и пытается его пропихнуть везде, где можно, задрал уже, честно говоря.
И все сценарии, на которых пытается доказать, что линк сливает его творению, как-то не кажутся мне жизненными (для тех целей, для которых linq2sql создавался), сколько я на них не смотрю. LINQ2SQL конечно тоже не идеал, все таки первая версия, но вот фатальных косяков мне пока не встречалось, пока все довольно логично и вполне вписывается в мои сценарии.

S>Почему я привык к ООП? я как не странно не стараюсь написать свой "бизнес-объект" на каждый чих. До сих пор по старинке датасетами пользуемся)

Ну и сами виноваты..

S>Угк. В общем я даже комментировать не хочу особо. Никогда не требовалось организовать удалённую обработку данных с последующим внесением изменений?) Так вот. LINQ for SQL в своём текущем состоянии этого не позволяет.

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

S>А контроль типов и интеллисенс худо-бедно обеспечивают те же типизированные датасеты.

Настолько худо и бедно, что лучше с ними вообще не связываться. =)
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[8]: LINQ to SQL. первые разочарования.
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.12.07 09:08
Оценка:
Здравствуйте, снежок, Вы писали:

С>Дык как раз мало таких идиотов, дело в том что пихает их генератор, а пихает их потому, что девелопер сделал неоптимальный LINQ-запрос (или не естественно выглядящий для генератора), в то же время девелопер не дурак, и он на T-SQL конечно же использовал бы exists.

Ну нет не использовал бы. Почитай статью — чувак начинает с left join (который вообще говоря малознакомому с SQL человеку покажется полным бредом — что это за where Id is null, когда у меня на эту колонку is not null констреинт стоит), а потом начинает обвинять линку.
С>Сейчас же выходит, что девелопер должен хорошо знать и писать и LINQ-запросы, и запросы на T-SQL, и не только знать, но и хорошо сопоставлять их, предугадывая что LINQ там может нагенерить.
Ничего предугадывать не надо. Достаточно поставить брекпоинт и навести мышой на запрос, чтобы тебе сразу показали получившийся T-SQL. Запросы на Linq, как и на SQL, нужно писать декларативно. То есть максимально стремиться к тому, чтобы описывать, что хочется получить. А не побочные эффекты, типа "загрузить еще и детей, хотя я на них не ссылаюсь".
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: LINQ to SQL. первые разочарования.
От: Аноним  
Дата: 12.12.07 10:23
Оценка:
Здравствуйте, IB, Вы писали:

S>>Угк. В общем я даже комментировать не хочу особо. Никогда не требовалось организовать удалённую обработку данных с последующим внесением изменений?) Так вот. LINQ for SQL в своём текущем состоянии этого не позволяет.

IB>Позволяет. Правда, в несколько ограниченном виде, но вполне позволяет, причем этого ограниченного вполне хватает для большинства сценариев. В следующей версии, доведут до ума окончательно, к сожалению к этому релизу не успели...

а, если не секрет, каким образом позволяет?
Мы даже на платформе2008 у "эксперта" спрашивали и про EF и про LINQ, нам ответили, типа не парьтесь и используйте прокси. После этого я попытался рассказать, что прокси — это не то, но нам снова ответили "не парьтесь и используйте прокси". Больше спрашивать не хотелось.
Re[6]: LINQ to SQL. первые разочарования.
От: Curufinwe Украина  
Дата: 12.12.07 10:37
Оценка:
Здравствуйте, Sinix, Вы писали:


S>Тоже согласен. Но вот насчёт будущей доработанности LINQ for SQL сиильна сомневаюсь. Чтобы не быть голословным. Есть такой дяденька, Frans Bouma. Один из команды разработчиков платного ормаппера LLBLGen Pro. И вот в его блоге есть чудная-чудная история в девяти частях про прикручивания LINQ к их мапперу. Очень советую осилить, перед тем, как холиварить на тему LINQ.


Было бы странно, если бы Frans Bouma не ругал LINQ. Он ведь напрямую отнимает у него хлеб . Он кстати не только LINQ ругает, но и другие ORM (Nhibernate например).

S>Гм. Шеф как раз не дурак. И он понимает, что ни один оптимайзер не способен вас защитить от идиота, который пихает left join'ы и сортировку где надо и не надо. А контроль типов и интеллисенс худо-бедно обеспечивают те же типизированные датасеты.


Просветите, каким образом датасет может обеспечить типизацию или интеллисенс при написании запроса (а не при чтении результатов).
... << RSDN@Home 1.2.0 alpha rev. 693>>
Re[7]: LINQ to SQL. первые разочарования.
От: Curufinwe Украина  
Дата: 12.12.07 10:52
Оценка:
Здравствуйте, IB, Вы писали:


IB>У Франса — рыльце в пушку. Он отчаянно пиарит свой LLBLGen и пытается его пропихнуть везде, где можно, задрал уже, честно говоря.

IB>И все сценарии, на которых пытается доказать, что линк сливает его творению, как-то не кажутся мне жизненными (для тех целей, для которых linq2sql создавался), сколько я на них не смотрю. LINQ2SQL конечно тоже не идеал, все таки первая версия, но вот фатальных косяков мне пока не встречалось, пока все довольно логично и вполне вписывается в мои сценарии.

Самый фатальный косяк, что я пока заметил, это очень большое время на генерацию SQL из LINQ выражения. Самый худший вариант — когда выражение большое и сложное, но базой выполняется довольно быстро — возможно замедление в несколько раз по сравнению с чистым ADO.NET. Смотрел в профайлере — некоторые методы в SqlProvider вызываются несколько сот тысяч раз за время одного преобразования . Странно, что не реализованно внутреннего кеширования для идентичных LINQ выражений — поскольку каждый раз выпольняется по сути идентичная работа. Компилируемые запросы конечно помогают, но они возможны не для всех типов выражений.
... << RSDN@Home 1.2.0 alpha rev. 693>>
Re[6]: LINQ to SQL. первые разочарования.
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.12.07 11:25
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Гм. Ну как ни странно, мне казалось, что если "таблички мапятся на классы" — то эту уже нечто с претензией на ормапистость. И если что, с дизайнером как-то не игрались, всё честно — классы плюс attribute-mapping.


Так как ОО-программа по любому опирирует объктами, то отображение на классы безусловно необходимо. Точнее необходимо как-то задать соотвествие между записью в таблице и объектом олицитворяющим эту запись.

Но O/R-маперы занимаются далеко не только этим. Они пытаются сделать вид, что БД — это некое хранилише для объектов. Мол мы неким волшебным образом помещаем объекты в БД и извлекаем их от туда.

Именно тут и заключается основная разница. И Линк и распрастраненные O/R-маперы проводят соответствие между записью и объектом. Но Линк позволяет оперировать данными как набором списков объектов делая запросы к ним. А O/R-маперы эмулируют прозрачную сериализацию и загрузку объектов в память.

В общем, O/R-маперы пытаются сделать впечатление, что мы работаем с объектами хранящимися в памяти, а Линк просто позволяет запросить и обработать список данных.

Так что пробелмы в восприятии очевидны. Люди привыкшие к O/R-маперам считают само собой разумеющися когда у объектов есть коллекции подобъектов, а O/R-мапер автоматизирует получение данных из этих списков. А Линк действует совсем иначе. Он намного проще. В нем нет подобъектов. В нем есть прямое отображение таблиц на классы объектов, а понятий списков подобъектов в нем нет и в помине. Именно по этому Линк не O/R-мапер.

S>>Тогда бы стало очевидно, что за отложенной загрузкой, отсоединенным режимом работы с данными, сериализацией и прочими вещами надо идти в Entity Framework а не кувыркаться с Linq2Sql.


S>Гм. А зачем тогда оно там есть? Для Галочки?)


А где это они есть в Линке? Можно примеры или ссылочки?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: LINQ to SQL. первые разочарования.
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.12.07 11:25
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Идея — да, да и ещё раз да. Я не собираюсь про это спорить. Я про конкретную реализацию. Я наверно даже не подозреваю, что тот кто её делал, слышал про "Лямбда исчисления Чёрча")


Не сомневайся, слышали. Они на работу взяли одного из разработчиков Хаскеля (самого фунционального языка).

S>Тут уже была куча холиваров... есть лямбды в 3-м шарпе, не есть лямбды... сколько можно?)


Как интересно! А можно ссылочку?

S>Тоже согласен. Но вот насчёт будущей доработанности LINQ for SQL сиильна сомневаюсь. Чтобы не быть голословным. Есть такой дяденька, Frans Bouma. Один из команды разработчиков платного ормаппера LLBLGen Pro. И вот в его блоге есть чудная-чудная история в девяти частях про прикручивания LINQ к их мапперу. Очень советую осилить, перед тем, как холиварить на тему LINQ.


Что я тут могу сказать. Будут пользователи массово просить, сделают эти джоины в следущей версии. Не будут, не сделают. Все просто.

S>Почему я привык к ООП? я как не странно не стараюсь написать свой "бизнес-объект" на каждый чих. До сих пор по старинке датасетами пользуемся)


Мне кажется, что Линк намного лучше датасетов.

S>Ну и насчёт нужных мне 20 строк. Если бы всё так просто было... Вы считаете что утянуть полтыщи строк за один раз и изредка их рефрешить куда медленнее, чем пихать при каждом скроле сервер тем же самым запросом, да ещё и с сортировкой (пусть и ограниченной с помощью top)?


Я считаю, что более разумно. Тратится меньше ресурсо, решение получается более простым и мастабируемым.

Сортировать же ничего не надо. Линк поддерживает страничный доступ на уровне синтаксиса.

S>И что вы все так сразу к мастер-детайлсам цепляетесь?) Если я скажу, что там не совсем мастер-детайлсы, это вас успокоит?)


Я не "мы". Я "прицепился" к 1000 строкам. Ну, не надо их тянуть. Эта идея кэширования и есть порождение бредовых идей O/R-мапинга. Зачем кэшировать данные где-то в промежуточном слое? Данные лучше всего обрабатывать средствами СУБД. А уж если кэшировать что-то, то как можно ближе к клиенту, чтобы эффктивность этого кэша была максимально эффектина. И лучше кэшировать не универсально и на всякий случай, а для решения конкретных задач производительности. Скажем закэшировать страничку со списком голосований и обновлять кэш только тогад когда список изменился. Сделать такое кэширование элементарно средствами веб-сервера. А вот кэшировать список голосований в памяти сервера приложений — это дурь вызванная подходами навязываемыми O/R-маперами. Все что унжно чтобы узнать изменился ли список — это мелкий запрос к БД возвращающий одно значение. А далее или отдаем страничку из кэша или перестраиваем ее.

VD>>Раздражают? На то есть уровни изоляции. Хотя разумнее не раздражаться, а расчитывать на это. Программы будут более мастабируемыми.


S>Таак. То есть, то, что клиент одновременно видит и устаревшие, и свежие данные — это уже преимущество?)


Как же ему удастся, то одновременно? Lazy load, это не более чем аналог однонаправленного курсора. Это и есть его влияние. Просто и для коллекций в памяти удается получить тот же результат за счет того, что Линковские фунции работающие с ними написаны с использованием итераторов (с yield-ами), а они автоматом обеспечивают этот самый отложенный доступ.

S>Ну и про уровни изоляции. Вы надеюсь не предлагаете держать serialized транзакцию, пока пользователь не проскролит по списку?)


Если это надо для логики, то никуда не денешся. Или перестраивай логику.

S>Угк. В общем я даже комментировать не хочу особо. Никогда не требовалось организовать удалённую обработку данных с последующим внесением изменений?) Так вот. LINQ for SQL в своём текущем состоянии этого не позволяет.


Можно пример, того о чем идет речь?

S>А я не негодую. Я делюсь наболевшим. Приятного холивара)


Почти уверен, что это не наболевшее, а результат неверного взгляда на средство. Ты думаешь, что это недоделанный O/R-мапер, а это интегрированные в язык запросы. Причем это даже не типизированные запросы к SQL-СУБД, а запросы которые могут быть преобразованны в SQL.
Плюсами технологии являются:
1. Тесная интеграция с ЯП.
2. Статическая типизация.
3. Абстрактный уровень повзоляющий сменой драйвера поддерживать новые СУБД.
4. Одинаковый синтаксис для разных источников данных (списки объектов, ХМЛ, БД и даже датасеты).
Недостатки:
1. Уровень абстрации не позволит использовать особенности конкретной СУБД.
2. Производительность запросов может хромать в некоторых случаях.
3. Своеобразный язык.
и т.п.

Надо взвесить "за" и "протим" и принять решение, что тебе лучше испоьзовать.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: LINQ to SQL. первые разочарования.
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 12.12.07 12:22
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Сортировать же ничего не надо. Линк поддерживает страничный доступ на уровне синтаксиса.


На уровне синтаксиса не поддерживает. Take() и Skip() в query pattern не входят.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
AVK Blog
Re[7]: LINQ to SQL. первые разочарования.
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 12.12.07 12:22
Оценка:
Здравствуйте, VladD2, Вы писали:

S>>Гм. А зачем тогда оно там есть? Для Галочки?)


VD>А где это они есть в Линке? Можно примеры или ссылочки?


Ну, кое какая отложенная загрузка там действительно есть. Но весьма примитивная.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
AVK Blog
Re[6]: LINQ to SQL. первые разочарования.
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 12.12.07 12:22
Оценка: +2
Здравствуйте, Sinix, Вы писали:

S>Гм. Ну как ни странно, мне казалось, что если "таблички мапятся на классы" — то эту уже нечто с претензией на ормапистость. И если что, с дизайнером как-то не игрались, всё честно — классы плюс attribute-mapping.


Тут есть один тонкий момент, который на первый взгляд не очевиден. Дело в том, что основное предназначение этих "классы плюс attribute-mapping" — внести в ОО-программу типы, описывающие метаданные БД. При этом, в отличие от полновесных мепперов, создавать экземпляры этих классов совсем не обязательно. Это просто хранилище метаданных, но не описание runtime-представления данных в памяти.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
AVK Blog
Re[8]: LINQ to SQL. первые разочарования.
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.12.07 12:48
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>На уровне синтаксиса не поддерживает. Take() и Skip() в query pattern не входят.


А тогда что же это?

Встроеные фунции часть синтаксиса.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.