Re: Настольная БД
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.04.06 05:08
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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

Это означает, что мы не можем отдать, к примеру, IEnumerable<OrderItem>, если OrderItem — это персистент ентити, и у нее есть свойство OrderItem.Order, кое указывает на персистент же ентити Order. Потому не можем, что это называется "навигация", и в общем случае потребует выполнения отдельного запроса, а это в свою очередь ведет к массе пренеприятнейших проблем и семантических неоднозначностей на пустом месте.
Вот ведь как хорошо в plain SQL! Там никакой навигации нету, и максимум, что может себе позволить иметь OrderItem — это свойство OrderId, размеченное соответствующим атрибутом. Все ясно, как день: хочешь Order по OrderItem — иди в базу лишний раз, получай Order по OrderId. Ну или сразу выбирай все, что нужно.

Но тогда синтаксис становится чрезмерно громоздким. К чему нам эти Id? Их значения как таковые вовсе не нужны; Id бывают потребны только для FK и навигации.
Хочется писать в запросах вместо
select orderItem.* from orderItem inner join order on orderItem.OrderId = orderId 
where order.Amount>100

просто
select * from orderItem where orderItem.Order.Amount > 100;


Это все хорошо для самописанного языка запросов — можно, к примеру, ввести спец.синтаксис для разыменования FK:
select * from orderItem where orderItem->Order.Amount > 100;

, но тогда теряются преимущества Linq в виде статической проверки запросов. А в Linq все честно — все предикаты описываются в коде делегатов, а стало быть, по возможностям запросы и "нормальный код" эквивалентны. Так что как только мы позволим OrderItem заиметь свойство Order, как к этому свойству тут же можно будет обратиться за пределами запроса.

Есть идеи, как можно разрулить эту идеологическую пропасть?
— Бросать исключение при попытке сделать dereference на FK-свойство за пределами запроса? (при выполнении запроса все равно никакого вызова get для этого свойства происходить не будет; вместо этого "под капотом" станет выполняться соответствующий join)
— Ограничить возможные результаты запроса потоками записей, состоящих из простых типов (принудительно "планаризовать" объектные данные). Богатая, кстати, идея, в плане 100% гарантии отсутствия злонамеренных побочных эффектов. Но неудобна тем, что затрудняет повторное использование запросов.
— Позволить в запросе намекать на то, какие данные еще могут понадобиться, и фактически отдавать не просто IEnumerable<OrderItem>, а целый граф объектов, до которых можно добраться по ссылкам из этих OrderItem (тогда результат dereference FK будет гарантированно одинаков и в запросе, и в "клиентском коде").
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Настольная БД
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 18.04.06 07:42
Оценка:
Здравствуйте, Sinclair, Вы писали:

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

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

Ну, собственно, так LINQ и работает. В случае standard query operators реализация такого поведения тривиальна, в случае DLINQ все, конечно, сложнее.

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


Не совсем так. Не забывай о том, что лямбды могут быть представлены анонимными методами, а могут ввиде expression tree. Очевидно, что DLINQ пользуется вторым, и столь же очевидно что DLINQ проглотит не любую лямбду.

S>Есть идеи, как можно разрулить эту идеологическую пропасть?


Я бы просто не отходил от реляционной модели.

S>- Бросать исключение при попытке сделать dereference на FK-свойство за пределами запроса? (при выполнении запроса все равно никакого вызова get для этого свойства происходить не будет; вместо этого "под капотом" станет выполняться соответствующий join)

S>- Ограничить возможные результаты запроса потоками записей, состоящих из простых типов (принудительно "планаризовать" объектные данные). Богатая, кстати, идея, в плане 100% гарантии отсутствия злонамеренных побочных эффектов. Но неудобна тем, что затрудняет повторное использование запросов.
S>- Позволить в запросе намекать на то, какие данные еще могут понадобиться, и фактически отдавать не просто IEnumerable<OrderItem>, а целый граф объектов, до которых можно добраться по ссылкам из этих OrderItem (тогда результат dereference FK будет гарантированно одинаков и в запросе, и в "клиентском коде").

ИМХО первый вариант лучше всего.
... << RSDN@Home 1.2.0 alpha rev. 642>>
AVK Blog
Re[3]: Настольная БД
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.04.06 09:03
Оценка:
Здравствуйте, AndrewVK, Вы писали:
AVK>Ну, собственно, так LINQ и работает. В случае standard query operators реализация такого поведения тривиальна, в случае DLINQ все, конечно, сложнее.
Ну, там я не совсем уверен — мне казалось что standarв query operators имеют ленивую семантику (а тогда модификация исходной коллекции в процессе енумерирования выкинет InvalidOperationException). Впрочем, в данном контексте это не столь уж важно.
S>>, но тогда теряются преимущества Linq в виде статической проверки запросов. А в Linq все честно — все предикаты описываются в коде делегатов, а стало быть, по возможностям запросы и "нормальный код" эквивалентны.

AVK>Не совсем так. Не забывай о том, что лямбды могут быть представлены анонимными методами, а могут ввиде expression tree. Очевидно, что DLINQ пользуется вторым, и столь же очевидно что DLINQ проглотит не любую лямбду.

Ну, я про себя думаю, что мы будем жить не с DLinq, а с каким-то своим ?Linq. Кроме того, если я правильно понял, то все зависит ровно от контекста, в котором мы употребляем лямбда експрешшн. Т.о. если мы не будем рисковать здоровьем и предлагать метод с сигнатурой типа DbTable<T>.Where(Predicate<T> where), куда может приехать любой делегат, а ограничимся только expression tree, то никаких чудес не возникнет.
Ну, и опять же очевидно, что мы тоже не обязаны глотать любую лямбду. Вон Dlinq не собирается этого делать — и ничего, никто в обмороке не лежит пока. Хотя, конечно, ultimate goal — это ровно предоставить 100% поддержку всего, что доступно в standard query operators и при этом при близком к теоретическому минимуму количестве page scan
AVK>Я бы просто не отходил от реляционной модели.
Т.е. все же полноразмерные join? Кстати, не можешь кинуть в двух словах синтаксис джойнов в Dlinq?
AVK>ИМХО первый вариант лучше всего.
Да, я тоже к нему склоняюсь. И волки целы, и овцы сыты.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Настольная БД
От: Belsen  
Дата: 18.04.06 09:49
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Есть идеи, как можно разрулить эту идеологическую пропасть?

S>- Бросать исключение при попытке сделать dereference на FK-свойство за пределами запроса? (при выполнении запроса все равно никакого вызова get для этого свойства происходить не будет; вместо этого "под капотом" станет выполняться соответствующий join)
S>- Ограничить возможные результаты запроса потоками записей, состоящих из простых типов (принудительно "планаризовать" объектные данные). Богатая, кстати, идея, в плане 100% гарантии отсутствия злонамеренных побочных эффектов. Но неудобна тем, что затрудняет повторное использование запросов.
S>- Позволить в запросе намекать на то, какие данные еще могут понадобиться, и фактически отдавать не просто IEnumerable<OrderItem>, а целый граф объектов, до которых можно добраться по ссылкам из этих OrderItem (тогда результат dereference FK будет гарантированно одинаков и в запросе, и в "клиентском коде").
Если я правильно помню, в DLinq реализован третий вариант, c Including.
IEnumerable<Order> orders = Orders.Where(o => o.Amount > 100)
                                .Including(o => o.OrderApprovalNote, o => 
                                     o.OrderDetails.Including(od => od.Products.Including(p => p.Category));

Думаю, небольшим хаком можно и первый вариант получить.

А в пределе мечтаний, конечно хотелось бы, что бы количество загружаемых в запросе данных расчитывалось в компайл-тайме анализом кода, который будет эти данные использовать. Но первый же виртуальный вызов потребует переноса этого процесса в рантайм, а там понятно, что хотелось бы учитывать и вероятность того, понадобятся дополнительные данные или нет, учитывать и стоимость догрузки недостающих данных, и оверхед загрузки неиспользуемых.
И тогда ручная загрузка данных станет таким же моветоном, как и ручное управление памятью, и на каком-нибудь форуме устанут повторять, что пытаться обогнать с помощью ручной загрузки оптимизатор в неспецифических случаях практического смысла не имеет
I might be wrong...
Re[4]: Настольная БД
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 18.04.06 09:55
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Ну, я про себя думаю, что мы будем жить не с DLinq, а с каким-то своим ?Linq.


Естественно.

S> Кроме того, если я правильно понял, то все зависит ровно от контекста, в котором мы употребляем лямбда експрешшн. Т.о. если мы не будем рисковать здоровьем и предлагать метод с сигнатурой типа DbTable<T>.Where(Predicate<T> where), куда может приехать любой делегат, а ограничимся только expression tree, то никаких чудес не возникнет.


Ну как бы тебе сказать. Да, формирование expression tree диктуется контекстом, а точнее типом параметров методов. Но множество допустимых expression tree больше можества допустимых для движка БД лямбд.

AVK>>Я бы просто не отходил от реляционной модели.

S>Т.е. все же полноразмерные join?

Да.

S> Кстати, не можешь кинуть в двух словах синтаксис джойнов в Dlinq?


Нет. Я его сам не видел. Просто знаю что он вобще есть и все. Ждем очередного CTP.
... << RSDN@Home 1.2.0 alpha rev. 642>>
AVK Blog
Re[3]: Настольная БД
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 18.04.06 10:04
Оценка: :)
Здравствуйте, Belsen, Вы писали:

B>А в пределе мечтаний, конечно хотелось бы, что бы количество загружаемых в запросе данных расчитывалось в компайл-тайме анализом кода, который будет эти данные использовать.


А почему бы тогда не захотеть, что бы сами данные были вкомпилированы в код. Тогда можно было бы избежать использования БД в рантайме вообще.
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[3]: Настольная БД
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 18.04.06 10:05
Оценка:
Здравствуйте, Belsen, Вы писали:

B>А в пределе мечтаний, конечно хотелось бы, что бы количество загружаемых в запросе данных расчитывалось в компайл-тайме анализом кода, который будет эти данные использовать.


В компайл тайме малореально во-первых из-за ограничений языка (Влад, молчать ), а во-вторых из-за того что ряд данных (навроде статистики), может быть в компайл-тайме просто недоступен.
Отдельная песня, если вдруг захочется писать запрос в терминах интерфейсов, а реализацию брать из сборок в БД уже в рантайме.

B> Но первый же виртуальный вызов потребует переноса этого процесса в рантайм,


Виртуальность нужна только при наличии наследования, следовательно вначале надо определится с ним.
... << RSDN@Home 1.2.0 alpha rev. 642>>
AVK Blog
Re[2]: Настольная БД
От: stalcer Россия  
Дата: 18.04.06 10:13
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Это означает, что мы не можем отдать, к примеру, IEnumerable<OrderItem>, если OrderItem — это персистент ентити, и у нее есть свойство OrderItem.Order, кое указывает на персистент же ентити Order.

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

Если уж мы собираемся работать с "персистент ентитями", то и думать надо (семантику задавать) по объектному. Навигация — она только в этом случае смысл имеет. То есть как минимум должен быть идентити-мап, чтобы объекты не дублировались в памяти.
А семантика — она здесь простая:

Во-первых не надо выполнять запрос вида:
select x.* from OrderItems x

А надо выполнять запрос вида:
select x from OrderItems x

Что должно означать то, что мы выбираем ссылки на обекты OrderItem. OrderItem ведь ссылочный тип. Ну и, собственно, получается, что результатом выполнения запроса будет набор ссылок, который действительно после выполнения уже не будет зависеть от дальнейших модификаций персистентных ентитей, хотя состояние самих ентитей — естественно будет зависеть. Ну дык, мы состояние-то и не выбирали !

S>Все ясно, как день: хочешь Order по OrderItem — иди в базу лишний раз, получай Order по OrderId.


Если принять идеологию ссылок, то это ничем не будет отличаться от навигации. Более неудобно — да, а семантически — ничем.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Настольная БД
От: Belsen  
Дата: 18.04.06 10:26
Оценка:
Здравствуйте, AndrewVK, Вы писали:

B>> Но первый же виртуальный вызов потребует переноса этого процесса в рантайм,

AVK>Виртуальность нужна только при наличии наследования, следовательно вначале надо определится с ним.
Имелось ввиду, что например в таком методе
public void ProcessOrdersData(IOrderProcessor orderprocessor)
{
    IEnumerable<Orders> orders = db.Orders.Where(o => o.Valid);
    orderprocessor.ProcessOrders(orders);
}

в компайл-тайме мы не можем даже теоретически определить количество необходимых данных в запросе. Нужно что-то вроде HotDataSpot, что бы генерировать отдельный запрос на каждую реализацию IOrderProcessor.
I might be wrong...
Re[3]: Настольная БД
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.04.06 10:46
Оценка:
Здравствуйте, Belsen, Вы писали:

B>А в пределе мечтаний, конечно хотелось бы, что бы количество загружаемых в запросе данных расчитывалось в компайл-тайме анализом кода, который будет эти данные использовать.

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

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

Пределом моих мечтаний является такой анализ кода, который позволяет оптимально назначать блокировки.
Ну вот к примеру, если я не делаю в транзакции повторных чтений, то для обеспечения serializable мне вполне достаточно удерживать read locks только на время сканирования. А если делаю — то надо держать локи до последнего чтения.
Современная реляционная СУБД в силу своей клиент-серверной природы ничего не может сказать о предстоящих действиях шального клиента. Поэтому такими вещами рулят разработчик на пару с дба, расставляя хинты и уровни изоляции. А в мегакрутой мегасреде, где весь код доступен еще до момента начала его выполнения, можно и поанализировать.

В теории это все близко к escape-анализу, который то ли собираются, то ли уже применили в Java для принятия решения о размещении объекта в стеке.

B>И тогда ручная загрузка данных станет таким же моветоном, как и ручное управление памятью, и на каком-нибудь форуме устанут повторять, что пытаться обогнать с помощью ручной загрузки оптимизатор в неспецифических случаях практического смысла не имеет

Угу. Уже сейчас порвать промышленную RDBMS хинтами крайне сложно.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Настольная БД
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 26.04.06 10:24
Оценка:
Судя по всему, кто хотел что то сказать, тот уже высказался. Посему всем спасибо. Заинтересованные в дальнейшей проработке концепции пишите мне на avk (собака) rsdn.ru.
... << RSDN@Home 1.2.0 alpha rev. 642>>
AVK Blog
Re[2]: Настольная БД
От: WoldemaR Россия  
Дата: 26.04.06 12:09
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Судя по всему, кто хотел что то сказать, тот уже высказался. Посему всем спасибо. Заинтересованные в дальнейшей проработке концепции пишите мне на avk (собака) rsdn.ru.


А можно маленькое такое замечание в догоночку... а?

Когда мне говорят про БД я воспринимаю это автоматом как предложение делать одну т туже работу дважды — рисовать таблицы и классы, а потом играть в синхронизацию моделей.
Если вам хотябы в концепции удасться избавить людей от этой утомительной игры — то будет большой респект.
Re[3]: Настольная БД
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 26.04.06 12:28
Оценка:
Здравствуйте, WoldemaR, Вы писали:

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

WR>Если вам хотябы в концепции удасться избавить людей от этой утомительной игры — то будет большой респект.

Об этом речь уже шла. Кое какие наметки есть в заготовке концепта, который я рассылал заинтересованным лицам. Вобщем то идея вполне логичная — LINQ устраняет промежуток между типами кортежей БД и типами программы, хотелось бы аналогичного механизма и в случае метаданных.
... << RSDN@Home 1.2.0 alpha rev. 642>>
AVK Blog
Re[2]: Настольная БД
От: GlebZ Россия  
Дата: 26.04.06 16:14
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Судя по всему, кто хотел что то сказать, тот уже высказался. Посему всем спасибо. Заинтересованные в дальнейшей проработке концепции пишите мне на avk (собака) rsdn.ru.

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

С уважением, Gleb.
Re[3]: Настольная БД
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.04.06 17:47
Оценка: :)
Здравствуйте, GlebZ, Вы писали:

AVK>>Судя по всему, кто хотел что то сказать, тот уже высказался. Посему всем спасибо. Заинтересованные в дальнейшей проработке концепции пишите мне на avk (собака) rsdn.ru.

GZ>Безумству храбрых поем мы песню.
GZ>Что-то я думал что все заглохло и пропало. Обычно когда человек замысливал такую вещь, его тут же отсылали к литературе и готовым образцам. После чего он как-то пропадал. Не ожидал.

Наоборот, напоминает афоризм: "Послушай женщину и сделай наоборот".
А толпа, как говаривал один известный деятель XX-го века -- она как женщина, любит силу


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: Настольная БД
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.05.06 04:19
Оценка:
Здравствуйте, AndrewVK, Вы писали:
Кстати, о птичках. Давно я не смотрел на DB4O. Вроде как и LINQ у них ужо есть... И репликация с RDBMS реализована для Occaisonally Connected модели...
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Настольная БД
От: GlebZ Россия  
Дата: 14.05.06 18:06
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Кстати, о птичках. Давно я не смотрел на DB4O. Вроде как и LINQ у них ужо есть...

Я бы это Linq не назвал(блин, назвали бы внутренний язык DLinq как нибудь по другому. Чтобы идентифицировать легче). Там SODA.
Вообще же там три языка.
1. QBE — Query By Example. Язык на основе прототипирования.
2. SODA.
3. Native QueryЗдесь Здесь Эти запросы пытается в свою очередь пытаются перевести в SODA и в таком виде оптимизировать и выполнить. А возможности SODA достаточно ограничены. Что не смог, то выполняет в явном виде с полным инстанцированием.
SODA — это не DLINQ. Джоинов там нет. Точнее все join могут выполняться только по предопределенным связкам. Что особенно не нравится — нет возможностей инстанцирования по умолчанию абстрактных классов и интерфейсов. Групповых операций тоже нет(что с их системой инстанцирования, неудивительно).
PS. Кстати, майский Linq уже вышел.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[3]: Настольная БД
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.05.06 04:49
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>3. Native QueryЗдесь


GZ> Здесь Эти запросы пытается в свою очередь пытаются перевести в SODA и в таком виде оптимизировать и выполнить. А возможности SODA достаточно ограничены. Что не смог, то выполняет в явном виде с полным инстанцированием.

Совершенно верно. Именно так работает DLinq. Какая разница, в какой таргет язык переводится предикат???
GZ>SODA — это не DLINQ. Джоинов там нет. Точнее все join могут выполняться только по предопределенным связкам. Что особенно не нравится — нет возможностей инстанцирования по умолчанию абстрактных классов и интерфейсов. Групповых операций тоже нет(что с их системой инстанцирования, неудивительно).
Хы-хы. Иначе б жить было скучно.
GZ>PS. Кстати, майский Linq уже вышел.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Настольная БД
От: GlebZ Россия  
Дата: 15.05.06 07:12
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Совершенно верно. Именно так работает DLinq. Какая разница, в какой таргет язык переводится предикат???

Вообще-то нет. У DLinq явно выделены комманды которые может распарсить и воспользоваться, и которые не может. Посмотри последнюю документашку по DLinq. Правда документации по expression tree так и нету.

GZ>>SODA — это не DLINQ. Джоинов там нет. Точнее все join могут выполняться только по предопределенным связкам. Что особенно не нравится — нет возможностей инстанцирования по умолчанию абстрактных классов и интерфейсов. Групповых операций тоже нет(что с их системой инстанцирования, неудивительно).

S>Хы-хы. Иначе б жить было скучно.
Этто точно.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.