Помня о флэйме разгоревшемся по поводу того, что "LINQ to SQL оказался плохим O/R Mapper-ом" когда писали редакционную статью для журнала Технология Клиент-Сервер, мы решили обратиться к тему "что же такое LINQ to SQL". Вот что получилось. Надеюсь этот текст позволит многим правильно воспринять LINQ to SQL, а не искать в нем недостаки которых в нем нет.
Многие воспринимают LINQ to SQL как очередной O/R mapper, но реализованный Microsoft. Учитывая, что от Microsoft всегда ожидают намного большего, чем от более бедных компаний, и тем более от Open Source-разработчиков, у многих при первом знакомстве с LINQ to SQL наступает серьезное разочарование. Однако это разочарование вызвано неправильным пониманием сути используемого в LINQ to SQL подхода. Дело в том, что LINQ to SQL не является O/R mapper-ом. На самом деле LINQ – это абстрактное средство обработки списков, а отдельные разновидности LINQ, такие как LINQ to SQL или LINQ to XML, просто рассматривают некий источник данных как набор списков. Задача средств отображения, присутствующих, например, в LINQ to SQL, не в том, чтобы создать объектную модель, позволяющую скрыть детали БД и обеспечить эффективную обработку данных императивными средствами (в основном фильтрацию списков в циклах), а в том, чтобы ввести в программу некий набор классов, предназначенных для считывания в них данных из таблиц СУБД. При этом LINQ to SQL хотя и позволяет работать с такими классами императивными средствами, но заранее предупреждает, что это будет неэффективно и неудобно. Вместо этого LINQ to SQL предлагает использовать статически типизируемые, проверяемые во время компиляции, SQL-подобные запросы. Эти запросы транслируется в эффективный SQL, который выполняется СУБД. Результаты выполнения этих запросов преобразуются в списки типизированных объектов, которые удобно обрабатывать в таких объектно-ориентированных языках программирования, как VB и C#. Простой пример: предположим, у нас таблица покупателей (Customer), ссылающаяся на список заказов (у каждого покупателя может быть 0 или более заказов, Order), при этом в каждом заказе может быть 0 или более позиций (OrderDetail), и в наши задачи входит посчитать, сколько конкретному покупателю было продано единиц некоторого товара. Предположим, что идентификатор покупателя – ТКС, а идентификатор товара – БумагаА4. И классический O/R mapper, и LINQ to SQL при создании объектной модели для связи между таблицами генерируют соответствующие коллекции. Для нашего примера в классе Customer будет создана коллекция Orders, содержащая список объектов типа Order, а Order будет содержать коллекцию типа OrderDetails, содержащую, соответственно, список позиций заказов (объектов OrderDetail). При использовании традиционного O/R mapper-а было бы совершенно нормально написать код, который получает (с помощью некоторой хитрой функции Lookup) объект по его идентификатору, а дальше, с помощью двух вложенных циклов, пробегает по его коллекции, отбирая нужные элементы. Казалось бы, объем данных невелик (сколько может быть заказов у одного покупателя?), и перебор должен произойти практически мгновенно. Нужную позицию можно отфильтровать с помощью if. Однако ни O/R mapper, ни, тем более, СУБД не знают о наших замечательных намерениях и, если они не используют специальных техник, это приведет к тому, что для выборки каждого объекта будет выполнено отдельное обращение к БД. Конечно, хороший O/R mapper буквально напичкан специальными техниками, сглаживающими подобные неприятности (в частности, они могут выполнять опережающее чтение). Однако без тотального кэширования данных движком O/R mapper и, фактически, дублирования функций СУБД высокой производительности добиться не удастся. Поскольку серьезные БД в память априори не помещаются (тем более в объектном представлении), производительность всех без исключения O/R mapper-ов оставляет желать лучшего. Обратите внимание – это проблема системного характера, и решить ее принципиально, используя данный подход, невозможно. Как же быть? Более 20 лет назад производители СУБД (а именно IBM) решили эту проблему для своих продуктов. Решением был переход от навигационной системы к запросной с использованием языка запросов SQL. SQL в декларативной манере говорит СУБД, какие данные нужны клиенту, что потенциально позволяет СУБД построить эффективный план запроса и возвратить клиенту только требуемые данные. При этом экономятся как ресурсы сервера, так и трафик. Так вот, хотя LINQ to SQL и содержит набор возможностей, похожих на предоставляемые O/R mapper-ами вроде Hybernate, основным средством доступа к данным в нем является SQL-подобный язык запросов. LINQ же обеспечивает его безопасность, проверку ошибок на стадии компиляции, а поддержка Intellisense для запросов, встроенных в язык, появившаяся в VS 2008, существенно повышает производительность программирования. Именно так и нужно смотреть на LINQ, а что касается O/R mapper-а от Microsoft, он, по всей видимости, вскоре появится под названием LINQ to Entity, но, скорее всего, и эта реализация будет склонять программиста к использованию интегрированного языка запросов, а не императивного доступа к данным.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>На самом деле LINQ – это абстрактное средство обработки списков
Не списков, скорее неких произвольных контейнеров или оберток (собственно, требуется что бы аргумент был вида C<T>, где C и T — произвольные типы). Списочная семантика это уже особенности конкретного LINQ провайдера.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, VladD2, Вы писали:
VD>>На самом деле LINQ – это абстрактное средство обработки списков
AVK>Не списков, скорее неких произвольных контейнеров или оберток (собственно, требуется что бы аргумент был вида C<T>, где C и T — произвольные типы). Списочная семантика это уже особенности конкретного LINQ провайдера.
Что такое "неких произвольных контейнеров"? В математике есть понятие "список" и "множество". Вот понятие "список" и использовано. Ну, а C<T> это вообще не требование, а какая-то недоразумение. Под нее можно все что угдно загнать. LINQ даже расшифровывается как "интегрированные в язык ЗАПРОСЫ". Запросы можно делать только к множествам или спискам. В общем, не путай людей. Они сами запутаются.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>>>На самом деле LINQ – это абстрактное средство обработки списков AVK>>Не списков, скорее неких произвольных контейнеров или оберток (собственно, требуется что бы аргумент был вида C<T>, где C и T — произвольные типы). Списочная семантика это уже особенности конкретного LINQ провайдера. VD>Что такое "неких произвольных контейнеров"? В математике есть понятие "список" и "множество". Вот понятие "список" и использовано.
"Контейнер" — он и есть "множество".
VD>Ну, а C<T> это вообще не требование, а какая-то недоразумение. Под нее можно все что угдно загнать.
Так же как и контейнером можно назвать всё что пожелаешь.
VD>LINQ даже расшифровывается как "интегрированные в язык ЗАПРОСЫ". Запросы можно делать только к множествам или спискам.
Вот-вот, а ты только про списки и "запутал".
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>"Контейнер" — он и есть "множество".
Ну, это проблемы вашего воображения. Для меня ведро не худший контейнер.
VD>>Ну, а C<T> это вообще не требование, а какая-то недоразумение. Под нее можно все что угдно загнать.
_FR>Так же как и контейнером можно назвать всё что пожелаешь.
Ну, вот чтобы не желали называть все что попало чем попало в математике и ввели понятие списка как упорядоченного множества.
VD>>LINQ даже расшифровывается как "интегрированные в язык ЗАПРОСЫ". Запросы можно делать только к множествам или спискам.
_FR>Вот-вот, а ты только про списки и "запутал".
Думаю, что все кто знаком с понятием списка все поняли. По крайней мере я, что-то вопросов не услышал.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Давно мучает вопрос по этому поводу. Если у меня есть более-менее серьёзный запрос к базе данных я делаю пользовательскую табличную функцию с параметрами и ложу её на сервер, где помещаю всё логику по выборке данных. От Linq мне тут надо только чтобы, он мне объект по результатам создал, но это и так давно умеют делать и без него. Потом мне гораздо проще менять SQL код, если чего не так, чем исходники. Вот и не понятно, чего это носятся все с этим linq. Хотя, конечно, если это не SQL провайдер, то может имеет смысл, но всё равно для XML, например, имхо часто вполне хватало XPath.
Здравствуйте, VladD2, Вы писали:
VD>Дело в том, что LINQ to SQL не является O/R mapper-ом. На самом деле LINQ – это абстрактное средство обработки списков, а отдельные разновидности LINQ, такие как LINQ to SQL или LINQ to XML, просто рассматривают некий источник данных как набор списков.
А в чем смысл такого средства? У меня есть функция, которая загружает списки из БД по коду объекта или по имени хп, чем этот LINQ лучше?
Здравствуйте, hell citizen, Вы писали:
HC>Здравствуйте, VladD2, Вы писали:
VD>>Дело в том, что LINQ to SQL не является O/R mapper-ом. На самом деле LINQ – это абстрактное средство обработки списков, а отдельные разновидности LINQ, такие как LINQ to SQL или LINQ to XML, просто рассматривают некий источник данных как набор списков.
HC>А в чем смысл такого средства? У меня есть функция, которая загружает списки из БД по коду объекта или по имени хп, чем этот LINQ лучше?
Это абстрактное средство обработки списков
LINQ к БД вообще никаким боком. Причем тут загрузка списков из БД по коду?
Здравствуйте, hugo, Вы писали:
H>LINQ к БД вообще никаким боком. Причем тут загрузка списков из БД по коду?
Речь идёт о LINQ to SQL.
Задача средств отображения, присутствующих, например, в LINQ to SQL, не в том, чтобы создать объектную модель, позволяющую скрыть детали БД и обеспечить эффективную обработку данных императивными средствами (в основном фильтрацию списков в циклах), а в том, чтобы ввести в программу некий набор классов, предназначенных для считывания в них данных из таблиц СУБД.
Такие средства есть, они хороши. Чем это новое средство лучше?
Ну дык цитату ты закомментил в своем посте не про LINQ to SQL, а про смысл именно LINQ. Вот на это я и отвечал.
HC>
HC>Задача средств отображения, присутствующих, например, в LINQ to SQL, не в том, чтобы создать объектную модель, позволяющую скрыть детали БД и обеспечить эффективную обработку данных императивными средствами (в основном фильтрацию списков в циклах), а в том, чтобы ввести в программу некий набор классов, предназначенных для считывания в них данных из таблиц СУБД.
HC>Такие средства есть, они хороши. Чем это новое средство лучше?
А кто сказал, что оно лучше? LINQ to SQL — ИМХО вполне логичное применение технологии LINQ. Можно рассматривать, как замену DataSet'у.
Здравствуйте, trickyKid, Вы писали:
K>Давно мучает вопрос по этому поводу. Если у меня есть более-менее серьёзный запрос к базе данных я делаю пользовательскую табличную функцию с параметрами и ложу её на сервер, где помещаю всё логику по выборке данных. От Linq мне тут надо только чтобы, он мне объект по результатам создал, но это и так давно умеют делать и без него. Потом мне гораздо проще менять SQL код, если чего не так, чем исходники. Вот и не понятно, чего это носятся все с этим linq.
У тебя отдельный подход. Он конечно тоже имеет право на лево... тфу ты, жизнь . Однако у него есть свои достоинства и недостатки.
Мы можем получить от использования ЛИНК-а?
1. Поддержку интелисенса. Это повзоляет писать код быстрее и качественее. Так же это позволяет быстро и без проблем рефакторить код. Несмоненно тоже можно сделать для конкретного диалекта SQL, но ведь почему-то качественно это не сделано.
2. Проверку выражений на стадии компиляции. Это позволяет раньше выявлять общики, а чем раньше выявлена ошибка, тем проще ее устранить.
3. Поддержку разных источников данных. По мощьности ЛИНК-запросы, а темболее в купе с Шарпом, Васиком или темболее Немерле мягко говоря не уступают возможностям императивных расширений SQL-я вроде TSQL (MS) или PSQL (Oracle). Более того у ЛИНК-а отсуствуют некоторые ограничения вроде уровней рекурсии процедур и т.п. Так что для написания прикладной логики ЛИНК подходит даже лучше чем TSQL/PSQL. При этом код получается кросплатформным. Ну, или по крайней мере его будет намного проще сделать таковым.
4. Линк позволяет использовать в качестве источника данных не только БД, но и другие источники (коллекции объектов, ХМЛ, датасеты и т.п.). Это позволяет реализовывать неординарную логику используя один диалект языка запросов.
5. Линк позволяет осуществлять часть обработки вне СУБД. Это повзяоляет разгрузить СУБД и тем самым повысить производительностить и мастабируемость решений.
В конце концов, если уж очень приспичет, всегда можно создать хранимые процедуры или фунции которые вызвать с помощь Линка и которые будут возвращать уже обработанные данные. Но при этом мы теряем перечисленные приемущества (возможно получаях что-то другое взамен). Но это друной подход, а речь в данном случае была связана с ОР-Мапперами.
K>Хотя, конечно, если это не SQL провайдер, то может имеет смысл, но всё равно для XML, например, имхо часто вполне хватало XPath.
Согласен. Но XPath не встроен в язык вроде Шарпа. Надо понимать, что Линк-запросы — это не SQL. Это похожий на SQL язык. Но его база — это фунциональное программирование, т.е. декомпозиция запроса на вызов нескольких фуцний получающих критерии в качестве параметров (в виде фунций-лямбд). Таким образом это универсальный язык обработки данных. Наверно можно было бы облачить его в форму XPath, но выбран был именно SQL. Видимо потому, что он лучше ложится на фунциональную декомпозицию.
Приемущество именно Линка как раз и заключается в том, что запросы сливаются с основным языком. Производится сквозной контроль типов. Мы уже не может мполучить ошибку связанную с типом во время выполнения. Мы получим сообщение об ошибке еще при компиляции. Ну, и мы получим одинаковые сообщения для разных источников данных. Эта унификация доргого стоит. Особенно если думать о вопросах обучения новичков.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
K>Давно мучает вопрос по этому поводу. Если у меня есть более-менее серьёзный запрос к базе данных я делаю пользовательскую табличную функцию с параметрами и ложу её на сервер, где помещаю всё логику по выборке данных. От Linq мне тут надо только чтобы, он мне объект по результатам создал, но это и так давно умеют делать и без него. Потом мне гораздо проще менять SQL код, если чего не так, чем исходники. Вот и не понятно, чего это носятся все с этим linq. Хотя, конечно, если это не SQL провайдер, то может имеет смысл, но всё равно для XML, например, имхо часто вполне хватало XPath.
Ага, действительно, странно было бы написать всю бизнес-логику на T-SQL и использвать LINQ 2 SQL для получения результата на клиенте А повторное использование написанной таким образом БЛ меня лично повергает в большое уныние
Здравствуйте, VladD2, Вы писали:
VD>Приемущество именно Линка как раз и заключается в том, что запросы сливаются с основным языком. Производится сквозной контроль типов. Мы уже не может мполучить ошибку связанную с типом во время выполнения. Мы получим сообщение об ошибке еще при компиляции. Ну, и мы получим одинаковые сообщения для разных источников данных. Эта унификация доргого стоит.
Ага, сразу вспоминается PowerBuilder. Эта унификация очень дорого стоит.
Здравствуйте, hugo, Вы писали:
H>Здравствуйте, trickyKid, Вы писали:
K>>Давно мучает вопрос по этому поводу. Если у меня есть более-менее серьёзный запрос к базе данных я делаю пользовательскую табличную функцию с параметрами и ложу её на сервер, где помещаю всё логику по выборке данных. От Linq мне тут надо только чтобы, он мне объект по результатам создал, но это и так давно умеют делать и без него. Потом мне гораздо проще менять SQL код, если чего не так, чем исходники. Вот и не понятно, чего это носятся все с этим linq. Хотя, конечно, если это не SQL провайдер, то может имеет смысл, но всё равно для XML, например, имхо часто вполне хватало XPath.
H>Ага, действительно, странно было бы написать всю бизнес-логику на T-SQL и использвать LINQ 2 SQL для получения результата на клиенте А повторное использование написанной таким образом БЛ меня лично повергает в большое уныние
Какая-такая бизнес логика в SQL? Я говорю о отчётах, например, или выборка данных для "сложных" форм. Там чаще всего идёт толпа join и некоторое количество union с группировками и агрегациями. Тут, кстати, вижу плюс использования обычного SQL в том, что чтобы проверить работает ли запрос, мне не надо проект собирать весь. Как вы, кстати, собираетесь реализовывать бизнес логику на Linq 2 sql?
Хотя, конечно, понятно, что с linq 2 sql мне не надо на каждый мелкий запрос делать sql функцию и плодить к ней бизнес объект. Хотя, не помню, когда последний раз нужен был такой простой запрос, разультаты которого нельзя было бы вытянуть уже из загруженных бизнес объектов.
Здравствуйте, trickyKid, Вы писали:
K>>>Давно мучает вопрос по этому поводу. Если у меня есть более-менее серьёзный запрос к базе данных я делаю пользовательскую табличную функцию с параметрами и ложу её на сервер, где помещаю всё логику по выборке данных. <SKIPPED>
K>Какая-такая бизнес логика в SQL?
Ну вот та, что в предыдущем посте. Или это просто логикаб не бизнес?
K>Я говорю о отчётах, например, или выборка данных для "сложных" форм. Там чаще всего идёт толпа join и некоторое количество union с группировками и агрегациями. Тут, кстати, вижу плюс использования обычного SQL в том, что чтобы проверить работает ли запрос, мне не надо проект собирать весь.
Слово "отчеты" появились только сейчас. Я не придираюсь к словам, просто отчеты это немного другие "звери". Повторное использование кода в них не так важно. Естественно, некоторые задачи решаются лучше с помощью T-SQL.
K>Как вы, кстати, собираетесь реализовывать бизнес логику на Linq 2 sql?
Никак. Ее можно реализовать на *.NET языке, а LINQ 2 SQL является мостом между T-SQL с его таблицами и ООЯ с его объектами.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, trickyKid, Вы писали:
В целом, я конечо, понимаю что это дело нужное и полезное, но похоже пройдёт время, пока он станет общеиспользуемым.
Было бы интересно посмотреть на нормальные решения, а не на примеры msdn или с блогов, где параметры hardcoded и 5 таблиц максимум используется.
K>>Хотя, конечно, если это не SQL провайдер, то может имеет смысл, но всё равно для XML, например, имхо часто вполне хватало XPath.
VD>Согласен. Но XPath не встроен в язык вроде Шарпа. Надо понимать, что Линк-запросы — это не SQL. Это похожий на SQL язык. Но его база — это фунциональное программирование, т.е. декомпозиция запроса на вызов нескольких фуцний получающих критерии в качестве параметров (в виде фунций-лямбд). Таким образом это универсальный язык обработки данных. Наверно можно было бы облачить его в форму XPath, но выбран был именно SQL. Видимо потому, что он лучше ложится на фунциональную декомпозицию.
С XML согласен, выглядит более удобным использовать human like запросы linq 2 xml чем время от времени вспоминать где какие слэши ставить в xpath.
Здравствуйте, hugo, Вы писали:
H>Здравствуйте, trickyKid, Вы писали:
K>>>>Давно мучает вопрос по этому поводу. Если у меня есть более-менее серьёзный запрос к базе данных я делаю пользовательскую табличную функцию с параметрами и ложу её на сервер, где помещаю всё логику по выборке данных. <SKIPPED>
K>>Какая-такая бизнес логика в SQL?
H>Ну вот та, что в предыдущем посте. Или это просто логикаб не бизнес?
Ну я имел ввиду максимум логику обработки параметров, а в остальном имел ввиду просто сложный запрос к базе. Linq ведь язык запросов? Сам не люблю когда появляются теже курсоры.
K>>Я говорю о отчётах, например, или выборка данных для "сложных" форм. Там чаще всего идёт толпа join и некоторое количество union с группировками и агрегациями. Тут, кстати, вижу плюс использования обычного SQL в том, что чтобы проверить работает ли запрос, мне не надо проект собирать весь.
H>Слово "отчеты" появились только сейчас. Я не придираюсь к словам, просто отчеты это немного другие "звери". Повторное использование кода в них не так важно. Естественно, некоторые задачи решаются лучше с помощью T-SQL.
Ну, не только отчёты... Если на форме торчит результат выборки из пару десятков таблиц, то имхо, тут тоже проще процедуру сделать...
K>>Как вы, кстати, собираетесь реализовывать бизнес логику на Linq 2 sql? H>Никак. Ее можно реализовать на *.NET языке, а LINQ 2 SQL является мостом между T-SQL с его таблицами и ООЯ с его объектами.
Здесь будут множественные вызовы в базу и скорее всего транзакция на всё время работы этого кода, что тоже не есть хорошо. Хотя, конечно, приятнее писать логику(циклы и условия) на C# чем на TSQL.
Здравствуйте, hugo, Вы писали:
H>Здравствуйте, hell citizen, Вы писали:
HC>>Такие средства есть, они хороши. Чем это новое средство лучше? H>А кто сказал, что оно лучше? LINQ to SQL — ИМХО вполне логичное применение технологии LINQ. Можно рассматривать, как замену DataSet'у.
Ну прям таки замена DataSet... Я что могу достать несколько связанных таблиц одним запросом? А версии записей разве он умеет отслеживать..?
K>Ну, не только отчёты... Если на форме торчит результат выборки из пару десятков таблиц, то имхо, тут тоже проще процедуру сделать...
Почему же проще? Вполне красиво такой же запрос можно оформить и на LINQ'e. И вернет он объект/список объектов.
K>>>Как вы, кстати, собираетесь реализовывать бизнес логику на Linq 2 sql? H>>Никак. Ее можно реализовать на *.NET языке, а LINQ 2 SQL является мостом между T-SQL с его таблицами и ООЯ с его объектами.
K>Здесь будут множественные вызовы в базу и скорее всего транзакция на всё время работы этого кода, что тоже не есть хорошо. Хотя, конечно, приятнее писать логику(циклы и условия) на C# чем на TSQL.
А если аналогичный запрос оформить в SP, то там транзакция не на все время работы скрипта будет? Не стоит также забывать обработку ошибок, которая на T-SQL выглядит совсем не так аккуратно, как, скажем, на C#, да и усилий для правильного написания кода обработки необходимо приложить значительно больше.
Здравствуйте, trickyKid, Вы писали:
K>Ну прям таки замена DataSet... Я что могу достать несколько связанных таблиц одним запросом?
Да, а в чем проблема? Он на то и LINQ.
VD>Приемущество именно Линка как раз и заключается в том, что запросы сливаются с основным языком. Производится сквозной контроль типов. Мы уже не может мполучить ошибку связанную с типом во время выполнения.
Хотелось бы добавить...
На самом деле вот какая штука не очень хорошая имеет место быть. Компилятором LINQ-выражение будет признано верным с точки зрения системы типов CLR.
Но для того механизма, который будет выполнять этот запрос в конечном итоге, правила корректности могут несколько отличаться.
Например, какой-нибудь Linq2Xxx может не поддерживать оператор is или например оператор ??. Ну и в конце концов, в Linq-выражениях могут использоваться какие-то произвольные внешние статические методы, незнакомые генератору SQL.
Соответственно, ТАКИЕ ошибки выявляются только на этапе выполнения и никакой помощи во время разработки не приходится ждять ни от IntelliSense, ни от компилятора, ни от кого-то еще
K> Тут, кстати, вижу плюс использования обычного SQL в том, что чтобы проверить работает ли запрос, мне не надо проект собирать весь.
Данный "плюс использования обычного SQL" нивелируется наличием в VS2008TS такой фичи как панелька "Object Test Bench" (хотя может она и в Pro) есть. Тем кто не знает — это панелька, кот. позволяет создать объект произовольного типа с указанием параметров конструктора и вызвать его метод — подебажить...
Я, правда, должен признаться не смог её запустить (может подскажете как? — не могу в неё класс закинуть для конструирования).
K>>Ну прям таки замена DataSet... Я что могу достать несколько связанных таблиц одним запросом? H>Да, а в чем проблема? Он на то и LINQ.
А можно простенький примерчик для ньюьбов? Допустим для того же примера: получить список кастомеров и для каждого OrderList покупок.
Я связь своего кода с базой ранее делал через BLToolKit, хотелось бы попробовать новое решение, но пока нет книги толковой под рукой, а вот интересно.
Здравствуйте, _Budda_, Вы писали:
K>>>Ну прям таки замена DataSet... Я что могу достать несколько связанных таблиц одним запросом? H>>Да, а в чем проблема? Он на то и LINQ. _B_>А можно простенький примерчик для ньюьбов? Допустим для того же примера: получить список кастомеров и для каждого OrderList покупок.
Сам полный ньюб, первый раз писал. Вот что получилось:
static void Main(string[] args)
{
NorthwindDataContext db = new NorthwindDataContext();
var customers = from c in db.Customers select c;
foreach (var cust in customers)
{
Console.WriteLine("Customer {0} ID = {1}", cust.ContactName, cust.CustomerID);
foreach (var order in cust.Orders)
{
Console.WriteLine(" Order Date = {0}", order.OrderDate);
foreach (var orderDetail in order.Order_Details)
{
Console.WriteLine(" Product {0} Quantity = {1}", orderDetail.Product.ProductName, orderDetail.Quantity);
}
}
Console.WriteLine();
}
Console.ReadKey();
}
Класс NorthwindDataContext сгенерил с помощью студии, тупо перетащив в дизайнер все таблицы из базы. БД — Northwind от Microsoft.
Здравствуйте, _Budda_, Вы писали:
_B_>Данный "плюс использования обычного SQL" нивелируется наличием в VS2008TS такой фичи как панелька "Object Test Bench" (хотя может она и в Pro) есть. Тем кто не знает — это панелька, кот. позволяет создать объект произовольного типа с указанием параметров конструктора и вызвать его метод — подебажить... _B_>Я, правда, должен признаться не смог её запустить (может подскажете как? — не могу в неё класс закинуть для конструирования).
Открываешь окошко Class View, там правой кнопкой на нужном классе и выбираешь Create Instance и выбираешь конструктор
Простите, где-то видел, но не помню где. Эта база, Northwind — это вроде какая-то стандартная, кот. поставляется вместе c MSSQL? Т.е. надо поставить последнее, дабы получить первое?
G>
G> static void Main(string[] args)
G> {
G> NorthwindDataContext db = new NorthwindDataContext();
G> var customers = from c in db.Customers select c;
G> foreach (var cust in customers)
G> {
G> Console.WriteLine("Customer {0} ID = {1}", cust.ContactName, cust.CustomerID);
G> foreach (var order in cust.Orders)
G> {
G> Console.WriteLine(" Order Date = {0}", order.OrderDate);
G> foreach (var orderDetail in order.Order_Details)
G> {
G> Console.WriteLine(" Product {0} Quantity = {1}", orderDetail.Product.ProductName, orderDetail.Quantity);
G> }
G> }
G> Console.WriteLine();
G> }
G> Console.ReadKey();
G> }
G>
G>Класс NorthwindDataContext сгенерил с помощью студии, тупо перетащив в дизайнер все таблицы из базы. БД — Northwind от Microsoft.
кхэх... и это всё? Т.е. всё, что надо сделать это:
var customers = from c in db.Customers select c;
?
ммм. появилось вопросов больше, чем было (что впринципе логично, при вхождении в новую область).
1. Но насколько я понимаю, в этом случае из базы выгребается ВСЁ, что связано с таблицей Customers?
2. или же необходимые данные выбираются по мере обращения к членам объекта customers?
_B_>>Я, правда, должен признаться не смог её запустить (может подскажете как? — не могу в неё класс закинуть для конструирования).
_>Открываешь окошко Class View, там правой кнопкой на нужном классе и выбираешь Create Instance и выбираешь конструктор
ну да, это я читал. Но когда я делаю "правой кнопкой на нужном классе", то в контекстном меню нет пункта "Create Instance"...?
Клас — примитивнейший.
public class C1
{
public C1(int a)
{ A=a; }
public int A { get; set; }
}
Здравствуйте, _Budda_, Вы писали:
_B_>Простите, где-то видел, но не помню где. Эта база, Northwind — это вроде какая-то стандартная, кот. поставляется вместе c MSSQL? Т.е. надо поставить последнее, дабы получить первое?
G>>
G>> static void Main(string[] args)
G>> {
G>> NorthwindDataContext db = new NorthwindDataContext();
G>> var customers = from c in db.Customers select c;
G>> foreach (var cust in customers)
G>> {
G>> Console.WriteLine("Customer {0} ID = {1}", cust.ContactName, cust.CustomerID);
G>> foreach (var order in cust.Orders)
G>> {
G>> Console.WriteLine(" Order Date = {0}", order.OrderDate);
G>> foreach (var orderDetail in order.Order_Details)
G>> {
G>> Console.WriteLine(" Product {0} Quantity = {1}", orderDetail.Product.ProductName, orderDetail.Quantity);
G>> }
G>> }
G>> Console.WriteLine();
G>> }
G>> Console.ReadKey();
G>> }
G>>
G>>Класс NorthwindDataContext сгенерил с помощью студии, тупо перетащив в дизайнер все таблицы из базы. БД — Northwind от Microsoft. _B_>кхэх... и это всё? Т.е. всё, что надо сделать это: _B_>
_B_>var customers = from c in db.Customers select c;
_B_>
_B_>?
Ну как видишь.
_B_>ммм. появилось вопросов больше, чем было (что впринципе логично, при вхождении в новую область). _B_>1. Но насколько я понимаю, в этом случае из базы выгребается ВСЁ, что связано с таблицей Customers? _B_>2. или же необходимые данные выбираются по мере обращения к членам объекта customers?
Профайлер показал что на каждый foreach по одному запросу. То есть кастомеры считываются один раз, orders выбирается столько раз, сколько кастомеров, с фильтром по ключу естественно, итд
G>Профайлер показал что на каждый foreach по одному запросу. То есть кастомеры считываются один раз, orders выбирается столько раз, сколько кастомеров, с фильтром по ключу естественно, итд
Т.о. код
var customers = from c in db.Customers select c;
выполняет создание контейнера и выбирает его записи из таблицы Customers. При обращении к его заказам
foreach (var order in cust.Orders)
в момент cust.Orders выполняется аналогичная операция уже для заказов. Но вопрос: кто выполняет новый поход в БД? ЛинКью? Или член Orders класса Customers? ИМХО последнее. Но он опять же юзает ЛинКью:
как-то так
var _orders = from o in db.Orders select o;
Подумаю вслух:
Если раньше для подобной операции мне надо было сделать:
public abstract class ACustomers{
// описать привязку полям к членам
}
List<ACustomers> customers ;
using (DbManager db = new DbManager())
{
customers = db
.SetCommand("SELECT Id, Name, ... FROM customers")// или SetSpCommand("GetCustomers")
.ExecuteList<ACustomers>()
;
}
То теперь... создавать класс для меня будет студия, а формировать и выполнять запрос ЛинКью.
Не могу понять только нюанс создания классов: ЧТО ИМЕННО выполняет эту функцию. То что это делает студия понятно, но какая её часть?
Linq2SQL это не язык запросов к БД, это набор классов, методов расширения и атрибутов, которые позволяют с помощью языка запросов Linq обращаться к БД.
Фактически всю работу по загрузке связанных таблиц выполняет класс EntitySet.
прочтите раздел MSDN про linq, там не очень много, если английского совсем не знаете, то хотя бы посмотрите картинки и повыполняйте приводимые примеры
посмотрите, что в отладчике происходит с вашим запросом
не додумывайте технологии, а просто изучайте
B>>То теперь... создавать класс для меня будет студия, а формировать и выполнять запрос ЛинКью. G>Linq2SQL это не язык запросов к БД, это набор классов, методов расширения и атрибутов, которые позволяют с помощью языка запросов Linq обращаться к БД.
Это я понимаю G>Фактически всю работу по загрузке связанных таблиц выполняет класс EntitySet.
А EntitySet — класс из System.Linq, верно?
Собственно не вопрос, какой именно класс загружает данные. Главное, что кто-то из System.LinQ.
Сумбур (для меня) внесло использование генерируемых студией классов... я просто не знаю их внутренностей... потому и возникают вопросы...
Мне просто чтобы посмотреть надо поставить MS SQL... потому задаю вопросы человеку, которому на них интересно отвечать... А>не додумывайте технологии, а просто изучайте
А что мы додумываем? Что в примере gandjustas'а додуманного?
Здравствуйте, _Budda_, Вы писали:
G>>Фактически всю работу по загрузке связанных таблиц выполняет класс EntitySet. _B_>А EntitySet — класс из System.Linq, верно?
System.Data.Linq
Linq2Sql это сборка System.Data.Linq.dll
_B_>Собственно не вопрос, какой именно класс загружает данные. Главное, что кто-то из System.LinQ. _B_>Сумбур (для меня) внесло использование генерируемых студией классов... я просто не знаю их внутренностей... потому и возникают вопросы...
А посмотреть?
_B_>>Собственно не вопрос, какой именно класс загружает данные. Главное, что кто-то из System.LinQ. _B_>>Сумбур (для меня) внесло использование генерируемых студией классов... я просто не знаю их внутренностей... потому и возникают вопросы... G>А посмотреть?
Обязательно посмотрю. Но щас нет под рукой установленной MSSQL с базой, чтобы посмотреть
Здравствуйте, _Budda_, Вы писали:
_B_>ну да, это я читал. Но когда я делаю "правой кнопкой на нужном классе", то в контекстном меню нет пункта "Create Instance"...?
Редакция VS2008 какая? Оно доступно только в Team-редакциях.
Здравствуйте, denisio_mcp, Вы писали:
_>Здравствуйте, _Budda_, Вы писали:
_B_>>ну да, это я читал. Но когда я делаю "правой кнопкой на нужном классе", то в контекстном меню нет пункта "Create Instance"...?
_>Редакция VS2008 какая? Оно доступно только в Team-редакциях.
TS редакция, тим юниты есть... Вид TestBench есть, в нём написано то же, что ты мне советовал выше... но добавить туда чего-то не получается
_>Редакция VS2008 какая? Оно доступно только в Team-редакциях.
Полез в "About" а там куча всего... может и нет того, что нужно для Test Bench. Посмотри, плиз.
Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5
Installed Edition: Enterprise
Microsoft Visual Basic 2008 хххх-ххх-ххххххх-ххххх
Microsoft Visual Basic 2008
Microsoft Visual C# 2008 хххх-ххх-ххххххх-ххххх
Microsoft Visual C# 2008
Microsoft Visual C++ 2008 хххх-ххх-ххххххх-ххххх
Microsoft Visual C++ 2008
Microsoft Visual Studio 2008 Tools for Office хххх-ххх-ххххххх-ххххх
Microsoft Visual Studio 2008 Tools for Office
Microsoft Visual Studio Team System 2008 Architecture Edition хххх-ххх-ххххххх-ххххх
Microsoft Visual Studio Team System 2008 Architecture Edition
Microsoft Visual Studio Team System 2008 Database Edition хххх-ххх-ххххххх-ххххх
Microsoft Visual Studio Team System 2008 Database Edition
Microsoft Visual Studio Team System 2008 Development Edition хххх-ххх-ххххххх-ххххх
Microsoft Visual Studio Team System 2008 Development Edition
Здравствуйте, _Budda_, Вы писали:
_>>Редакция VS2008 какая? Оно доступно только в Team-редакциях. _B_>Полез в "About" а там куча всего... может и нет того, что нужно для Test Bench. Посмотри, плиз.
Здравствуйте, _Budda_, Вы писали:
_B_>>>Собственно не вопрос, какой именно класс загружает данные. Главное, что кто-то из System.LinQ. _B_>>>Сумбур (для меня) внесло использование генерируемых студией классов... я просто не знаю их внутренностей... потому и возникают вопросы... G>>А посмотреть? _B_>Обязательно посмотрю. Но щас нет под рукой установленной MSSQL с базой, чтобы посмотреть
Linq должен работать и для SQL Server Compact — его ставить практически не надо.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, AndrewVK, Вы писали:
TK>>Linq должен работать и для SQL Server Compact — его ставить практически не надо. AVK>Ну, пока что Linq2Sql работает только с MSSQL, поддержка иных БД пока только планируется, а у CE довольно много отличий.
Пробовал? У меня Linq2Sql работает и с базами SqlServerCe.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, AndrewVK, Вы писали:
AVK>Ну, пока что Linq2Sql работает только с MSSQL, поддержка иных БД пока только планируется, а у CE довольно много отличий.
Differences between LINQ to SQL for SQL Server and SSCE:
Notice the command line tool I referred you to for generating the object-relational mapping. While SQL Server will have a nice designer to do the same thing, atleast till Orcas, SQL Compact will have to do with SqlMetal command line tool. No designer support. (If you prefer command line tools like me, you shall have no problem!)
Note: SQLMetal extracts SQL metadata from your database and generates a source file containing entity class declarations. Alternatively, you can split the process into two steps, first generating an XML file representing the SQL metadata and then later translating that XML file into a source file containing declarations. This split process allows you to retain the metadata as a file so you may edit it.
LINQ queries are eventually mapped to SQL queries. Since SQL supported by SSC is a strict subset of that on SQL Server, LINQ follows suit. (To see the SQL which is generated, set db.Log = Console.Out where db is the DataContext.).
Stored procedures and views are not supported by SSC, and so will not be supported through LINQ to SQL either.
... << RSDN@Home 1.2.0 alpha rev. 786>>
((lambda (x) (list x (list 'quote x))) '(lambda (x) (list x (list 'quote x))))
Здравствуйте, hell citizen, Вы писали:
HC>А в чем смысл такого средства? У меня есть функция, которая загружает списки из БД по коду объекта или по имени хп, чем этот LINQ лучше?
Здравствуйте, hugo, Вы писали:
H>Ага, действительно, странно было бы написать всю бизнес-логику на T-SQL и использвать LINQ 2 SQL для получения результата на клиенте А повторное использование написанной таким образом БЛ меня лично повергает в большое уныние
Даже в таком случае будет выгода, так как при измененеии процедур и функций в СУБД при перегенерации метаданных буду выявляться несоотвествия типов и т.п. Это облегчит поиск мест в программе которые нужно привести в соотвествие с БД.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, trickyKid, Вы писали:
K>Какая-такая бизнес логика в SQL? Я говорю о отчётах, например, или выборка данных для "сложных" форм. Там чаще всего идёт толпа join и некоторое количество union с группировками и агрегациями.
Дык join-ы и union-ы ничем не хуже делать и средствами ЛИНК-а.
K>Тут, кстати, вижу плюс использования обычного SQL в том, что чтобы проверить работает ли запрос, мне не надо проект собирать весь.
Тут сама компиляция и интелисенс снимет большую часть проблем. К тому же, надо понимать, что мелких и простых запросов к БД будет куда больше. Отлаживать их отдельно особого смысла нет. А вот тестировать (в программе) надо. Так что это только повысить твою производительность.
Ну, а для тестирования сложных запросов можно создать интерпретатор ЛИНК-а который позволит интерактивно проверять запросы. Задача эта довольно простая. Не удивлюсь если он уже создан или запросы можно просто тестировать в окне Immediate в VS2008.
K> Как вы, кстати, собираетесь реализовывать бизнес логику на Linq 2 sql?
Гы. В сто раз лучше чем на убогом T-SQL. В T-SQL есть одно достоинство — SQL, а вот "T-" в нем очень поганое. Это убогий язык с массой ограничений.
K>Хотя, конечно, понятно, что с linq 2 sql мне не надо на каждый мелкий запрос делать sql функцию и плодить к ней бизнес объект. Хотя, не помню, когда последний раз нужен был такой простой запрос, разультаты которого нельзя было бы вытянуть уже из загруженных бизнес объектов.
Дык сам подход с кэшированием, да и созданием бизнес-объектов порочен и ущербен. Именно он вынуждает делать переборы вместо запросов и сажает производительность.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, trickyKid, Вы писали:
K>Ну, не только отчёты... Если на форме торчит результат выборки из пару десятков таблиц, то имхо, тут тоже проще процедуру сделать...
Ну, и какая разница будет ли эта хранимая процедура или функция на C# 3.0 или другом совместимом с ЛИНК-ом языке? T-SQL убог. Современные ЯП куда гибче и существенно быстрее. Понятно, что в основном там будут запросы к БД и скорость тут не очень важна, но все же куда приятнее чувствовать под копотом мощьный движок, а не дряглый и малосильный. T-SQL максимум что позволяет, это поместить все запросы в СУБД. Но обычно это не является критичным. Ведь выборка делается в бизнес-уровне который соеденен с СУБД широким и не латентным каналом связи. В прочем, уверен, что ЛИНК можно применять из из того же MS SQL Swrver, так что вообще не ясно в чем проблема.
Лично я не задумываясь променяют T-SQL на ЛИНК.
K>Здесь будут множественные вызовы в базу и скорее всего транзакция на всё время работы этого кода, что тоже не есть хорошо.
Обычно время затрачиваемое на переход гранниц между промежуточным слоем и СУБД не сравнимо со временем запросов. Так что эти опасения не очень обоснованны. К тому же хранимки тоже можно писать на Шарпе. А это позволяет избавиться от оверхэда вызова.
В общем, это предварительнрые оптимизации. Вот если вы будете сдавать систему и профайлером выявите, что в некоторых местах оверхэд на межсетевые вызовы слишком велик, то и запихнете эти места в хранимки. А так вы просто убьете свое веремя на борьбу с собственными страхами.
K>Хотя, конечно, приятнее писать логику(циклы и условия) на C# чем на TSQL.
Вот именно. А лучеш вообще без циклов...
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Ну, а для тестирования сложных запросов можно создать интерпретатор ЛИНК-а который позволит интерактивно проверять запросы. Задача эта довольно простая. Не удивлюсь если он уже создан или запросы можно просто тестировать в окне Immediate в VS2008.
Вот это можно использовать для просмотра и исполнения Linq to Sql запросов в дебаге. Правда этот инструмент довольно сырой.
В разгоревшейся дискусии о Linq2sql не затронута тема ADO.NET 3.0 — т.е. Entity FrameWork. Может я просто чего-то не знаю... тогда просветите, плиз.
Или "это" (Entity Framework) — и есть "вот то самое" вставляние базы данных в проект, на основе которого генерятся классы, представляющие таблицы и их данные... ?
Здравствуйте, Alexey M., Вы писали:
AM>Вот это можно использовать для просмотра и исполнения Linq to Sql запросов в дебаге. Правда этот инструмент довольно сырой.
Это немного не то, но тоже вещь полезная.
Это визуализатор. Он позволяет в режиме отладки Студии видеть, что тварится в запросе. Я же говорил, про отдельную утилиту которая позволяла бы писать и сразу же интерактивно выолнять ЛИНК-запросы.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, _Budda_, Вы писали:
_B_>В разгоревшейся дискусии о Linq2sql не затронута тема ADO.NET 3.0 — т.е. Entity FrameWork. Может я просто чего-то не знаю... тогда просветите, плиз.
Лично я с ним не возился. Так что пусть АВК и IB ответят, если копили... У них должен быть доступ к альфам и т.п.
_B_>Или "это" (Entity Framework) — и есть "вот то самое" вставляние базы данных в проект, на основе которого генерятся классы, представляющие таблицы и их данные... ?
Это делает SQLMetal. А Entity Framework должен по уму делать обратный процесс. Предоставлять некий дизайнер оперирующий некими высокоуровневыми сущностями (моделью). А уже по модели должна генерироваться БД и классы для ее отображения. Но это все мое видение, которое может не иметь ничего общего с действительностью.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, _Budda_, Вы писали:
_B_>>В разгоревшейся дискусии о Linq2sql не затронута тема ADO.NET 3.0 — т.е. Entity FrameWork. Может я просто чего-то не знаю... тогда просветите, плиз.
VD>Лично я с ним не возился. Так что пусть АВК и IB ответят, если копили... У них должен быть доступ к альфам и т.п.
К слову: входит ли этот энтити фрэймворк в .НЕТ фрэймворк 3.0 или 3.5?
_B_>>Или "это" (Entity Framework) — и есть "вот то самое" вставляние базы данных в проект, на основе которого генерятся классы, представляющие таблицы и их данные... ?
VD>Это делает SQLMetal. А Entity Framework должен по уму делать обратный процесс. Предоставлять некий дизайнер оперирующий некими высокоуровневыми сущностями (моделью). А уже по модели должна генерироваться БД и классы для ее отображения. Но это все мое видение, которое может не иметь ничего общего с действительностью.
Порылся чуток в гугле, из найденного понял, что Metal — это консольная программулина, которая вроде как идёт в поставке со студией (2008?). Но в одном из постов топика мне намекали, что она интегрирована в студию... всё верно?
Здравствуйте, _Budda_, Вы писали:
VD>>Лично я с ним не возился. Так что пусть АВК и IB ответят, если копили... У них должен быть доступ к альфам и т.п. _B_>К слову: входит ли этот энтити фрэймворк в .НЕТ фрэймворк 3.0 или 3.5?
Нет, не входит — выйдет позже отдельным пакетом.
VD>>Это делает SQLMetal. А Entity Framework должен по уму делать обратный процесс. Предоставлять некий дизайнер оперирующий некими высокоуровневыми сущностями (моделью). А уже по модели должна генерироваться БД и классы для ее отображения. Но это все мое видение, которое может не иметь ничего общего с действительностью.
_B_>Порылся чуток в гугле, из найденного понял, что Metal — это консольная программулина, которая вроде как идёт в поставке со студией (2008?). Но в одном из постов топика мне намекали, что она интегрирована в студию... всё верно?
Нет, не интегрирована. Есть в составе Windows SDK
... << RSDN@Home 1.2.0 alpha rev. 786>>
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, _Budda_, Вы писали:
_B_>Порылся чуток в гугле, из найденного понял, что Metal — это консольная программулина, которая вроде как идёт в поставке со студией (2008?). Но в одном из постов топика мне намекали, что она интегрирована в студию... всё верно?
В состав студии входит визуальный редактор назначение которого аналогично SQLMetal.
Здравствуйте, Alexey M., Вы писали:
AM>Здравствуйте, _Budda_, Вы писали:
_B_>>Порылся чуток в гугле, из найденного понял, что Metal — это консольная программулина, которая вроде как идёт в поставке со студией (2008?). Но в одном из постов топика мне намекали, что она интегрирована в студию... всё верно?
AM>В состав студии входит визуальный редактор назначение которого аналогично SQLMetal.
Скажи, плиз, где его найти? Я видел "Server Explorer", но это другое, верно?
Здравствуйте, _Budda_, Вы писали:
_B_>Скажи, плиз, где его найти? Я видел "Server Explorer", но это другое, верно?
Добавляешь новый файл в проект, при этом выбираешь тип "Linq to Sql classes". Дальше можно будет кидать таблицы из Сервер Эксплорера на поверхность редактирования.
Здравствуйте, Alexey M., Вы писали:
AM>Здравствуйте, _Budda_, Вы писали:
_B_>>Скажи, плиз, где его найти? Я видел "Server Explorer", но это другое, верно?
AM>Добавляешь новый файл в проект, при этом выбираешь тип "Linq to Sql classes". Дальше можно будет кидать таблицы из Сервер Эксплорера на поверхность редактирования.
Здравствуйте, VladD2, Вы писали:
VD>Это визуализатор. Он позволяет в режиме отладки Студии видеть, что тварится в запросе. Я же говорил, про отдельную утилиту которая позволяла бы писать и сразу же интерактивно выолнять ЛИНК-запросы.
Не, это все не то.
Скорее, нужен плагин к студии, чтобы, написав запрос с использованием IntelliSense и прочей лабуды, можно было встать на запрос, нажать капу, оно бы спросило значения внешних (по отношению к запросу) параметров, с учетом их типов, а потом бы скомпиляло, и выполнило.
Вот только все равно это полноценно скорее всего не получится.. Потому как и параметры могут быть сложными объектами и вообще..
Да, в этом плане SQL конечно чем-то поудобнее.
С другой стороны, можно написать unit-тест с LINQ-запросом, выполнил, проверил результат, прибил тест. Или даже оставил с каким-то ключевым Assert'ом.
VD>Лично я с ним не возился. Так что пусть АВК и IB ответят, если копили... У них должен быть доступ к альфам и т.п.
Доступ к альфам у всех есть, это выходило как CTP или что-то такое...
VD>Это делает SQLMetal. А Entity Framework должен по уму делать обратный процесс. Предоставлять некий дизайнер оперирующий некими высокоуровневыми сущностями (моделью). А уже по модели должна генерироваться БД и классы для ее отображения. Но это все мое видение, которое может не иметь ничего общего с действительностью.
Да там NHibernate от Microsoft просто С поддержкой LINQ и дизайнером.
Ну или что-то очень-очень похожее на NHibernate.
Re[4]: К вопросу о LINQ to SQL и O/R Mapper-ах
От:
Аноним
Дата:
15.01.08 19:41
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:
iT>Да там NHibernate от Microsoft просто С поддержкой LINQ и дизайнером. iT>Ну или что-то очень-очень похожее на NHibernate.
в EntityFramework требуется наследование от базового класса, в NHibernate — нет. А это создаёт неудобства при работе с EF в распределённых системах.
Здравствуйте, Аноним, Вы писали: А>в EntityFramework требуется наследование от базового класса, в NHibernate — нет. А это создаёт неудобства при работе с EF в распределённых системах.
В EntityFramework обещают избавиться от наследования от базового класса, тем не менее хоть в NHibernate, хоть в EDF или любом другом ORM на практике часто приходится этот базовый класс вводить искусственно для реализации биндинга, Undo/Redo, Validation, Security и прочей сопутствующей обвязки. В "голом" виде POCO/POJO практически не используется никогда, разве что только для отображения в readonly (frontend какой нибудь).
Что за неудобства в распределенных системах? Ведь все что касается передачи данных настраивается контрактами или атрибутами сериализации.
Кто-нибудь знает как обстоят дела с проблемой потери состояния в Entity Data FrameWork при передаче объектов сервисам.
Последнее предлагаемое решение проблемы — перемапить объект на объект(новый) в сервисе и сохранить новый:
newObject.Name = transferObject.Name;
newObject.Desc = transferObject.Desc;
...
Но это сами понимаете тупость — избавились от ручного маппинга в одном месте, получили в другом.
Как обстоят дела сейчас?
Здравствуйте, снежок, Вы писали:
С>Что за неудобства в распределенных системах? Ведь все что касается передачи данных настраивается контрактами или атрибутами сериализации.
неудобства в передаче графа
Danny Simmons в своём блоге (http://blogs.msdn.com/dsimmons/) пишет про то, как пытаются решить проблему (EntityBag)
Здравствуйте, снежок, Вы писали:
С>Но это сами понимаете тупость — избавились от ручного маппинга в одном месте, получили в другом. С>Как обстоят дела сейчас?
Что мешает сделать автоматический маппер?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, снежок, Вы писали:
С>тем не менее хоть в NHibernate, хоть в EDF или любом другом ORM на практике часто приходится этот базовый класс вводить искусственно для реализации биндинга, Undo/Redo, Validation, Security и прочей сопутствующей обвязки
Ну да, настоящим пацанам никакие архитектурные изыски не помеха.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
С>>тем не менее хоть в NHibernate, хоть в EDF или любом другом ORM на практике часто приходится этот базовый класс вводить искусственно для реализации биндинга, Undo/Redo, Validation, Security и прочей сопутствующей обвязки
AVK>Ну да, настоящим пацанам никакие архитектурные изыски не помеха.
Ну а куда ты вынесешь общий функционал DDD объектов и коллекций?
Здравствуйте, TK, Вы писали:
TK>Что мешает сделать автоматический маппер?
Не слишком ли много мапперов и слоев в которых этот маппинг происходит для одного фреймворка?
Здравствуйте, Ziaw, Вы писали: Z>вы бы сначала обрисовали функционал.
Коротко по выше перечисленному — Lhotka C# Bussiness Objects 2005 (CSLA).
...
Валидация должна происходить на всех слоях, а не только в Presentation. Иногда с бизес-объектами и без интерфейса есть необходимость работать.
Здравствуйте, снежок, Вы писали:
Z>>вы бы сначала обрисовали функционал. С>Коротко по выше перечисленному — Lhotka C# Bussiness Objects 2005 (CSLA). С>... С>Валидация должна происходить на всех слоях, а не только в Presentation. Иногда с бизес-объектами и без интерфейса есть необходимость работать.
Ну и что? Для чего здесь общий предок?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
С>>Коротко по выше перечисленному — Lhotka C# Bussiness Objects 2005 (CSLA). С>>... С>>Валидация должна происходить на всех слоях, а не только в Presentation. Иногда с бизес-объектами и без интерфейса есть необходимость работать.
_FR>Ну и что? Для чего здесь общий предок?
Извените, что встряю в разговор.
Сюдя по всему имеется в виду набор хелпер методов базового класса, которые надо в ручную вызвать в переопределённом методе, для того чтобы построить список правил валидации, которые потом применяются для проверки свойств объекта.
Естественно никаких причин держать все эти методы в базовом классе, кроме убеждения, что раз ООП — значит весь функционал для работы с объектом надо запихнуть в базовый класс.
Здравствуйте, снежок, Вы писали:
TK>>Что мешает сделать автоматический маппер? С>Не слишком ли много мапперов и слоев в которых этот маппинг происходит для одного фреймворка?
Если вам кажется, что слоев слишком много — скорее всего, вы просто используете инструмент не по назначению.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, Curufinwe, Вы писали:
C>Естественно никаких причин держать все эти методы в базовом классе, кроме убеждения, что раз ООП — значит весь функционал для работы с объектом надо запихнуть в базовый класс.
Вредное, безграмотное и частое, замечу, убеждение
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, Curufinwe, Вы писали:
C>>Естественно никаких причин держать все эти методы в базовом классе, кроме убеждения, что раз ООП — значит весь функционал для работы с объектом надо запихнуть в базовый класс.
_FR>Вредное, безграмотное и частое, замечу, убеждение
Не сыпте соль на рану. Сами мучаемся, по требованию заказчика с CSLA .
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, trickyKid, Вы писали:
K>>Ну, не только отчёты... Если на форме торчит результат выборки из пару десятков таблиц, то имхо, тут тоже проще процедуру сделать...
VD>Ну, и какая разница будет ли эта хранимая процедура или функция на C# 3.0 или другом совместимом с ЛИНК-ом языке? T-SQL убог. Современные ЯП куда гибче и существенно быстрее. Понятно, что в основном там будут запросы к БД и скорость тут не очень важна, но все же куда приятнее чувствовать под копотом мощьный движок, а не дряглый и малосильный. T-SQL максимум что позволяет, это поместить все запросы в СУБД. Но обычно это не является критичным. Ведь выборка делается в бизнес-уровне который соеденен с СУБД широким и не латентным каналом связи. В прочем, уверен, что ЛИНК можно применять из из того же MS SQL Swrver, так что вообще не ясно в чем проблема.
VD>Лично я не задумываясь променяют T-SQL на ЛИНК.
Зря зря батеьнка.
T-SQL надежен универсален и отлажен, 20 годами реляционной теории и мелкософтом
А Linq — пока неизвестно что, а именно:
версиями в обьектах не управляет.
генерит запросы плохо. так что все недовольны.
не заменишь поведение.
Запрос, Линк который нормальный, зато испоняется "при необходимости",
т.е. при запросе к каждой строке обьекта он делает запрос к базе данных,
и чтобы переплюнуть это надо сильно извратиться.
Здравствуйте, andrex, Вы писали:
A>Здравствуйте, VladD2, Вы писали:
A>В тему, по поводу качества генерируемых запросов Outsmarted by LINQ-to-SQL
Linq — пока неизвестно что по качеству системы, а именно:
версиями в обьектах не управляет.
генерит запросы плохо. так что все недовольны.
не заменишь поведение.
Запрос, Линк который нормальный, зато испоняется "при необходимости",
т.е. при запросе к каждой строке обьекта он делает запрос к базе данных,
и чтобы переплюнуть это надо сильно извратиться.
Здравствуйте, vgrigor, Вы писали:
V>А Linq — пока неизвестно что, а именно: V>версиями в обьектах не управляет.
А T-SQL управляет?
V>генерит запросы плохо. так что все недовольны.
Нормально генерит. Для неочень сложной базы вообще отлично генерит.
V>Запрос, Линк который нормальный, зато испоняется "при необходимости", V>т.е. при запросе к каждой строке обьекта он делает запрос к базе данных, V>и чтобы переплюнуть это надо сильно извратиться.
Неправда. Один запрос получет список объектов.
V>В общем недостаток на недостатке.
А может вы просто не умеете его использовать?
А что делать тем кто не знает в совершенстве SQL?
Re[8]: К вопросу о LINQ to SQL и O/R Mapper-ах
От:
Аноним
Дата:
31.01.08 13:36
Оценка:
Здравствуйте, vgrigor, Вы писали:
V>А Linq — пока неизвестно что, а именно: V>версиями в обьектах не управляет. V>генерит запросы плохо. так что все недовольны.
пример в студию, пока что все мои запросы вполне нормальные V>не заменишь поведение.
поведение чего?
V>Запрос, Линк который нормальный, зато испоняется "при необходимости", V>т.е. при запросе к каждой строке обьекта он делает запрос к базе данных,
на TSQL тоже можно вызывать подзапросы из курсоров, разве это говорит плохо о языке?
V>и чтобы переплюнуть это надо сильно извратиться.
да, кто-то называет это нормально программировать, а кто-то — сильно извратиться
V>В общем недостаток на недостатке.
Re[3]: К вопросу о LINQ to SQL и O/R Mapper-ах
От:
Аноним
Дата:
31.01.08 13:42
Оценка:
Здравствуйте, vgrigor, Вы писали:
V>Linq — пока неизвестно что по качеству системы, а именно: V>версиями в обьектах не управляет. V>генерит запросы плохо. так что все недовольны. V>не заменишь поведение.
V>Запрос, Линк который нормальный, зато испоняется "при необходимости", V>т.е. при запросе к каждой строке обьекта он делает запрос к базе данных, V>и чтобы переплюнуть это надо сильно извратиться.
V>В общем недостаток на недостатке.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, vgrigor, Вы писали:
V>>А Linq — пока неизвестно что, а именно: V>>версиями в обьектах не управляет. V>>генерит запросы плохо. так что все недовольны. А>пример в студию, пока что все мои запросы вполне нормальные
var query =
from b in db.GroupCountTests
group
new { b.Code, b.Catalog }
by b.Code into g
where g.Distinct().Count() > 1
select g;
дает
SELECT [t1].[Code] AS [Key]
FROM (
SELECT [t0].[Code]
FROM [dbo].[GroupCountTest] AS [t0]
GROUP BY [t0].[Code]
) AS [t1]
WHERE ((
SELECT COUNT(*)
FROM (
SELECT DISTINCT [t2].[Code], [t2].[Catalog]
FROM [dbo].[GroupCountTest] AS [t2]
WHERE (([t1].[Code] IS NULL) AND ([t2].[Code] IS NULL)) OR (([t1].[Code] IS NOT NULL) AND ([t2].[Code] IS NOT NULL) AND ([t1].[Code] = [t2].[Code]))
) AS [t3]
вместо чего-то вроде
SELECT SomeDayID, DayValue
FROM SomeDays
WHERE DayValue in
(
SELECT DayValue
FROM SomeDays
GROUP BY DayValue
HAVING COUNT(*) > 1
)
V>>не заменишь поведение. А>поведение чего?
поведение генерации запросов
например Deffered Execution при вышеуказанном запросе,
ВСЕГДА будет выполняться запросы для каждой группы, если не менять сам запрос,
никакие опции не помогут!
V>>Запрос, Линк который нормальный, зато испоняется "при необходимости", V>>т.е. при запросе к каждой строке обьекта он делает запрос к базе данных, А>на TSQL тоже можно вызывать подзапросы из курсоров, разве это говорит плохо о языке?
Нет, в примере выше, простой запрос генерит всякие ненужные отложенности,
и это плохо говорит о том что работает под названием LINQ,
а язык может и хороший, но исполнение частей — бывает в нем плохое,
и это не поправить.
V>>и чтобы переплюнуть это надо сильно извратиться. А>да, кто-то называет это нормально программировать, а кто-то — сильно извратиться
а кто-то хочет (ВЫ)назвать все что относится к LInq заведомо нормальным,
а все что к другим языкам "проблемными усложнениями для чего и вводился Linq"...
таким фразам верить нельзя, они зхвалят то что выбрали, хотя именно ругаются они хорошо.
В общем недостаток на недостатке.
Винтовку добудешь в бою!
Re: проблема: не передадите разные данные через уровень
А еще проблема-
вы никогда не передадите разные данные через уровень, в SQL serverу примеру
не меняя сервиса — т.е.
не добавля метода с другой сигнатурой и кода для обработки...
т.е. на каждый запрос будете писать кучу кода,
хотя это то от чего позволял отказаться Линк в сладких Декларациях
Винтовку добудешь в бою!
Re[10]: К вопросу о LINQ to SQL и O/R Mapper-ах
От:
Аноним
Дата:
31.01.08 14:15
Оценка:
Здравствуйте, vgrigor, Вы писали:
V> var query = V> from b in db.GroupCountTests V> group V> new { b.Code, b.Catalog } V> by b.Code into g V> where g.Distinct().Count() > 1 V> select g;
дайте, пожалуйста, описание таблицы и если не сложно опишите задачу
Re[9]: если генерация не опртимальна ,то как вы это обойдете
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, vgrigor, Вы писали:
V>>генерит запросы плохо. так что все недовольны. G>Нормально генерит. Для неочень сложной базы вообще отлично генерит.
Как вы сделали заключение что отлично?
брали кучу запросов и анализировали планы исполнения SQL?
V>>Запрос, Линк который нормальный, зато испоняется "при необходимости", V>>т.е. при запросе к каждой строке обьекта он делает запрос к базе данных, V>>и чтобы переплюнуть это надо сильно извратиться. G>Неправда. Один запрос получет список объектов.
Но без обьектов на которые ссылается по группировке.
V>>В общем недостаток на недостатке. G>А может вы просто не умеете его использовать?
я тестирую, но чтобы получить приемлемое качество мне приходится неадекватно
не то чтобы зменять,
а именно извращать запросы.
а часть проблем — если предложенный способ генерации не оптимален ,
то как вы это обойдете?
Ведь оптимизация происходит в SQL Servere,
и есть технологии для этого, и по мету выполнения,
и реально весьма эффективные
а для LINQ нет ничего,
G>А что делать тем кто не знает в совершенстве SQL?
C>>Естественно никаких причин держать все эти методы в базовом классе, кроме убеждения, что раз ООП — значит весь функционал для работы с объектом надо запихнуть в базовый класс.
_FR>Вредное, безграмотное и частое, замечу, убеждение
Предложите другой вариант, как сделать версионность данных ? Undo..
Здравствуйте, vgrigor, Вы писали:
_FR>>Вредное, безграмотное и частое, замечу, убеждение
V>Предложите другой вариант, как сделать версионность данных ? Undo..
V>которые прибиндены к UI контролам..
Можно использовать БО через DynamicProxy в котором перехватывать все изменения свойтв и запоминать их.
От БО требуется только чтобы изменяемые свойства были виртуальными и совершенно необязательно запихивать этот функционал в базовый класс.
Здравствуйте, vgrigor, Вы писали:
А>>дайте, пожалуйста, описание таблицы и если не сложно опишите задачу V>в таблице из двух полей: код и каталог V>найти записи, где для одного кода больше одного разного каталога
В чем проблема? Пишите stored prcedure и вызывайте её.
C>Можно использовать БО через DynamicProxy в котором перехватывать все изменения свойтв и запоминать их. C>От БО требуется только чтобы изменяемые свойства были виртуальными и совершенно необязательно запихивать этот функционал в базовый класс.
Я имел ввиду любую неусложненную имплементацию, которая устраняет массовое кодирование "каждый раз",
мне придется все сгенеренные свойства вручную переписывать как виртуальные?
или
БО с DynamicProxy — это что придется их генерить через Reflection.Emit ?
Здравствуйте, vgrigor, Вы писали:
V>Я имел ввиду любую неусложненную имплементацию, которая устраняет массовое кодирование "каждый раз", V>мне придется все сгенеренные свойства вручную переписывать как виртуальные?
что мешает делать сразу виртуальными, если вы их генерируете? Как раз один раз написаный interceptor для DynamicProxy решает проблемы undo для любого объекта (даже если он уже наследуется от какого-то базового класса, в котором нет нужного функционала).
V>или V>БО с DynamicProxy — это что придется их генерить через Reflection.Emit ?
Всё уже сделали за нас — вызываете конструктор DynamicProxy передаёте ему тип вашего объекта и список нужных интерсепторов (валидации, undo etc) и все.
Любая возможная реализация undo в базовом классе, всё равно будет использовать Reflection.
V>>Я имел ввиду любую неусложненную имплементацию, которая устраняет массовое кодирование "каждый раз", V>>мне придется все сгенеренные свойства вручную переписывать как виртуальные?
C>что мешает делать сразу виртуальными, если вы их генерируете? Как раз один раз написаный interceptor для DynamicProxy решает проблемы undo для любого объекта (даже если он уже наследуется от какого-то базового класса, в котором нет нужного функционала).
Их генерирует SQLMetal Linq, а не я, поэтому контроля не имею.
V>>или V>>БО с DynamicProxy — это что придется их генерить через Reflection.Emit ?
C>Всё уже сделали за нас — вызываете конструктор DynamicProxy передаёте ему тип вашего объекта и список нужных интерсепторов (валидации, undo etc) и все.
покажите на хорошую реализуацию ?
я не знал про это, но
но читал о чем -то что неприятное: http://www.theserverside.net/news/thread.tss?thread_id=23933
As far as I know, there are two ways to do this:
— Using the magical RealProxy class that monkeys with the context (whatever that means). This requires that the object that is being proxied must extend ContextBound.
— Using Reflection.Emit to generate a new class at runtime that overrides/implements the necessary methods and dispatches invocations to a generic handler. This can implement an interface or override any virtual method."
C>Любая возможная реализация undo в базовом классе, всё равно будет использовать Reflection.
но может сделали хорошую? покажите ?
а то я подозреваю, вы говорите что сделали,
а мне придется в их реализации и выправлять тормоза,
и разгребать кучу других проблем, с аппдоменами, контекстами, или кодо -генерацией,
тогда это что называется "приемлемой имплементи НЕТ", и "проблема поднимает кучу других проблем".
Здравствуйте, vgrigor, Вы писали:
C>>что мешает делать сразу виртуальными, если вы их генерируете? Как раз один раз написаный interceptor для DynamicProxy решает проблемы undo для любого объекта (даже если он уже наследуется от какого-то базового класса, в котором нет нужного функционала).
V>Их генерирует SQLMetal Linq, а не я, поэтому контроля не имею.
Тогда речь о использовании базового класса для реализации undo вообще быть не может.
Зато есть не очень сложный способ сделать свойство виртуальным даже в классе, сгенерированном SQLMetal Linq:
допустим есть сгенерированный класс:
[Table(Name="dbo.PERSONNELS")]
public partial class PERSONNEL : INotifyPropertyChanging, INotifyPropertyChanged
{
....
}
c свойством int PERSONNEL_ID.
создаём класс:
interface IPersonnel
{
int PERSONNEL_ID { get; set; }
}
public partial class PERSONNEL : IPersonnel
{
}
и свойство автоматически становится виртуальным. Интерфейсы можно генерировать по "dbml" файлу. Не совсем красиво конечно.
C>>Всё уже сделали за нас — вызываете конструктор DynamicProxy передаёте ему тип вашего объекта и список нужных интерсепторов (валидации, undo etc) и все.
V>покажите на хорошую реализуацию ? V>я не знал про это, но V>но читал о чем -то что неприятное: V>http://www.theserverside.net/news/thread.tss?thread_id=23933 V>As far as I know, there are two ways to do this: V>- Using the magical RealProxy class that monkeys with the context (whatever that means). This requires that the object that is being proxied must extend ContextBound. V>- Using Reflection.Emit to generate a new class at runtime that overrides/implements the necessary methods and dispatches invocations to a generic handler. This can implement an interface or override any virtual method."
ProxyGenerator generator = new ProxyGenerator();
return (T)generator.CreateProxy(typeof(T), new AsyncProxy(), target);
где Т — тип нашего объекта.
Насколько я знаю, этот прокси используется в NHibernate и Spring.NET.
C>>Любая возможная реализация undo в базовом классе, всё равно будет использовать Reflection. V>но может сделали хорошую? покажите ?
V>а то я подозреваю, вы говорите что сделали, V>а мне придется в их реализации и выправлять тормоза, V>и разгребать кучу других проблем, с аппдоменами, контекстами, или кодо -генерацией,
О проблемах, кроме необходимости иметь виртуальные свойства/методы не знаю. Оверхед по скорости минимально возможный — один раз генерируется класс наследник в котором перехватываются все вызовы и дальше Reflection не используется. В любом случае на фоне тормозов дата байндинга ничего заметно не будет.
TK>Если вам кажется, что слоев слишком много — скорее всего, вы просто используете инструмент не по назначению.
не слоев и даже не сериализации/десериализации а мапперов. Ну согласись ведь бред дважды "перемапливать" объект только для того чтобы получить его state на стороне сервис.
Здравствуйте, vgrigor, Вы писали:
V> var query = V> from b in db.GroupCountTests V> group V> new { b.Code, b.Catalog } V> by b.Code into g V> where g.Distinct().Count() > 1 V> select g;
V>дает V>SELECT [t1].[Code] AS [Key] V>FROM ( V> SELECT [t0].[Code] V> FROM [dbo].[GroupCountTest] AS [t0] V> GROUP BY [t0].[Code] V> ) AS [t1] V>WHERE (( V> SELECT COUNT(*) V> FROM ( V> SELECT DISTINCT [t2].[Code], [t2].[Catalog] V> FROM [dbo].[GroupCountTest] AS [t2] V> WHERE (([t1].[Code] IS NULL) AND ([t2].[Code] IS NULL)) OR (([t1].[Code] IS NOT NULL) AND ([t2].[Code] IS NOT NULL) AND ([t1].[Code] = [t2].[Code])) V> ) AS [t3]
V>вместо чего-то вроде
V>SELECT SomeDayID, DayValue V>FROM SomeDays V>WHERE DayValue in V>( V>SELECT DayValue V>FROM SomeDays V>GROUP BY DayValue V>HAVING COUNT(*) > 1 V>)
А ты уверен в том, что второй запрос для сиквела оптимальнее?
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
V> var query =
V> from b in db.GroupCountTests
V> group
V> new { b.Code, b.Catalog }
V> by b.Code into g
V> where g.Distinct().Count() > 1
V> select g;
V>дает
V>SELECT [t1].[Code] AS [Key]
V>FROM (
V> SELECT [t0].[Code]
V> FROM [dbo].[GroupCountTest] AS [t0]
V> GROUP BY [t0].[Code]
V> ) AS [t1]
V>WHERE ((
V> SELECT COUNT(*)
V> FROM (
V> SELECT DISTINCT [t2].[Code], [t2].[Catalog]
V> FROM [dbo].[GroupCountTest] AS [t2]
V> WHERE (([t1].[Code] IS NULL) AND ([t2].[Code] IS NULL)) OR (([t1].[Code] IS NOT NULL) AND ([t2].[Code] IS NOT NULL) AND ([t1].[Code] = [t2].[Code]))
V> ) AS [t3]
угу, а после этого ещё N запросов типа
exec sp_executesql N'SELECT [t0].[Code], [t0].[Catalog]
FROM [dbo].[GroupCountTests] AS [t0]
WHERE @x1 = [t0].[Code]',N'@x1 nvarchar(3)',@x1=N'ХХХХ'
Здесь используется Left Semi Join, к сожалению в Linq такого нет, поэтому нужно использовать join, что вполне приемлеммо, хотя конечно эффективность процентов на 10-20 теряется. Хотя если учесть, что ваша исходная таблица не оптимизирована, то никто разницы даже и не заметит.
var q = from b2 in db.GroupCountTests
join b1 in
(from b in db.GroupCountTests
group b by b.Code into g
where g.Count() > 1
select g)
on b2.Code equals b1.Key
select b2;
SQL соответсвующий ему
SELECT [t0].[Code], [t0].[Catalog]
FROM [dbo].[GroupCountTests] AS [t0]
INNER JOIN (
SELECT COUNT(*) AS [value], [t1].[Code]
FROM [dbo].[GroupCountTests] AS [t1]
GROUP BY [t1].[Code]
) AS [t2] ON [t0].[Code] = [t2].[Code]
WHERE [t2].[value] > 1
все нужные данные получились за один запрос, что и требовалось получить
_FR>Вредное, безграмотное и частое, замечу, убеждение
Равно как и попытки любыми способами необосованно избавиться от этого общего предка, выставляя "фитчу" отсутствия необходимости наследования от базового предка как супер "изыск архитектуры" и как "истину в последней инстанции".
В каждом отдельно взятом проекте лучшим может оказаться тот или иной подход в зависимости от требований (в том числе по поддержке) и ситуации. А многие почему то за "модой" гонятся.
Выделяете базового предка — да, возможно, получаете более сильную связность и меньшую переносимость.
Отказываетесь от базового предка — получаете обвязку в виде AOP, кучи паттернов в которых, возможно, для конкретного проекта даже нет необходимости и менее приятный с точки зрения семантики написания код.
Как тут не вспомнить про "Hello word" иронично написанный с использованием десятка паттернов
Вообщем палка о двух концах, и в каждом конкретном случае удобно то или иное.
Re[11]: К вопросу о LINQ to SQL и O/R Mapper-ах
От:
Аноним
Дата:
31.01.08 18:05
Оценка:
Здравствуйте, AndrewVK, Вы писали:
AVK>А ты уверен в том, что второй запрос для сиквела оптимальнее?
Основная проблема там не в оптимальности запроса, а в том, что после первого запроса Linq вызовет ещё N запросов сродни select * from table where code='xxx' для каждой возвращаемой записи
Здравствуйте, <Аноним>, Вы писали:
А>Основная проблема там не в оптимальности запроса, а в том, что после первого запроса Linq вызовет ещё N запросов сродни select * from table where code='xxx' для каждой возвращаемой записи
А это уж как ты запрос напишешь. Если будешь писать в реляционном стиле — никаких дополнительных запросов не будет. Ну а если попытаешься работать как с ORMами — ну так ССЗБ.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, снежок, Вы писали:
_FR>>Вредное, безграмотное и частое, замечу, убеждение
С>Равно как и попытки любыми способами необосованно избавиться от этого общего предка, выставляя "фитчу" отсутствия необходимости наследования от базового предка как супер "изыск архитектуры" и как "истину в последней инстанции".
После того как ты рассказал нам про биндинг и undo/redo в базовом классе БО, дальше об архитектуре можно уже не разговаривать.
С>В каждом отдельно взятом проекте лучшим может оказаться тот или иной подход в зависимости от требований (в том числе по поддержке) и ситуации. А многие почему то за "модой" гонятся.
Какими бы требования не были, программирование в стиле "мухив котлетах" ни к чему хорошему не приведет.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, vgrigor, Вы писали:
G>>В чем проблема? Пишите stored prcedure и вызывайте её.
V>проблемы нет. V>Просто этот случай типичный, V>т.е. на многие типичные случаи вы предлагаете писать usp? V>Зачем же тогда Linq ?
V>Часть премуществ по устранению излишнего кодирования пропадает далеко.
Только, используя Linq2SQL, вы будете вызывать SP как метод класса, возвращающий типизированную коллекцию.
AVK>А ты уверен в том, что второй запрос для сиквела оптимальнее?
Честно говоря, нет,
т.к. не проверял в планах выполнения и отладчике.
Опять же можно сказать что имплементация Линк как правило вполне эффективная,
но, хотелось бы иметь возможность чтобы генерил как хотелось а не как оно сделало,
хотя все же это недостаток небольшой,
хотя и недостаток,
но в серьезном программировании нельзя пользоваться средством обращения к базе
SQL которого вы не контролируете, т.к. нарветесь не сейчас а в будущем.
Запретят и правильно.
Хотя конечно можно пистаь напрямую SQL, но это уже не вполне Линк,
хотя приемлемо.
AVK>А это уж как ты запрос напишешь. Если будешь писать в реляционном стиле — никаких дополнительных запросов не будет. Ну а если попытаешься работать как с ORMами — ну так ССЗБ.
Нет, при серьезной работе с базой — никаких "ну так", а именно чтобы "примерно самый эффективный SQL и использование ресурсов сети",
но именно тот запрос нельзя сделать неленивым — однократно вызываемым...
хотя обмануть и можно, но это это все же недостаток,
и может быть не всегда получится, тогда снова сюда же — надо все проверять каждый раз, и писать прямой SQL в Линке.
AVK>А выставить у свойства в дизайнере inheritance modifier = virtual религия не позволяет?
религия мне позволяет признавать то на что она направлена — лучшие решения.
вопрос в том чтобы потом на работе на меня не показывали со словами "вот идиот, че предложил, а мы расхлебываем.."
и пока есть такие места.
"virtual" хорошая вещь, которая дает некоторые возможности — "придется писать свой кодогенератор, подменяет сгенеренное SQLMetal,
и дописывать DataContext чтобы правильно унаследованное принимал, и.т.д..."
в общем неплохо так писать генераторов... хотя можно.
Здравствуйте, vgrigor, Вы писали:
V>"virtual" хорошая вещь, которая дает некоторые возможности — "придется писать свой кодогенератор, подменяет сгенеренное SQLMetal, V>и дописывать DataContext чтобы правильно унаследованное принимал, и.т.д..."
V>в общем неплохо так писать генераторов... хотя можно.
Если ничего не помогает, прочтите наконец документацию. В твоем случае по дизайнеру Linq2SQL classes.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, снежок, Вы писали:
_FR>>>Вредное, безграмотное и частое, замечу, убеждение
С>>Равно как и попытки любыми способами необосованно избавиться от этого общего предка, выставляя "фитчу" отсутствия необходимости наследования от базового предка как супер "изыск архитектуры" и как "истину в последней инстанции".
AVK>После того как ты рассказал нам про биндинг и undo/redo в базовом классе БО, дальше об архитектуре можно уже не разговаривать.
Многие западные программеры бьются с мелкософтом, за то чтобы они сделали EF обьекты без наследования,
а мелкософт говорит что пока всякие сервисы обьектов не получается сделать орошо без наследования,
но будут стараться.
т.е. совпадают с товарищем который их процитировал просто видимо.
В то же время никто не возражает что WinForm всьма оптимальны в иерархическом виде..
С>>В каждом отдельно взятом проекте лучшим может оказаться тот или иной подход в зависимости от требований (в том числе по поддержке) и ситуации. А многие почему то за "модой" гонятся.
AVK>Какими бы требования не были, программирование в стиле "мухив котлетах" ни к чему хорошему не приведет.
Как видите, микрософт очень часто предпочитает наследование.
Скорее всего вы политически хотите таким выражением, именно свое предпочтение продвинуть а остальные "для порядка" запретить, чтобы однообразно,
как в одной компании.
у нас так менеджеры манипулируют тоже, хитрые...
AVK>Если ничего не помогает, прочтите наконец документацию. В твоем случае по дизайнеру Linq2SQL classes.
Это конечно разумно..
сейчас почти только и делаю что читаю разное. А то доки много, описания классов хорошие по размеру, но проблем пока не рашает...
А если вы знаете — не дали бы сссылку на нужное место в документации,
которое укажет всем как решить непроходимую проблему расширения Linq? тем более если дизайнер можно расщирить, как XSD шный кодогенератор,то вообще круто.
AVK>>А это уж как ты запрос напишешь. Если будешь писать в реляционном стиле — никаких дополнительных запросов не будет. Ну а если попытаешься работать как с ORMами — ну так ССЗБ.
Здравствуйте, vgrigor, Вы писали:
V>А еще проблема- V>вы никогда не передадите разные данные через уровень, в SQL serverу примеру V>не меняя сервиса — т.е. V>не добавля метода с другой сигнатурой и кода для обработки...
V>т.е. на каждый запрос будете писать кучу кода, V>хотя это то от чего позволял отказаться Линк в сладких Декларациях
LINQ отношения к вышесказанному никакого вообще не имеет. Читай исходную статью Влада -- ты путаешь LINQ и ADO .NET Entity Framework.
А>Здесь используется Left Semi Join, к сожалению в Linq такого нет, поэтому нужно использовать join, что вполне приемлеммо, хотя конечно эффективность процентов на 10-20 теряется. Хотя если учесть, что ваша исходная таблица не оптимизирована, то никто разницы даже и не заметит.
А>
А>var q = from b2 in db.GroupCountTests
А> join b1 in
А> (from b in db.GroupCountTests
А> group b by b.Code into g
А> where g.Count() > 1
А> select g)
А> on b2.Code equals b1.Key
А> select b2;
А>
А>SQL соответсвующий ему А>
А>SELECT [t0].[Code], [t0].[Catalog]
А>FROM [dbo].[GroupCountTests] AS [t0]
А>INNER JOIN (
А> SELECT COUNT(*) AS [value], [t1].[Code]
А> FROM [dbo].[GroupCountTests] AS [t1]
А> GROUP BY [t1].[Code]
А> ) AS [t2] ON [t0].[Code] = [t2].[Code]
А>WHERE [t2].[value] > 1
А>
А>все нужные данные получились за один запрос, что и требовалось получить
+1
....
Ну что же, хороший подход, интересный пост.
Я не говорил что нельзя проблему решить, и не одним способом, — но переписывая запрос на более сложный.
и то что нельзя простой и адекватный исходный Linq запрос сделать не разбиваемым на SQL запросы
при текущей реализации.
Ваш Linq запрос замечателен, но нельзя не признать что сложен для поставленной задачи ?
___________
Впрочем я не говорю что Linq плох, наоборот весьма хорош,
но есть пока серьезные недостатки, такие что не допускают его ПРЯМОГО применения в серьезной программе,
его надо несколько (но существенно) дополнить, чтоы это все обойти.
Дописать надо —
написав свой генератор вместо SQLMetal (люди уже написали),
написать расширения LINQ, для оптимизации генеримого в выражениях,
которые хороши, но несколько непросты, но все делается .
Тут даже можно сделать и исходный запрос неразбиваемым.
что хорошо, это то что есть возможность напрямую писать SQL, который как в этом случае заметно проще Linq варианта.
Винтовку добудешь в бою!
Re[3]: проблема: не передадите разные данные через уровень
DG>LINQ отношения к вышесказанному никакого вообще не имеет. Читай исходную статью Влада -- ты путаешь LINQ и ADO .NET Entity Framework.
У меня статья по ссылке к сожалению не находится... может сервер их сегодня отдыхает..
Но все же сам Linq напрямую проблему не решает...
И если вы в будущем захотите перейти на многуровневую модель, все запросы придется менять на запросы Entity Framework ?
хотя многие эту проблему пытаются решить, т.к. Linq расширяем,
как изначально сторонник Linq, я тоже,
но нельзя и не признавать теперешних недостатков Linq?
надо ведь видеть проблемы реальных серьезных приложений в c Linq,
а не то как красиво выглядит Linq в декларациях.
Винтовку добудешь в бою!
Re[4]: проблема: не передадите разные данные через уровень
Здравствуйте, vgrigor, Вы писали:
V>Но все же сам Linq напрямую проблему не решает... V>И если вы в будущем захотите перейти на многуровневую модель, все запросы придется менять на запросы Entity Framework ?
Какую проблему? Передачу данных между layers? И в чем она конкретно заключается?
V>хотя многие эту проблему пытаются решить, т.к. Linq расширяем, V>как изначально сторонник Linq, я тоже, V>но нельзя и не признавать теперешних недостатков Linq?
А у кого нет недостатков? Другое дело, LINQ тоже нужно правильно готовить.
V>надо ведь видеть проблемы реальных серьезных приложений в c Linq, V>а не то как красиво выглядит Linq в декларациях.
Проблемы в "реальных" приложениях обусловленны объективной сложность этих самых реальных приложений и мира в котором мы живем