Здравствуйте, 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 в декларациях.
Проблемы в "реальных" приложениях обусловленны объективной сложность этих самых реальных приложений и мира в котором мы живем