Re[10]: Некоторые мысли о LINQ
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.03.09 19:13
Оценка:
Здравствуйте, Jakobz, Вы писали:

J>Хорошая логика. Типа "нет человека — нет проблем" Не будет датаконтекстов — не будет и удобств, которые они дают.



J>Я имел ввиду identity объектов:

J>1. select * from Persons where person_id = 1
J>2. юзер выбирает список персон
J>3. select * from Persons
J>Первая персона у нас теперь в виде объектов в двух экземплярах — из первого и второго запроса.
J>Не запутаешься с этим? Ничего что "==" для объектов нельзя будет использовать? Или будет собственный велик?
Отличный пример. Он показывает порочность использования "маппинга", как преобразования, меняющего идентичность.
Обрати внимание, что если ты не будешь выполнять маппинг, подобной проблемы просто не возникнет.
Попробуй выполнить эти два запроса в рамках SQL консоли. У тебя просто не будет ничего такого, что можно было бы сравнить "друг с другом".
Вот другой пример:
select Name from person where id = 1
update Person set Name = "Vasya" where id=1

Всё, у тебя нет никакого способа получить для id=1 не-васю, каким бы способом ты его не поселектил. Потому, что не существует никакой отдельной копии строки с id=1, которую можно было бы поменять. Ты всегда модифицируешь оригинал.
А для разведения конфликтов изменений, произведенных в разных соединениях, работает могучая транзакционность.

J>Откуда их станет меньше? Почему я не могу успешно управлять ими в LINQ to SQL?

Из-за отсутсивия "копий", которые могут быть изменены независимо.

J>Проблема в том, что эта проблема в очередной раз будет решаться руками или велосипедами.

Этой проблемы не будет вообще.
J>Не, я вообще не привык к комфорту. На проекте, на котором я уже пару лет занят — вообще датасеты и все руками. Но у нас специфика такая, что в основном с базой только на чтение работа идет.
Датасеты — это ухудшенный вариант OR-мапперов.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[14]: Некоторые мысли о LINQ
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.03.09 19:13
Оценка: +6
Здравствуйте, Jakobz, Вы писали:
J>Ок. Если нужно залить несколько разных объектов кто будет заниматься сортировкой операций insert/update/delete?
Не нужно думать об этом в стиле "залить несколько разных объектов" и всё будет замечательно.

J>Я в другой ветке писал про это. Что если у нас два одинаковых объекты и мы поменяем только один?

Это прямое следствие того, что вы сначала создали себе два одинаковых объекта.

J>Pessimistic — да, обеспечивает. На уровне одного соединения/транзакции. Как средствами СУБД обрабатывать классическую ситуацию: чувак открыл форму редактирования, ушел домой, а кому-то нужно что-то в ней этой же форме поправить?

Вот те объекты, которые работают "через форму редактирования" — они нормально совместимы и с датасетами, и с ормапперами, и прочими идентити тракингами. Ключевая особенность — прямой контроль не над действием, а над результатом.

Представь себе другую ситуацию — ты открыл форму оплаты за телефон пластиковой картой. Она, собственно, не собирается "редактировать" никакой объект — она описывает действие, а не результат. Действием будет перевод денег со счёта на счёт; в его результате изменится баланс. Если попробовать "редактировать" баланс счёта в той идеологии, которую предполагаешь ты, то возникает масса угловых сценариев — вроде того, как два человека вручную вычитают сумму транзакции из баланса, и происходит потеря изменений.
Ну, точнее, с учетом optmistic locking, тот, кто опоздал, получит "конфликт обновления" и будет вынужден вычитать сумму транзакции заново, до тех пор, пока не окажется достаточно шустрым для победы в гонке коммитов.
Но если трактовать транзакцию именно как действие, то совершенно неважно, ушел ли ты домой или нет — это никому не мешает производить другие транзакции с тем же счётом.

Фишка в том, что датасеты и прочие механизмы прочитать-изменить-записать посвящены именно проблеме прямого управления данными.
Для управления в стиле действий, которые как раз хорошо ложатся на update, insert, delete, приходится изобретать многочисленные приседания.
Особенно забавно то, что для простых транзакций, с изменением одиночных объектов, identity tracking и change tracking не очень-то нужны — ты и так знаешь, какой именно объект ты пытаешься изменить. Эти механизмы становятся критически нужны в тех случаях, когда ты согласованно изменяешь набор "объектов", причем такой набор, который заранее плохо определен.

Так вот юмор как раз в том, что это именно та ситуация, для которой и создавался SQL. И "прокладка", которая сначала хорошо помогала реализовывать чужеродный для СУБД сценарий "сохранения объекта", теперь начинает мешать — и к ней нужна еще одна прокладка в виде кэша, а к нему точные change трекеры и прочие костыли.

Поэтому идеальная модель работы с данными должна давать оба способа — как "сохранение", которое пригодно для простых случаев прямого ввода, так и "действие", которое будет точно описывать трансформации с данными.

J>Update() в LINQ тоже с блокировками выполняется и в одной транзакции. Странно, зачем там optimistic concurency?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: Некоторые мысли о LINQ
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 25.03.09 19:15
Оценка: +1
Здравствуйте, Jakobz, Вы писали:

J>А что ты понимаешь под базвордом "statefull-архитектура"?


Это не баззворд. Stateless архитектура, когда все объекты живут исключительно в течение вызова метода, не требует никаких танцев с конкарренси за пределами БД.
... << RSDN@Home 1.2.0 alpha 4 rev. 1138 on Windows Vista 6.1.7000.0>>
AVK Blog
Re[13]: Некоторые мысли о LINQ
От: Jakobz Россия  
Дата: 25.03.09 19:17
Оценка:
Здравствуйте, IT, Вы писали:

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


J>>А что ты понимаешь под базвордом "statefull-архитектура"?


IT>Архитектуры построенные на хранении состояния.


J>>Почему дизайн с person1 == person2 — не нормален?


IT>Потому что в stateless системе я представить не могу где это может понадобиться. А если понадобится, то написать person1.ID == person2.ID я не переломлюсь. Так даже понятней будет.


Ну вот, здравствуйте! На RSDN все флеймы заканчиваются Хаскелем?
Напомнаю — мы говорим о технологии LINQ для императивного C#, призванного упростить работу с большим куском стейта — СУБД
Re[14]: Некоторые мысли о LINQ
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 25.03.09 19:21
Оценка:
Здравствуйте, Jakobz, Вы писали:

J>Ну вот, здравствуйте! На RSDN все флеймы заканчиваются Хаскелем?


При чем тут Хаскел?

J>Напомнаю — мы говорим о технологии LINQ для императивного C#


1) C# не только императивный
2) LINQ уж точно не императивная штука, а очень даже функциональная.
... << RSDN@Home 1.2.0 alpha 4 rev. 1138 on Windows Vista 6.1.7000.0>>
AVK Blog
Re[14]: Некоторые мысли о LINQ
От: IT Россия linq2db.com
Дата: 25.03.09 19:31
Оценка:
Здравствуйте, Jakobz, Вы писали:

J>Ну вот, здравствуйте! На RSDN все флеймы заканчиваются Хаскелем?


Шутку юмора не понял, ну да ладно.

J>Напомнаю — мы говорим о технологии LINQ для императивного C#, призванного упростить работу с большим куском стейта — СУБД


Это не просто кусок стейта, это и есть весь и только стейт. Ты же хочешь этот стейт хранить не только в БД, но и размазать его по серверам и клиентам. А потом долго и упорно его трекать.
Если нам не помогут, то мы тоже никого не пощадим.
Re[11]: Некоторые мысли о LINQ
От: Jakobz Россия  
Дата: 25.03.09 19:57
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

J>>Откуда их станет меньше? Почему я не могу успешно управлять ими в LINQ to SQL?

S>Из-за отсутсивия "копий", которые могут быть изменены независимо.

Тут одна вешь, которую ты упускаешь, уходя всё дальше от темы: в большинстве случаев "отсоединение" сущностей просто необходимо.

Да, если у тебя есть детерменированная операция, db = f(db) — ты можешь ее записать в одной транзакции, и это будет правильно. Тебе ничего не нужно "отсоединять", мэппить в объекты, select-ить из базы чтобы сделать update и заниматься прочей чепухой.

Но, если у нас есть пользователь или другой медленный, недетерменированный, ввод-вывод, ты никак не уйдешь от отсоединенной модели с optimistic concurrency. Тебе нужно будет отсоединить данные от базы, хотя бы чтобы положить их в input на веб-форме. Те данные, которые на форме, уже будут копией информации из базы, без какой-либо гарантии актуальности.

Мы приходим к тому, что нужно эти данные как-то передать на эту форму и работать с ними из кода. Мы сейчас говорим о ООП-языке C#, где для хранения данных принято использовать объекты. Поэтому логично как посредника для передачи данных из БД использовать именно эти самые объекты. Причем и при получении из базы и при засовывании их назад. Можно применять и другие временные хранилища, например датасеты. Но, как показывает практика, в C# это неудобно. Хотя я не исключаю, что может быть и хорошая, удобная реализация такой концепции. У обычных объектов есть свои минусы, да, но с ними как правило удобнее.

И вот — с объектами есть проблемы, см. object-relation impedance mismatch. Но делать-то, в общем-то, с этим особо нечего. Варианты "перейти на другой язык" или "написать свои мегадатасеты" не будем рассматривать здесь, пожалуйста.

А потом полученые от того же пользователя данные нужно положить назад в базу. Логично юзать тот же формат данных, в каком эти данные были получены. И при засовывании нужно проверить — а не обновил ли кто эти данные до нас? Можно этого и не делать, но это не по-феншую, а зачастую этого требуют явно.

И вот именно эти задачи решает Linq to sql. Замечу — это не какой-то волшебный инструмент, который принес реляционную алгебру в ООП (как мне показалось именно этого хотел от него VladD2). Отнюдь, это не так. Linq to sql — это инструмент для решения описаных выше задач. И нужно учесть, что это — инструмент для работы именно с отсоединенной моделью.

Еще в Linq to sql есть DataContext, с которого начался спор. Эта штука частично решает/упрощает некоторые задачи и, в общем, могла бы "быть попроще". Но, на мой взгляд, сильного оверхеда она не приносит, а удобства у нее есть. Например, она сглаживает проблему с identity. И сама запоминает какие объекты менялись, чтобы потом нам не вспоминать что апдейтить. Я не вижу в этих удобствах ничего плохого. В любом случае от этих удобств никто не запрещает отказываться — на то ReadOnly и прочии фичи.

Почему я тут так подробно это расписываю? Потому что разговор ушел куда-то в полный астрал. Мы уже, вон, до Хаскеля дошли. Непонятно где Немерле только отстало
Re[12]: Некоторые мысли о LINQ
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 25.03.09 20:17
Оценка: +1
Здравствуйте, Jakobz, Вы писали:

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


J>>>Откуда их станет меньше? Почему я не могу успешно управлять ими в LINQ to SQL?

S>>Из-за отсутсивия "копий", которые могут быть изменены независимо.

J>Тут одна вешь, которую ты упускаешь, уходя всё дальше от темы: в большинстве случаев "отсоединение" сущностей просто необходимо.

Там где необходимо "отсоединение" там контексты Linq2SQL, EF, сессии NHibernate тоже не справляются и надо "отсоедиенный" набор данных поддерживать руками.

J>Но, если у нас есть пользователь или другой медленный, недетерменированный, ввод-вывод, ты никак не уйдешь от отсоединенной модели с optimistic concurrency. Тебе нужно будет отсоединить данные от базы, хотя бы чтобы положить их в input на веб-форме. Те данные, которые на форме, уже будут копией информации из базы, без какой-либо гарантии актуальности.

В одном запросе мы считали из базы объекты, сгенерировали по ним форму. В следующем запросе получили данные с формы и выполнили запрос на изменение данных в БД.
Зачем здесь identity\change tracking контекста? Он хоть каким-то боком помогает?

J>И вот — с объектами есть проблемы, см. object-relation impedance mismatch. Но делать-то, в общем-то, с этим особо нечего. Варианты "перейти на другой язык" или "написать свои мегадатасеты" не будем рассматривать здесь, пожалуйста.

А это все и не поможет. Чем дальше разработчики пытаются уйти от работы с данными, тем больше проблем получается.
Большенство паттернов применяемых для работы с данными — это костыли.

J>А потом полученые от того же пользователя данные нужно положить назад в базу. Логично юзать тот же формат данных, в каком эти данные были получены. И при засовывании нужно проверить — а не обновил ли кто эти данные до нас? Можно этого и не делать, но это не по-феншую, а зачастую этого требуют явно.

И снова вопрос, чем нам identity\change tracking помогает в этом?

J>И вот именно эти задачи решает Linq to sql. Замечу — это не какой-то волшебный инструмент, который принес реляционную алгебру в ООП (как мне показалось именно этого хотел от него VladD2). Отнюдь, это не так. Linq to sql — это инструмент для решения описаных выше задач. И нужно учесть, что это — инструмент для работы именно с отсоединенной моделью.

Да ну? Напишите мне Linq2SQL запрос, который к БД не обращается.

J>Еще в Linq to sql есть DataContext, с которого начался спор. Эта штука частично решает/упрощает некоторые задачи и, в общем, могла бы "быть попроще". Но, на мой взгляд, сильного оверхеда она не приносит, а удобства у нее есть. Например, она сглаживает проблему с identity. И сама запоминает какие объекты менялись, чтобы потом нам не вспоминать что апдейтить. Я не вижу в этих удобствах ничего плохого. В любом случае от этих удобств никто не запрещает отказываться — на то ReadOnly и прочии фичи.

проблем с identity не будет если отказаться от идеи получать объекты, потом их изменять и записывать в том же контексте.
Re[15]: Некоторые мысли о LINQ
От: Jakobz Россия  
Дата: 25.03.09 20:21
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Фишка в том, что датасеты и прочие механизмы прочитать-изменить-записать посвящены именно проблеме прямого управления данными.

S>Для управления в стиле действий, которые как раз хорошо ложатся на update, insert, delete, приходится изобретать многочисленные приседания.
S>Особенно забавно то, что для простых транзакций, с изменением одиночных объектов, identity tracking и change tracking не очень-то нужны — ты и так знаешь, какой именно объект ты пытаешься изменить. Эти механизмы становятся критически нужны в тех случаях, когда ты согласованно изменяешь набор "объектов", причем такой набор, который заранее плохо определен.

S>Так вот юмор как раз в том, что это именно та ситуация, для которой и создавался SQL. И "прокладка", которая сначала хорошо помогала реализовывать чужеродный для СУБД сценарий "сохранения объекта", теперь начинает мешать — и к ней нужна еще одна прокладка в виде кэша, а к нему точные change трекеры и прочие костыли.


S>Поэтому идеальная модель работы с данными должна давать оба способа — как "сохранение", которое пригодно для простых случаев прямого ввода, так и "действие", которое будет точно описывать трансформации с данными.


Да понимаю я это всё, понимаю.
Просто ты упускаешь следующие моменты:
— сложные сценарии обработки данных сложно писать на SQL. Если бы это было не так — писали бы всю логику на хранимках и не парились бы. И вот, чтобы обработать эти данные в C#, можно их таки вынуть, преобразовать в формат, понятный C#, обработать их, преобразовать обратно и положить. Да, не обязательно это делать. Можно работать напрямую на SQL, можно реализовывать какой-то реляционный DSL прямо в языке, и т.п. Но вот Linq to Sql, про который речь, это все-таки подход с преобразованием в объекты. Т.е. это ORM, со всеми его минусами и плюсами.
— усложним твой пример с банкоматом. Пусть он показывает текуший счет. И мы считаем, что человек принимает решение о переводе денег, основываясь на текущем счете: из 20штук занять другу 5 — одно, из 6 занять 5 — другое, самому кушать нужно. И мы тут же приходим обратно к обработке оптимистической конкуренции в той или иной форме. Не смотря на то, что "перевод денег" остается таким же атомарным действием. Пример можно сколь угодно усложнять. Главное тут то, что что-то из внешней среды принимает решение за конечное время, основываясь на потенциально устаревшей информации. Т.е. дело не в "концепции сохранения", проблема эта будет существовать при абсолютно любых условиях.
Re[12]: Некоторые мысли о LINQ
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.03.09 20:44
Оценка: +1
Здравствуйте, Jakobz, Вы писали:

J>Тут одна вешь, которую ты упускаешь, уходя всё дальше от темы: в большинстве случаев "отсоединение" сущностей просто необходимо.


J>Да, если у тебя есть детерменированная операция, db = f(db) — ты можешь ее записать в одной транзакции, и это будет правильно. Тебе ничего не нужно "отсоединять", мэппить в объекты, select-ить из базы чтобы сделать update и заниматься прочей чепухой.


J>Но, если у нас есть пользователь или другой медленный, недетерменированный, ввод-вывод, ты никак не уйдешь от отсоединенной модели с optimistic concurrency. Тебе нужно будет отсоединить данные от базы, хотя бы чтобы положить их в input на веб-форме. Те данные, которые на форме, уже будут копией информации из базы, без какой-либо гарантии актуальности.

Воот. Я-то как раз ничего не упускаю. Сама по себе идея "положить данные в input" подразумевает, что ты управляешь конечным состоянием, а не действием.
Понимаешь? Действия — stateless.
А ты упускаешь то, что этих случаев — совсем не "большинство".
Возьми, к примеру, кассовый терминал. Там инпуты совершенно не содержат никакие "данные", которые нужно откуда-то отсоединять.
С другой стороны в ту же базу смотрит сотня разнообразных отчетов. И там объектам делать нечего — ты устанешь конструировать классы для этих объектов. Анонимные типы как-то спасают, ровно до тех пор, пока не появляются "пользовательские" отчеты, и как раз тут на передний план выбегают датасеты со своей хреновой типизацией.

Понятно, что это — крайний случай, база с "одной большой таблицей".
Но и во многих других интересных случаях то, о чем ты говоришь — это редактирование справочников. Пусть юз-кейзов про них будет 95, а юз-кейзов с "интересным" наполнением — всего пять.
Интересными я здесь называю всякие штуки типа "найти подходящие объекты, и нужным способом их согласованно изменить". Классический пример — резервирование товара на складах, с минимизацией холостого пробега машины доставки. Или там выбор подходящей комнаты для митинга и резервирование оборудования, связанного с ней. Или еще что-нибудь такое, где тебе сильно хочется применить change tracking. Во всех этих случаях лучше ничего ниоткуда не отсоединять — потому что обратное присоедининить трудно.

J>И вот — с объектами есть проблемы, см. object-relation impedance mismatch.

Этот мисмэтч происходит из-за того, что "не ту страну назвали гондурасом". Точнее, кто-то с какого-то перепугу решил сопоставить объекты отдельным записям в таблицах.
И вот тут-то всё и началось. Дело в том, что строки таблиц не ведут себя как объекты. Как объекты себя ведут реляции.
Вот как только ты начинаешь об этом задумываться, весь мисмэтч исчезает на глазах.
Вот у тебя есть объект Customers. Не Сustomer, а Customers.
Есть операция Where, которая может вернуть тебе объект CustomersWithNameVasya, который того же типа, что и Customers.
А есть операция Select, которая может вернуть тебе CustomersFirstName, который того же типа, что и Strings.
И так далее.

J>Но делать-то, в общем-то, с этим особо нечего.

Да-да-да. До изобретения Linq именно так и считалось. Что ничего интересного тут сделать нельзя, поэтому давайте ваши датасеты, и поехали.
Однако вопросы с select, where, order by, group by в общем-то решили положительно.

Но вот тут у парней появился выбор:
1. Трактовать результаты Linq-выражений в стиле сиквела: неизменяемыми "слепками", снятыми с настоящих данных.
2. Разрешить программистам думать, что результат запроса — это не один объект, а набор полноценных объектов с изменямым состоянием.
Первый путь потребовал бы ввести поддержку модификаций в том же SQL стиле (чего очень хочется мне, Владу, и еще нескольким отморозкам-любителям).
Второй путь потребовал бы ввести поддержку change tracking, identity map и прочей ерунды.
Выбрали второй. Но не нужно думать, что он такой единственный.

J>И вот именно эти задачи решает Linq to sql. Замечу — это не какой-то волшебный инструмент, который принес реляционную алгебру в ООП (как мне показалось именно этого хотел от него VladD2). Отнюдь, это не так. Linq to sql — это инструмент для решения описаных выше задач. И нужно учесть, что это — инструмент для работы именно с отсоединенной моделью.

Мы прекрасно понимаем, что такое Linq, как устроен Linq2Sql, и почему он так устроен. Мы просто с этим не согласны.
Я тебя понимаю — я еще в долинковские времена наприседался с ORM, и самописанными в том числе, и все их прелести прекрасно осознаю. Linq — это шаг в правильную сторону, вот только надо бы шагнуть и второй ногой тоже. А то между ними как раз зависла суровая действительность, где вся мощь функциональной декомпозиции притянута вниз гирей two-way binding.

J>Почему я тут так подробно это расписываю? Потому что разговор ушел куда-то в полный астрал. Мы уже, вон, до Хаскеля дошли. Непонятно где Немерле только отстало
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[13]: Некоторые мысли о LINQ
От: Jakobz Россия  
Дата: 25.03.09 20:44
Оценка:
Здравствуйте, gandjustas, Вы писали:

J>>Тут одна вешь, которую ты упускаешь, уходя всё дальше от темы: в большинстве случаев "отсоединение" сущностей просто необходимо.

G>Там где необходимо "отсоединение" там контексты Linq2SQL, EF, сессии NHibernate тоже не справляются и надо "отсоедиенный" набор данных поддерживать руками.
Вполне справляются. Автоматически они это не делают, но лучше уж так, чем никак.

Еще раз:
— identity tracking. Позволяет имитировать отсутствие identity у объектов внутри контекста. Позволяет дозапрашивать данные и не думать о том, что у нас могут появиться два разных объекта с одним и тем же.
— change tracking. Позволяет не писать на каждый чих db.НеЗабудьПроапдейтитьПотом(myObject).

Оба два — для удобства.
Оба — не обязательно юзать, они отключаются
Re[16]: Некоторые мысли о LINQ
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.03.09 21:01
Оценка: +1
Здравствуйте, Jakobz, Вы писали:
J>Просто ты упускаешь следующие моменты:
J>- сложные сценарии обработки данных сложно писать на SQL. Если бы это было не так — писали бы всю логику на хранимках и не парились бы.
Я ничего не упускаю. Сложность обработки данных на SQL связана с убогостью наличных средств декомпозиции.
J> И вот, чтобы обработать эти данные в C#, можно их таки вынуть, преобразовать в формат, понятный C#, обработать их, преобразовать обратно и положить.
Ты опять перескакиваешь через ступеньку.

Вот смотри, я делаю движение номер 1:
var q = from Customers c select c;

Пока ничего интересного не произошло. Но это как раз очень важно: эта строчка пока не означает, что мы "вытащили все данные миллионов кастомеров в C# и преобразовали их в формат, понятный C#"
Теперь я делаю движение номер 2:
if (minRegistrationDate.HasValue)
  q = from q c where c.RegistrationDate >= RegistrationDate.Value
      select c;

Потом я делаю движения номер 3, 4, 5, и так до 18ти.
На 19м я делаю return q.

Компилятор строго следит за тем, чтобы я нигде не накосячил. У меня нет шанса получить в запросе "AND AND". При этом никакие данные никуда не преобразуются. Я работаю с объектом запроса, а не с его результатом.
Вот такой трюк повторить в SQL — чистое самоубийство. Малейшее неровное движение — и в каком-то одном из 2^18 сценариев отчет падает с неустранимой ошибкой.
Что я получил? Я получил "сложный сценарий обработки данных, который сложно писать на SQL". Однако, мне совершенно не потребовалось обрабатывать на C# данные.
Данные должен обрабатывать специализированный сервер, у него это получится значительно лучше, чем у наколенной программы на C#. Сервер умеет применять злую магию индексов, разнообразные оптимизации. Программу на C# можно этому научить, но это еще сложнее, чем функции высшего порядка на T-SQL.

J>Да, не обязательно это делать. Можно работать напрямую на SQL, можно реализовывать какой-то реляционный DSL прямо в языке, и т.п. Но вот Linq to Sql, про который речь, это все-таки подход с преобразованием в объекты.

Ну... В какой-то мере да. Но мы его любим не за это
J>Т.е. это ORM, со всеми его минусами и плюсами.
J>- усложним твой пример с банкоматом. Пусть он показывает текуший счет. И мы считаем, что человек принимает решение о переводе денег, основываясь на текущем счете: из 20штук занять другу 5 — одно, из 6 занять 5 — другое, самому кушать нужно. И мы тут же приходим обратно к обработке оптимистической конкуренции в той или иной форме.
Ну почему обязательно "оптимистической". Вот, к примеру, популярные "Золотые Короны" предлагают вполне себе пессимистическую блокировку, аналогичную системам version control — делаешь себе "checkout" со счета на чиповую карту, и всё. Деньги у тебя, никто со счета их не спишет.

J> Не смотря на то, что "перевод денег" остается таким же атомарным действием. Пример можно сколь угодно усложнять. Главное тут то, что что-то из внешней среды принимает решение за конечное время, основываясь на потенциально устаревшей информации. Т.е. дело не в "концепции сохранения", проблема эта будет существовать при абсолютно любых условиях.

Вовсе даже не при любых. Вот, к примеру, наши форумы. Ты пишешь ответ мне. В это время кто-то другой пишет ответ мне на то же сообщение. Вы друг другу никак не мешаете — потому, что ты не пытаешься вручную увеличивать счетчик ответов.
Проблемы с "устарелостью информации" разрешимы только в замкнутой среде, как, к примеру, в том же SQL Server.
Там, если ты сделал select balance from account where id = 1 (при уровне изоляции serializable), то он умрёт, но не даст никому сделать так, чтобы эта информация "устарела".
Вот только удерживать эту транзакцию длительное время — дорого. Причем эта дорогостоящесть связана не с механикой конкретной блокировки — в оптимистической технике будет примерно то же самое, только стоимость возьмут не с тех, кто "позже прочитал", а с тех, кто "позже записал". Это размазывание состояния, а оно бесплатным не бывает.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[14]: Некоторые мысли о LINQ
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 25.03.09 21:03
Оценка: +1
Здравствуйте, Jakobz, Вы писали:

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


J>>>Тут одна вешь, которую ты упускаешь, уходя всё дальше от темы: в большинстве случаев "отсоединение" сущностей просто необходимо.

G>>Там где необходимо "отсоединение" там контексты Linq2SQL, EF, сессии NHibernate тоже не справляются и надо "отсоедиенный" набор данных поддерживать руками.
J>Вполне справляются. Автоматически они это не делают, но лучше уж так, чем никак.
Они это никак не делают.
Контекст обычно жевет гораздо меньше, чем проходит времени от показу пользователю формы до ввода данных.

J>Еще раз:

J>- identity tracking. Позволяет имитировать отсутствие identity у объектов внутри контекста. Позволяет дозапрашивать данные и не думать о том, что у нас могут появиться два разных объекта с одним и тем же.
J>- change tracking. Позволяет не писать на каждый чих db.НеЗабудьПроапдейтитьПотом(myObject).

J>Оба два — для удобства.

J>Оба — не обязательно юзать, они отключаются
Только при откоючении обоих изменить данные становиться тяжко.
Я бы сказал что identity\change tracking — необходимые фичи современного ORM (хотя также необходима возможность их отключения для некоторых сценариев).
Но такой способ работать с данными — далеко не единственный, и не самый правильный.
Re[13]: Некоторые мысли о LINQ
От: Jakobz Россия  
Дата: 25.03.09 21:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Я тебя понимаю — я еще в долинковские времена наприседался с ORM, и самописанными в том числе, и все их прелести прекрасно осознаю. Linq — это шаг в правильную сторону, вот только надо бы шагнуть и второй ногой тоже. А то между ними как раз зависла суровая действительность, где вся мощь функциональной декомпозиции притянута вниз гирей two-way binding.


Я тоже понимаю о чем вы говорите. Но это всё очень далеко от практики.
Хорошие подходы: тащить код к данным, а не наоборот, писать на языке, удобным для работы со структурой данных, и т.п. Но они все как-то не совмещаются ни с SQL, ни с C#. Не сможешь ты прозрачно отобразить сколько-то сложный C#-код или какой-то DSL на нем, в полноценный SQL прямо на сервере. А если и сможешь — умрешь разбираться с проблемами производительности и блокировками.
Поэтому модель "оцепил что нужно — обработал — положил назад" — очень даже жизнеспособна. Хотя, конечно, эта вся гетерогенность в виде совершенно разных SQL и C#-или-что-еще-там местами напрягает, да.
Re[14]: Некоторые мысли о LINQ
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.03.09 21:34
Оценка: +1
Здравствуйте, Jakobz, Вы писали:

J>Хорошие подходы: тащить код к данным, а не наоборот, писать на языке, удобным для работы со структурой данных, и т.п. Но они все как-то не совмещаются ни с SQL, ни с C#. Не сможешь ты прозрачно отобразить сколько-то сложный C#-код или какой-то DSL на нем, в полноценный SQL прямо на сервере.

Я не понимаю — неужели Linq2Sql недостаточно убедительно демонстрирует отображение C# в полноценный SQL с блэкджеком и шлюхами?
Никакого сомнения нет в том, что всё это возможно (с некоторыми нюансами).

J>А если и сможешь — умрешь разбираться с проблемами производительности и блокировками.

J>Поэтому модель "оцепил что нужно — обработал — положил назад" — очень даже жизнеспособна.
Всё как раз наоборот: проблемы производительности и блокировок — вторая натура "отсоединенной модели".
Ты еще учти, что в веб, к примеру, приложении, отсоединенные данные один хрен выбрасываются в гарбадж коллектор. Потому что следующий запрос будут обрабатывать совсем другие объекты, и другой датаконтекст.

J>Хотя, конечно, эта вся гетерогенность в виде совершенно разных SQL и C#-или-что-еще-там местами напрягает, да.


Лично меня напрягает только отсутствие полного контроля над событиями. В этом смысле EF всё-таки меньшее зло по сравнению с full blown ORM, но всё-таки дает некоторую излишнюю изоляцию от того, что происходит.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[17]: Некоторые мысли о LINQ
От: Jakobz Россия  
Дата: 25.03.09 21:47
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вот смотри, я делаю движение номер 1:

S>
S>var q = from Customers c select c;
S>

S>Пока ничего интересного не произошло. Но это как раз очень важно: эта строчка пока не означает, что мы "вытащили все данные миллионов кастомеров в C# и преобразовали их в формат, понятный C#"
S>Теперь я делаю движение номер 2:
S>
S>if (minRegistrationDate.HasValue)
S>  q = from q c where c.RegistrationDate >= RegistrationDate.Value
S>      select c;
S>

S>Потом я делаю движения номер 3, 4, 5, и так до 18ти.
S>На 19м я делаю return q.

Да это все понятно. Но опять же опустимся с небес на землю. Вот есть какая-то сложная операция, не влезающая в SQL. Например — поиск хорошего ресторана, до которого по трассе от заданой точки не дальше 5 км. Такой запрос не ляжет на LINQ. Мы можем заюзать его для извлечения минимума нужных данных, например можно вынуть все перекрестки и рестораны в квадрате 10x10 км — этого нам должно хватить. И потом — уточнить это все дело уже в коде. Там нам не нужно будет плясять с бубнами, заставляя SQL-сервер решать эту задачу, заодно и снимем с него вычислительную нагрузку.

Я хочу показать, что на простых примерах — да, select в LINQ решает простые проблемы от корки до корки и это клёво. А чуть дальше — и всё, приехали. И это — только запросы. Сценарии обработки информации могут быть намного сложнее.

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


Да понятно что размазывание состояния не бывает бесплатным. Речь о том, что без него далеко не всегда можно обойтись. А порой оно, создавая, конечно, свои проблемы, решает другие: масштабирируемость например может увеличить.

Кстати про аналогию между оптимистической и пессимистической блокировкой. Есть таки принципиальная разница. Например Вася и Дима открыли форму редактирования чего-то там. В пессимистическом варианте мы заблокируем полученые данные до того, как они оба эту форму не закроют. В оптимистическом — мы не дадим потом им сохранить изменения. Но далеко не факт, что они захотят что-то сохранять.
Re[15]: Некоторые мысли о LINQ
От: Jakobz Россия  
Дата: 25.03.09 21:48
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Я бы сказал что identity\change tracking — необходимые фичи современного ORM (хотя также необходима возможность их отключения для некоторых сценариев).

G>Но такой способ работать с данными — далеко не единственный, и не самый правильный.

Видимо мы таки пришли к пониманию
Re[14]: Некоторые мысли о LINQ
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 25.03.09 21:49
Оценка: +2
Здравствуйте, Jakobz, Вы писали:

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


S>>Я тебя понимаю — я еще в долинковские времена наприседался с ORM, и самописанными в том числе, и все их прелести прекрасно осознаю. Linq — это шаг в правильную сторону, вот только надо бы шагнуть и второй ногой тоже. А то между ними как раз зависла суровая действительность, где вся мощь функциональной декомпозиции притянута вниз гирей two-way binding.


J>Я тоже понимаю о чем вы говорите. Но это всё очень далеко от практики.

J>Хорошие подходы: тащить код к данным, а не наоборот, писать на языке, удобным для работы со структурой данных, и т.п. Но они все как-то не совмещаются ни с SQL, ни с C#. Не сможешь ты прозрачно отобразить сколько-то сложный C#-код или какой-то DSL на нем, в полноценный SQL прямо на сервере.
Если хочется отображать императивный код на C#, то лучше и не пытаться. А если вполне функциональный Linq, то очень даже хорошо получается.
Сейчас Linq мапится в селекты очень хорошо, за исключением CTE и, кое-где уловия IN.

J>А если и сможешь — умрешь разбираться с проблемами производительности и блокировками.

Как раз с проблем с производительностью и блокировками будет меньше.

J>Поэтому модель "оцепил что нужно — обработал — положил назад" — очень даже жизнеспособна.

В отсуствии лучшего решения — конечно.
Re[18]: Некоторые мысли о LINQ
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 25.03.09 22:04
Оценка:
Здравствуйте, Jakobz, Вы писали:

J>Да это все понятно. Но опять же опустимся с небес на землю. Вот есть какая-то сложная операция, не влезающая в SQL. Например — поиск хорошего ресторана, до которого по трассе от заданой точки не дальше 5 км. Такой запрос не ляжет на LINQ. Мы можем заюзать его для извлечения минимума нужных данных, например можно вынуть все перекрестки и рестораны в квадрате 10x10 км — этого нам должно хватить. И потом — уточнить это все дело уже в коде. Там нам не нужно будет плясять с бубнами, заставляя SQL-сервер решать эту задачу, заодно и снимем с него вычислительную нагрузку.

Такой запрос написать можно (в MS SQL 2008), и я уверен что работать оно будет побыстрее, чем наколеночная реализация в клиетском коде.

J>Я хочу показать, что на простых примерах — да, select в LINQ решает простые проблемы от корки до корки и это клёво. А чуть дальше — и всё, приехали. И это — только запросы. Сценарии обработки информации могут быть намного сложнее.

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

Именно Linq позволяет с простотой использования стаически типизированного языка собирать sql запросы.

J>Да понятно что размазывание состояния не бывает бесплатным. Речь о том, что без него далеко не всегда можно обойтись. А порой оно, создавая, конечно, свои проблемы, решает другие: масштабирируемость например может увеличить.

Да ну?
stateless улучшает масштабируемость, но никак не размазанность состояния.

J>Кстати про аналогию между оптимистической и пессимистической блокировкой. Есть таки принципиальная разница. Например Вася и Дима открыли форму редактирования чего-то там. В пессимистическом варианте мы заблокируем полученые данные до того, как они оба эту форму не закроют. В оптимистическом — мы не дадим потом им сохранить изменения. Но далеко не факт, что они захотят что-то сохранять.

Левая аналогия. Работа БД — не открытие форм пользователем.
Даже если рассматривать пользователей, то оба могут открыть форму на чтение, но пока один правит (считаем что данные общие), другой не может увидеть ни актуальные данные, ни поменять что-то сам.
Re[15]: Некоторые мысли о LINQ
От: Jakobz Россия  
Дата: 25.03.09 22:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Я не понимаю — неужели Linq2Sql недостаточно убедительно демонстрирует отображение C# в полноценный SQL с блэкджеком и шлюхами?

S>Никакого сомнения нет в том, что всё это возможно (с некоторыми нюансами).

Linq2Sql демонстрирует отображение Linq в SQL, а не C# в SQL. Нет никаких сомнений что можно также завернуть и update-ы. Сомнения есть в том, что так можно завернуть решение диф. уравнений или поиск пути на графе. Так или иначе для решения сложных задач тебе придется вытаскивать данные на уровень приложения.

S>Всё как раз наоборот: проблемы производительности и блокировок — вторая натура "отсоединенной модели".


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

S>Ты еще учти, что в веб, к примеру, приложении, отсоединенные данные один хрен выбрасываются в гарбадж коллектор. Потому что следующий запрос будут обрабатывать совсем другие объекты, и другой датаконтекст.


Ну они не совсем выбрасываются. Они просто проходят тяжкий путь через веб-запросы и пользовательский браузер.

S>Лично меня напрягает только отсутствие полного контроля над событиями. В этом смысле EF всё-таки меньшее зло по сравнению с full blown ORM, но всё-таки дает некоторую излишнюю изоляцию от того, что происходит.


Ну это так везде. Чем выше абстракция — тем больнее с нее падать
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.