Разбирался на днях с Entity Framework, точнее сказать задача стояла работать с базой через ORM, и я остановился на Entity Framework.
У меня сложилось очень двоякое впечатление. Что-то хорошо, а что-то, что можно сделать совершенно простым запросом к бд, через entity framework просто так не сделаешь.
Здравствуйте, Ringin, Вы писали:
R>Разбирался на днях с Entity Framework, точнее сказать задача стояла работать с базой через ORM, и я остановился на Entity Framework. R>У меня сложилось очень двоякое впечатление. Что-то хорошо, а что-то, что можно сделать совершенно простым запросом к бд, через entity framework просто так не сделаешь.
R>Выскажите пожалуйста свои мнения!
Ну почему же, многие вещи даже проще чем в SQL
Кстати вроде как и сейчас можно в Linq to SQL использовать вывод типа http://msdn.microsoft.com/ru-ru/magazine/hh781018.aspx
string entitySQL = " SELECT p, p.Filling " +
"FROM PartyContext.Pinatas AS p "
"WHERE p.Filling.Description='Candy'";
var query=context.CreateQuery<DbDataRecord>(entitySQL);
query.MergeOption = System.Data.Objects.MergeOption.NoTracking;
var pinatasWithFilling=query.ToList();
Такой аля 1С ный синтаксис
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Ringin, Вы писали:
R>Разбирался на днях с Entity Framework, точнее сказать задача стояла работать с базой через ORM, и я остановился на Entity Framework. R>У меня сложилось очень двоякое впечатление. Что-то хорошо, а что-то, что можно сделать совершенно простым запросом к бд, через entity framework просто так не сделаешь.
Крайне медленный, уродливый и костыльный framework. Если вам нужен простой OM, советую Dapper. Для более сложных задач может вполне сгодиться NHibernate. Если все-таки намерены использовать EF, будьте готовы к крайне низкой производительности, огромному количеству кода и целому валу проблем.
S>> Такой аля 1С ный синтаксис
R>А вот надо мне например вывести пользователю все таблицы базы данных, прочитать констрейнты и показать связи, как это сделать?
Так никто тебе не мешает использовать SQL, там где это удобнее. Просто в Linq to EF полно прочих вкусностей. Ассемблер в нативе никто пока не запрещал
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, a_g_99, Вы писали:
__>Если все-таки намерены использовать EF, будьте готовы к крайне низкой производительности, огромному количеству кода и целому валу проблем.
В этом смысле это тот же NHibernate только в профиль — разницы никакой.
Здравствуйте, IB, Вы писали:
IB>В этом смысле это тот же NHibernate только в профиль — разницы никакой.
По крайней мере он быстрее EF(по моим личным тестам в среднем примерно в 6 раз). И там можно что-то быстро исправить (open source). А вообще согласен, оба каркаса отвратительны.
Здравствуйте, a_g_99, Вы писали:
__>Здравствуйте, IB, Вы писали:
IB>>В этом смысле это тот же NHibernate только в профиль — разницы никакой. __>По крайней мере он быстрее EF(по моим личным тестам в среднем примерно в 6 раз). И там можно что-то быстро исправить (open source). А вообще согласен, оба каркаса отвратительны.
Здравствуйте, QrystaL, Вы писали:
QL>Что посоветуете в качестве альтернативы?
В одной русской(российской?) песне пелось "Лучшие друзья девушек это бриллианты". Аналогично ситуации, лучшим другом developer является SqlDataReader. Но если вы все-таки хотите большего:
1) dapper, микро-OM для некоторого "ускорения" процесса разработки. Это скорее некоторая идеология а не полноценная ORM, но ее вполне достаточно like base для дальнейшего построения DL
2) разрабатывайте собственную OM based on features & tasks in DL которые вы должны реализовать
Здравствуйте, a_g_99, Вы писали:
__>Здравствуйте, QrystaL, Вы писали:
QL>>Что посоветуете в качестве альтернативы? __>В одной русской(российской?) песне пелось "Лучшие друзья девушек это бриллианты". Аналогично ситуации, лучшим другом developer является SqlDataReader. Но если вы все-таки хотите большего:
Только хранимки, только динамический sql, только хардкор!
__>2) разрабатывайте собственную OM based on features & tasks in DL которые вы должны реализовать
Здравствуйте, Yoriсk, Вы писали:
Y>И велосипедирование!
У каждого свой уровень. Кто-то велесипидирует, кто-то максимально эффективно и быстро реализует свой DL.
Здравствуйте, a_g_99, Вы писали:
__>Здравствуйте, Serginio1, Вы писали:
S>>1C __>За что же вас так Бог наказал ?
Может наоборот Природа наградила? А если без шуток, то для небольших систем Linq to EF самое то. Все, что больше уже требует огромного количества кода и наработок. А вот здесь уже выступают системы типа 1С,Microsoft Dynamics и оракловские продукты. Скорости вполне хватает, а для записи бОльших данных можно использовать прямой доступ. В том числе и для чтения но это типа не правильно, так позволяет обходиться без ключей.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Ringin, Вы писали:
R>Разбирался на днях с Entity Framework, точнее сказать задача стояла работать с базой через ORM, и я остановился на Entity Framework. R>У меня сложилось очень двоякое впечатление. Что-то хорошо, а что-то, что можно сделать совершенно простым запросом к бд, через entity framework просто так не сделаешь.
R>Выскажите пожалуйста свои мнения!
Хорошая вещь, сильно упрощает жизнь, за счет графического дизайнера модели можно быстро начать работать и уже по ходу дела разбираться с тонкостями.
Сильно тормозит на запросах к нескольким связанным таблицам. Но вообще, если что-то работает не так, как хотелось бы, почти всегда можно выкрутиться.
Здравствуйте, a_g_99, Вы писали:
__> И там можно что-то быстро исправить (open source). А вообще согласен, оба каркаса отвратительны.
Да и EF теперь OpenSource здесь
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, a_g_99, Вы писали:
__>>Если все-таки намерены использовать EF, будьте готовы к крайне низкой производительности, огромному количеству кода и целому валу проблем. IB>В этом смысле это тот же NHibernate только в профиль — разницы никакой.
Здравствуйте, Ringin, Вы писали:
R>Разбирался на днях с Entity Framework, точнее сказать задача стояла работать с базой через ORM, и я остановился на Entity Framework. R>У меня сложилось очень двоякое впечатление. Что-то хорошо, а что-то, что можно сделать совершенно простым запросом к бд, через entity framework просто так не сделаешь.
В EF можно напрямую в БД запрос отправить и замапить результаты на классы.
R>Выскажите пожалуйста свои мнения!
Здравствуйте, a_g_99, Вы писали:
__>Здравствуйте, IB, Вы писали:
IB>>В этом смысле это тот же NHibernate только в профиль — разницы никакой. __>По крайней мере он быстрее EF(по моим личным тестам в среднем примерно в 6 раз). И там можно что-то быстро исправить (open source). А вообще согласен, оба каркаса отвратительны.
В последней версии сильно оптимизировали и выложили на codeplex с исходниками.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Вот только разработка собственного LINQ провайдера — та еще задачка, далеко не каждому бюджету по плечу.
Перефразируя классика скажу что "слухи о " полезности LINQ провайдера "сильно преувеличены". Я например всегда обходился SQL, там где теоретически возможно использовать LINQ — это было более просто, изящнее и гораздо эффективнее. Парни из stack_overflow тоже похоже с этим не парились когда разрабатывали dapper. Хотя на вкус и цвет товарищей. Пусть те кто хотят использовать технологии MS типа LINQ, "подставляют бокалы, кто пьет такое".
Здравствуйте, a_g_99, Вы писали:
__>Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>Вот только разработка собственного LINQ провайдера — та еще задачка, далеко не каждому бюджету по плечу. __>Перефразируя классика скажу что "слухи о " полезности LINQ провайдера "сильно преувеличены". Я например всегда обходился SQL, там где теоретически возможно использовать LINQ — это было более просто, изящнее и гораздо эффективнее. Парни из stack_overflow тоже похоже с этим не парились когда разрабатывали dapper. Хотя на вкус и цвет товарищей. Пусть те кто хотят использовать технологии MS типа LINQ, "подставляют бокалы, кто пьет такое".
Если ты не видишь полезности в Linq to database, то это не значит что другие не видят. Я с линком писал такие запросы, что вручную их почти нереально было родить. И эти запросы проверялись при компиляции.
Парни из SO изначально юзали Linq2SQL, а когда структура базы устаканилась и запросы стали более-менее постоянными, то написали лековыесный маппер, чтобы убрать оверхеед.
Надеяться в начале разработки на то, что сразу удастся продумать правильную структуру базы и фиксированные запросы, по меньшей мере глупо.
Здравствуйте, gandjustas, Вы писали:
G>Если ты не видишь полезности в Linq to database, то это не значит что другие не видят.
Разве я против? Я же написал "на вкус и цвет товарищей нет".
>Я с линком писал такие запросы, что вручную их почти нереально было родить. И эти запросы проверялись при компиляции.
Чушь. Ну напишите мне что я "нереально не могу родить" с помощью T-SQL или PL/SQL, что вы можете сделать с помощью LINQ.
G>Парни из SO изначально юзали Linq2SQL, а когда структура базы устаканилась и запросы стали более-менее постоянными, то написали лековыесный маппер, чтобы убрать оверхеед.
И что ? Это как-то оправдывает убогость этого framework? Ваш посыл — они от него отказались, но он все равно хороший ?
G>Надеяться в начале разработки на то, что сразу удастся продумать правильную структуру базы и фиксированные запросы, по меньшей мере глупо.
По меньшей мере глупо быть дураком и не делать все правильно, в т.ч. и структуру БД и реализовать эффективные запросы. Не умеете, наймите того, кто умеет. Это же просто, следовательно правильно.
Здравствуйте, a_g_99, Вы писали:
>>Я с линком писал такие запросы, что вручную их почти нереально было родить. И эти запросы проверялись при компиляции. __>Чушь. Ну напишите мне что я "нереально не могу родить" с помощью T-SQL или PL/SQL, что вы можете сделать с помощью LINQ.
G>>Парни из SO изначально юзали Linq2SQL, а когда структура базы устаканилась и запросы стали более-менее постоянными, то написали лековыесный маппер, чтобы убрать оверхеед. __>И что ? Это как-то оправдывает убогость этого framework? Ваш посыл — они от него отказались, но он все равно хороший ?
Важно что они с него начали и 2 года на нем прожили. Если бы они начали с написания своего маппера, то скорее всего мы бы сейчас не знали про SO.
Считаешь это недостаточная причина использовать в своих проектах Linq2ORM? Ведь многие проекты даже до тысячной части нагрузки SO не доживают.
G>>Надеяться в начале разработки на то, что сразу удастся продумать правильную структуру базы и фиксированные запросы, по меньшей мере глупо. __>По меньшей мере глупо быть дураком и не делать все правильно, в т.ч. и структуру БД и реализовать эффективные запросы. Не умеете, наймите того, кто умеет. Это же просто, следовательно правильно.
Тут не вопрос в умении, а вопрос в знании. Заранее никто не знает что понадобится. Даже самые тяжелые методологии не помогают избежать изменений.
Здравствуйте, QrystaL, Вы писали:
QL>Здравствуйте, Ночной Смотрящий, Вы писали: НС>>BLToolkit QL>Он вроде на основе LINQ-to-SQL сделан? Или нет?
BLToolkit — самостоятельный продукт.
Здравствуйте, a_g_99, Вы писали:
__>Перефразируя классика скажу что "слухи о " полезности LINQ провайдера "сильно преувеличены"
Сказать ты можешь что угодно, но по факту наличие возможности статического контроля запросов компилятором и развитые средства декомпозиции дают вполне неиллюзорные бенефиты. Чтобы от этих бенефитов отказываться нужны железобетонные аргументы.
__>. Я например всегда обходился SQL
А некоторые так вообще голым ассемблером обходились. Это что, аргумент что ли?
__>Парни из stack_overflow тоже похоже с этим не парились когда разрабатывали dapper
Dapper это не ORM. Задачи работы с декларативными запросами и меппера в общем случае непересекающиеся. Т.е. можно использовать LINQ и не использвать меппер, и наоборот.
Здравствуйте, gandjustas, Вы писали:
>>>Я с линком писал такие запросы, что вручную их почти нереально было родить. И эти запросы проверялись при компиляции. __>>Чушь. Ну напишите мне что я "нереально не могу родить" с помощью T-SQL или PL/SQL, что вы можете сделать с помощью LINQ.
G>Да легко:
G>
Здравствуйте, Vaako, Вы писали:
V>Извиняюсь, тут разве не 2 разных LINQ запроса?
Суть и мощь совсем не в том. Вот пример возможно более наглядный: ORM vs Plain SQL: по просьбам трудящихся
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>BLToolkit
Если уж сравнивать легковесный ОРМ с монстром типа EF: как принято выкручиваться с самым простым UI типа "выгреб — прибиндил — отредактировал — сохранил"?
В BLToolkit ведь нет ChangeTracking/ChangeContext-а?
Здравствуйте, Sinix, Вы писали:
S>Если уж сравнивать легковесный ОРМ с монстром типа EF: как принято выкручиваться с самым простым UI типа "выгреб — прибиндил — отредактировал — сохранил"?
EditableObject BLT поддерживает (старая его часть), а всякие lazy loading и identity tracking — весьма спорные технологии. Лично я с удовольствием обхожусь без них при возможности.
S>В BLToolkit ведь нет ChangeTracking/ChangeContext-а?
Искаропки вроде бы нету. Может быть кто прикручивал, но я в старом BLT не слишком хорошо разбираюсь.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>EditableObject BLT поддерживает (старая его часть), а всякие lazy loading и identity tracking — весьма спорные технологии. Лично я с удовольствием обхожусь без них при возможности.
Это не всегда удобно
Самый простой пример — Master-Detail.
Сценарий 1:
Прибиндили на форму с гридом, добавили записи
Сценарий 2:
Передали мастера в метод для заполнения по какому-то шаблону, записи в спецификации удалились/поменялись
Как сохранять изменения в БД? Или имеем промежуточный слой, который отслеживает изменения и прозрачен для БЛ, или нагружаем ответственностью за отслеживание все части приложения.
Достаточно попросить многозвенку, или возможность добавлять записи в нескольких потоков и придётся писать всё, что умеет орм, только ручками.
Здравствуйте, Sinix, Вы писали:
S>Как сохранять изменения в БД?
Отдельный фреймворком, если очень хочется именно такой сценарий. Накапливаем данные в биндинге (иными словами, в UI), на основании накопленных данных и метаданных формируем сразу апдейт или набор DTO для пересылки изменений. При этом, к примеру, появляется возможность оформленные в UI как групповые операции групповыми же выполнять и в БД (скажем, если я жму кнопку "Удалить все", то в БД идет DELETE FROM OrderLine WHERE Order.ID=123, а не куча DELETE FROM OrderLine WHERE ID=XXX).
S> Или имеем промежуточный слой, который отслеживает изменения и прозрачен для БЛ, или нагружаем ответственностью за отслеживание все части приложения.
Этот слой, к сожалению, на практике не совсем прозрачен, потому что все равно в прикладном коде приходится учитывать кучу моментов типа изоляции при параллельной модификации. Слой этот, конечно, нужно делать по возможности прозрачным, но интегрировать его с ORM в неделимое целое совершенно не обязательно.
S>Достаточно попросить многозвенку
Здравствуйте, Vaako, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
>>>>Я с линком писал такие запросы, что вручную их почти нереально было родить. И эти запросы проверялись при компиляции. __>>>Чушь. Ну напишите мне что я "нереально не могу родить" с помощью T-SQL или PL/SQL, что вы можете сделать с помощью LINQ.
G>>Да легко:
G>>
Здравствуйте, gandjustas, Вы писали:
G>Покажи как такое с голым sql сделать.
if (f)
select ... from [Table or Join] where [...].UnitsInStock>0
else
select ... from [Table or Join] group by ... having sum([...].Price * [...].Quantity) > 1000)
Смотрите. И что по вашему прозрачнее?
G>Важно что они с него начали и 2 года на нем прожили. Если бы они начали с написания своего маппера, то скорее всего мы бы сейчас не знали про SO.
Не уверен что это эта тормозная и глючная штука была причиной роста SO. Предположения того что ЭТО увеличивает скорость разработки неверны. Просто на тот момент это казалось модным
G>Считаешь это недостаточная причина использовать в своих проектах Linq2ORM? Ведь многие проекты даже до тысячной части нагрузки SO не доживают.
Я считаю это бессмысленным, т.к. это framework не имеет никаких преимуществ перед обычным Data FCL .Net
G>Тут не вопрос в умении, а вопрос в знании. Заранее никто не знает что понадобится. Даже самые тяжелые методологии не помогают избежать изменений.
Я что не понимаю в какую сторону вы клоните (клонитесь?). Если мне нужно использовать database в проекте я точно знаю, ЧТО мне понадобится и каким образом я буду это реализовать. Does it make sense?
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Сказать ты можешь что угодно, но по факту наличие возможности статического контроля запросов компилятором и развитые средства декомпозиции дают вполне неиллюзорные бенефиты. Чтобы от этих бенефитов отказываться нужны железобетонные аргументы.
Какие аргументы кроме того что ваш код выполняется до обеда? В цифрах пожалуйста.
Я могу выполнить любой запрос с использованием SqlDataReader в несколько раз быстрее, при этом мой код будет проще, яснее и легче в отладке. Вот мой аргумент
НС>А некоторые так вообще голым ассемблером обходились. Это что, аргумент что ли?
Для дураков, которые не знают SQL и вынуждены пользоваться индейскими костылями конечно не аргумент. Для меня аргумент.
Здравствуйте, gandjustas, Вы писали: G>Потому что все сложные запросы в Linq у меня генеряться по частям. Вот одна из таких частей.
Самым главным преимуществом Linq перед Pure SQL для меня является повторное использование кода, т.к. перенос бизнес логики в SQL для меня всегда сопровождался с кромешной копипастой
Здравствуйте, a_g_99, Вы писали:
G>>Если ты не видишь полезности в Linq to database, то это не значит что другие не видят. __>Разве я против? Я же написал "на вкус и цвет товарищей нет".
>>Я с линком писал такие запросы, что вручную их почти нереально было родить. И эти запросы проверялись при компиляции. __>Чушь. Ну напишите мне что я "нереально не могу родить" с помощью T-SQL или PL/SQL, что вы можете сделать с помощью LINQ.
Y>Incorrect syntax near ') динамический sql не предлагать.
declare @filter1 varchar(max)
set @filter1 = 'body'
declare @filter2 varchar(max)
--set @filter2 = '1'select * from settings
where (@filter1 IS NULL OR [Key] = @filter1) AND (@filter2 IS NULL OR [Value] = @filter2)
Здравствуйте, a_g_99, Вы писали:
__>Здравствуйте, gandjustas, Вы писали:
G>>Покажи как такое с голым sql сделать. __>if (f) __>
__>select ... from [Table or Join] where [...].UnitsInStock>0
__>
__>else __>
__>select ... from [Table or Join] group by ... having sum([...].Price * [...].Quantity) > 1000)
__>
__>Смотрите. И что по вашему прозрачнее?
Неверно, какой IQueryable на входи подается — неизвестно, там уже могут быть join и фильтры, на результат также могу быть навешаны дополнительные предикаты.
Во вторых твой код тупо длиннее.
В третьих — код не рабочий, так как превратить три точки в что-то конкретное далеко не тривиально.
G>>Важно что они с него начали и 2 года на нем прожили. Если бы они начали с написания своего маппера, то скорее всего мы бы сейчас не знали про SO. __>Не уверен что это эта тормозная и глючная штука была причиной роста SO. Предположения того что ЭТО увеличивает скорость разработки неверны. Просто на тот момент это казалось модным
Я тоже не уверен что она была причиной роста. Но ручное написание запросов однозначно стало бы причиной фейла.
И таки да — увеличивает скорость разработки в разы. Тупо за счет compile-time check.
G>>Считаешь это недостаточная причина использовать в своих проектах Linq2ORM? Ведь многие проекты даже до тысячной части нагрузки SO не доживают. __>Я считаю это бессмысленным, т.к. это framework не имеет никаких преимуществ перед обычным Data FCL .Net
Как минимум compile time check. Этого уже более чем достаточно, чтобы писать быстрее, чем sql запросы в тексте.
G>>Тут не вопрос в умении, а вопрос в знании. Заранее никто не знает что понадобится. Даже самые тяжелые методологии не помогают избежать изменений. __>Я что не понимаю в какую сторону вы клоните (клонитесь?). Если мне нужно использовать database в проекте я точно знаю, ЧТО мне понадобится и каким образом я буду это реализовать. Does it make sense?
В любом случае ты в начале проекта не сможешь родить схему и все запросы, чтобы они ни разу не изменились.
Здравствуйте, gandjustas, Вы писали:
G>Неверно, какой IQueryable на входи подается — неизвестно, там уже могут быть join и фильтры, на результат также могу быть навешаны дополнительные предикаты. G>Во вторых твой код тупо длиннее. G>В третьих — код не рабочий, так как превратить три точки в что-то конкретное далеко не тривиально.
У меня твердое ощущение, что вы человек исключительно гуманитарного склада ума. Причем в крайней степени (стадии?). По пунктам:
1) Да все равно мне какой IQueryable на вход подается. Вы можете все что угодно там джойнить и выставлять любые SARG во клиентском коде (в N строках кода) — я все равно сделаю все лакончинее и эффективнее Одним запросом
2) Вы рассчитывайте по SARG и все встанет на свои места. Если вы знаете, что такое SARG конечно . Это не говоря уже о сравнении с итоговым SQL то EF.
3) Да что вы такое говорите ? Не собирается в студии ? Вы привели мне пример концептуального кода, я привел вам контрпример. Зачем глупости-то говорить?
G>И таки да — увеличивает скорость разработки в разы. Тупо за счет compile-time check.
Это называется школярское мышление. Вы видимо не можете себе представить, насколько может быть производительным инженер, если он владеет предметной областью.
compile-time check — это суррогат малограмотных идиотов, которые из-за отсутствия системного мышления пересобирают проект каждые 5 секунд в поисках ошибки.
G>Как минимум compile time check. Этого уже более чем достаточно, чтобы писать быстрее, чем sql запросы в тексте.
Для разработки sql-запросов существуют специальные tools, которые позволяют делать это быстро, эффективно и тут реализовать проверки with sql engine. Если вы владеете подобными tools и имеете соответствующий опыт разработки SQL, то вы будете делать это гораздо быстрее чем с помощью какого-то индо-пакистанского костыльного убожества.
G>В любом случае ты в начале проекта не сможешь родить схему и все запросы, чтобы они ни разу не изменились.
А мне и не нужно этого делать. Я достаточно владею SQL, чтобы гибко изменять код и схему в зависимости от измени внутри проекта. Зачем мне для этого этот тормозной костыльный каркас?
Здравствуйте, a_g_99, Вы писали:
__>Здравствуйте, gandjustas, Вы писали:
G>>Неверно, какой IQueryable на входи подается — неизвестно, там уже могут быть join и фильтры, на результат также могу быть навешаны дополнительные предикаты. G>>Во вторых твой код тупо длиннее. G>>В третьих — код не рабочий, так как превратить три точки в что-то конкретное далеко не тривиально. __>У меня твердое ощущение, что вы человек исключительно гуманитарного склада ума. Причем в крайней степени (стадии?).
Да, я понимаю то когда нечего ответить, то можно поискать проблемы в собеседнике.
__>По пунктам: __>1) Да все равно мне какой IQueryable на вход подается. Вы можете все что угодно там джойнить и выставлять любые SARG во клиентском коде (в N строках кода) — я все равно сделаю все лакончинее и эффективнее Одним запросом
Давай вариант попроще:
Количество вариантов запросов на выходе — 6 штук. Вообще если у тебя N то запросов будет N! (факториал).
При этом при изменении одного аспекта тебе надо будет вносить правки в (N-1)! запросов.
При N=5 человек уже не может это делать.
__>2) Вы рассчитывайте по SARG и все встанет на свои места. Если вы знаете, что такое SARG конечно . Это не говоря уже о сравнении с итоговым SQL то EF.
Понятия не имею что такое SARG. Гугл не помог. Скорее всего ты привел эти буквы чтобы казаться умнее. Может ты расскажешь что это?
__>3) Да что вы такое говорите ? Не собирается в студии ? Вы привели мне пример концептуального кода, я привел вам контрпример. Зачем глупости-то говорить?
Мой пример собирается в студии, я только оттуда несущественные детали убрал. Ты же пропустил довольно важные части.
G>>И таки да — увеличивает скорость разработки в разы. Тупо за счет compile-time check. __>Это называется школярское мышление. Вы видимо не можете себе представить, насколько может быть производительным инженер, если он владеет предметной областью.
Это не релевантно, независимо от знания предметной области проверка кода компилятором ускоряет разработку.
__>compile-time check — это суррогат малограмотных идиотов, которые из-за отсутствия системного мышления пересобирают проект каждые 5 секунд в поисках ошибки.
Зачем пересобирать? Студия прямо при вводе показывает несоответствия типов \ опечатки. Причем именно банальные опечатки \ недоисправления после копипасты приводят к большей части ошибок, которые в случае текстового SQL отлавливаются очень сложно.
G>>Как минимум compile time check. Этого уже более чем достаточно, чтобы писать быстрее, чем sql запросы в тексте. __>Для разработки sql-запросов существуют специальные tools, которые позволяют делать это быстро, эффективно и тут реализовать проверки with sql engine. Если вы владеете подобными tools и имеете соответствующий опыт разработки SQL, то вы будете делать это гораздо быстрее чем с помощью какого-то индо-пакистанского костыльного убожества.
Пример? Что ты используешь?
G>>В любом случае ты в начале проекта не сможешь родить схему и все запросы, чтобы они ни разу не изменились. __>А мне и не нужно этого делать. Я достаточно владею SQL, чтобы гибко изменять код и схему в зависимости от измени внутри проекта. Зачем мне для этого этот тормозной костыльный каркас?
Каждое изменение текстового SQL имеет вероятность ошибки. Отсутствие декомпозиции запросов повышает риск получения несогласованных действий.
Здравствуйте, a_g_99, Вы писали:
НС>>Сказать ты можешь что угодно, но по факту наличие возможности статического контроля запросов компилятором и развитые средства декомпозиции дают вполне неиллюзорные бенефиты. Чтобы от этих бенефитов отказываться нужны железобетонные аргументы. __>Какие аргументы
Это ты мне скажи, какие аргументы у тебя оправдывают отказ от линка в пользу собственных велосипедов.
__>Я могу выполнить любой запрос с использованием SqlDataReader в несколько раз быстрее
Ну попробуй, обгони BLT. Результаты объективных замеров показывают, что рукопашный код быстрее больше чем на единицы процентов написать не удается.
__>, при этом мой код будет проще, яснее и легче в отладке.
Ручное чтение из ридела vs linq запрос? Ну ну.
__>Для дураков, которые не знают SQL и вынуждены пользоваться индейскими костылями конечно не аргумент. Для меня аргумент.
При чем тут знание SQL? Линк предназначен вовсе не для тех, кто не знает SQL.
Здравствуйте, QrystaL, Вы писали:
QL>Здесь достаточно интересный проект...
At this moment, and as far as we know, there's no commercial or open source ORM mapper with a full Linq provider apart from Microsoft, LLBLGen and Signum Framework.
Здравствуйте, a_g_99, Вы писали:
__>Перефразируя классика скажу что "слухи о " полезности LINQ провайдера "сильно преувеличены". Я например всегда обходился SQL, там где теоретически возможно использовать LINQ — это было более просто, изящнее и гораздо эффективнее. Парни из stack_overflow тоже похоже с этим не парились когда разрабатывали dapper. Хотя на вкус и цвет товарищей. Пусть те кто хотят использовать технологии MS типа LINQ, "подставляют бокалы, кто пьет такое".
У SQL как у одной из технологий широко используемых сегодня при разработке современных приложений есть одна большая фундаментальная проблема — отсутствие внятной интеграции с языками, которые этот SQL используют. Например, полное отсутсвие типизации, необходимость писать дополнительные слои, для перевода SQL в термины приложения. В результате SQL начинает потихоньку выпадать из технического прогресса и становиться откровенным тормозом. Например, словосочетание "рефакторинг базы данных" для большинства на сегодня фантастика.
Linq эту проблему как-то пытается решить. Другое дело, что существующие провайдеры часть проблем решают, а часть как полагается привносят. Тот же EF больше похож на SQL в железных доспехах, которые делают его с одной стороны неуязвимыми для типизации, с другой настолько сковывают движения, что весь бенефит от такой неуязвимости не просто пропадает, а становится отрицательным.
Ближе всего, на мой нескромный взгляд, к решению типизированного SQL подошёл BLToolkit. Ещё ближе подойдёт linq2db. Но решение близкое к идеальному возможно только на специально обученном DSL.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, a_g_99, Вы писали:
>>Я с линком писал такие запросы, что вручную их почти нереально было родить. И эти запросы проверялись при компиляции. __>Чушь. Ну напишите мне что я "нереально не могу родить" с помощью T-SQL или PL/SQL, что вы можете сделать с помощью LINQ.
Вопрос не в теоретической возможности, а в практической реальности. Ты просто не станешь писать на SQL то, что можно сделать с помощью LINQ. Если ты, конечно, вменяемый разработчик.
Реально сложные запросы на LINQ пишутся как правило в несколько выражений, позволяющих конструировать запрос пошагово. Для plain SQL это делается только с помощью конкатенации строк, что само по себе было проклято ещё теми, кто придумал DAL. Конкатенация/конструирование сложного запроса в LINQ это зачастую даже более предпочтительно, чем написать целый запрос целиком, потому что это более читаемо.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Sinix, Вы писали:
S>Достаточно попросить многозвенку, или возможность добавлять записи в нескольких потоков и придётся писать всё, что умеет орм, только ручками.
Зачем же? T4 в руки и всё захреначим синей изолентой.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, a_g_99, Вы писали:
__>1) Да все равно мне какой IQueryable на вход подается. Вы можете все что угодно там джойнить и выставлять любые SARG во клиентском коде (в N строках кода) — я все равно сделаю все лакончинее и эффективнее Одним запросом
Только при этом задолбаешься пот с лица вытирать.
__>2)Если вы знаете, что такое SARG конечно .
Shelter Animals Rescue Group?
G>>И таки да — увеличивает скорость разработки в разы. Тупо за счет compile-time check. __>Это называется школярское мышление. Вы видимо не можете себе представить, насколько может быть производительным инженер, если он владеет предметной областью. __>compile-time check — это суррогат малограмотных идиотов, которые из-за отсутствия системного мышления пересобирают проект каждые 5 секунд в поисках ошибки.
Таак, пошёл неадекват. Вот оказывается какие они инженеры, владеющие предметной областью.
G>>Как минимум compile time check. Этого уже более чем достаточно, чтобы писать быстрее, чем sql запросы в тексте. __>Для разработки sql-запросов существуют специальные tools, которые позволяют делать это быстро, эффективно и тут реализовать проверки with sql engine.
Ну-ка, назови ка нам, SQL разработчикам с пятидесятилетным стажем хоть один SQL тул, чтобы мы не поржали хотя бы 10 минут.
G>>В любом случае ты в начале проекта не сможешь родить схему и все запросы, чтобы они ни разу не изменились. __>А мне и не нужно этого делать. Я достаточно владею SQL, чтобы гибко изменять код и схему в зависимости от измени внутри проекта. Зачем мне для этого этот тормозной костыльный каркас?
Тебе стоит поделится своей технологий разработки с общественностью. Если всё так как ты рассказываешь, то номинирование на Нобелевку гарантирую.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Ближе всего, на мой нескромный взгляд, к решению типизированного SQL подошёл BLToolkit. Ещё ближе подойдёт linq2db. Но решение близкое к идеальному возможно только на специально обученном DSL.
Кстати, linq2db теперь полностью на C#? Так и дальше будет?
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>А ты когда на него смотрел последний раз? IB>Месяц назад, примерно. Как был недоделком, так и остался.
Точно? То что ты описываешь было актуально около 2 лет назад.
Здравствуйте, IT, Вы писали:
IT>Только при этом задолбаешься пот с лица вытирать.
Зато это работает. Быстро. Для этого и нужен мозг вы не находите ?
IT>Shelter Animals Rescue Group?
В точку! Именно так! Как вы догадались? Как я сам ранее не догадался???
IT>Таак, пошёл неадекват. Вот оказывается какие они инженеры, владеющие предметной областью.
А что вас смущает? Или вы удивлены тем что есть еще люди, за которых VS не думает ?
IT>Ну-ка, назови ка нам, SQL разработчикам с пятидесятилетным стажем хоть один SQL тул, чтобы мы не поржали хотя бы 10 минут.
Да мы сами с усами вообще-то .
1) Для Sql Server я использую Query Analyzer если это возможно. Ну и SSMS, когда приходится.
2) Для Oracle Sql*Plus & Oracle SQL Developer
Начинайте ржать (кукарекать я думаю необязательно)
IT>Тебе стоит поделится своей технологий разработки с общественностью. Если всё так как ты рассказываешь, то номинирование на Нобелевку гарантирую.
По шагам сложно, но я попробую. Нужно например расширить таблицу, я исполняю ALTER TABLE. Нужно добавить логику в sp — аналогично меняю sp. Требуется поменять код в соответствии с DL — меняю. Это называется — разработка программного обеспечения. Слышали про такой термин?
Это кстати просто — на нобелевскую премию ну никак не тянет.
Здравствуйте, a_g_99, Вы писали:
IT>>Только при этом задолбаешься пот с лица вытирать. __>Зато это работает. Быстро. Для этого и нужен мозг вы не находите ?
Для того, чтобы вытирать пот с лица нужен платок, а не мозг. Мозгом это делать не удобно.
Что касается быстроты, то по этой ветке выше давали пример где как раз переписывание прямого SQL на LINQ дало прирост производительности на порядки. Догадаешься почему?
IT>>Таак, пошёл неадекват. Вот оказывается какие они инженеры, владеющие предметной областью. __>А что вас смущает? Или вы удивлены тем что есть еще люди, за которых VS не думает ?
Я удивлён, что во времена, когда есть автомобили? некоторые считают, что передвижение на телеге предпочтительней.
IT>>Ну-ка, назови ка нам, SQL разработчикам с пятидесятилетным стажем хоть один SQL тул, чтобы мы не поржали хотя бы 10 минут. __>Да мы сами с усами вообще-то . __>1) Для Sql Server я использую Query Analyzer если это возможно. Ну и SSMS, когда приходится. __>2) Для Oracle Sql*Plus & Oracle SQL Developer __>Начинайте ржать (кукарекать я думаю необязательно)
Ржунимагу. Query Analyser существует правктически в неизменном виде уже лет 15. После разбора полётов в нём оптимизация запросов сводится как правило к двум вещам: либо в 80% случаев к обновлению статистики (но при чём тут тогда LINQ?), либо к устранению извращений, которые на LINQ написать значительно сложнее. Если ты так и не догадался почему в примере в этой ветке LINQ работает быстрее, чем прямой SQL, то даю подсказку — переписывание запроса на LINQ позводлило устранить все извращения в запросе, легко и просто поэкспериментировать с разными вариантами и выбрать наилучший. Кстати, при этом QA довольно эффективно использовался. Да-да, а ты думал планы запросов могут читать только те, кто самолично своими руками выпиливает в коде волшебное слово "SELECT"?
IT>>Тебе стоит поделится своей технологий разработки с общественностью. Если всё так как ты рассказываешь, то номинирование на Нобелевку гарантирую. __>По шагам сложно, но я попробую. Нужно например расширить таблицу, я исполняю ALTER TABLE. Нужно добавить логику в sp — аналогично меняю sp. Требуется поменять код в соответствии с DL — меняю. Это называется — разработка программного обеспечения. Слышали про такой термин?
Это называется косностью мышления. Слышали про такой термин? Эффективная разработка программного обеспечения подразумевает не только знание инструментов 15-ти летней давности, но и владение современными технологиями и, что ещё важнее, умение их использовать, а в идеале понимание причин по которым они появились. Впрочем с последним сложнее, сначала нужно одолеть предыдущий пункт.
__>Это кстати просто — на нобелевскую премию ну никак не тянет.
Кто бы сомневался. Это не тянет вообще ни на какую премию, даже на квартальную.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Что касается быстроты, то по этой ветке выше давали пример где как раз переписывание прямого SQL на LINQ дало прирост производительности на порядки. Догадаешься почему?
Не догадаюсь. Объясните дураку? Прежде не забудьте посмотреть на тесты производительности dapper между SqlDataReader, NHibernate, EF. Чтобы не ошибиться в объяснениях.
IT>Я удивлён, что во времена, когда есть автомобили? некоторые считают, что передвижение на телеге предпочтительней.
Исходя из Вашей аллегории, ваш автомобиль Медленнее телеги в 3-6 раз минимум. У меня сразу возникает вопрос, что тут автомобиль а что телега?
IT>Ржунимагу. Query Analyser существует правктически в неизменном виде уже лет 15. После разбора полётов в нём оптимизация запросов сводится как правило к двум вещам: либо в 80% случаев к обновлению статистики (но при чём тут тогда LINQ?), либо к устранению извращений, которые на LINQ написать значительно сложнее.
Что за глупость. Вы точно владеете optimization skills & SQL refactoring для modern серверов большой тройки (я владею только Sql Server & Oracle)? Обновление статистики в 80% случаев? Я все эти годы использовал сложные методы построения индексов/битовых карт в зависимости от различных факторов (селективности, стратегий соединения), рефакторил SQL по SARG/GROUP_BY исходя из планов исполнения, статы по физич./логическим чтениям и т.д. А всего-то надо было статистику обновлять ?
IT>Если ты так и не догадался почему в примере в этой ветке LINQ работает быстрее, чем прямой SQL, то даю подсказку — переписывание запроса на LINQ позводлило устранить все извращения в запросе, легко и просто поэкспериментировать с разными вариантами и выбрать наилучший. Кстати, при этом QA довольно эффективно использовался. Да-да, а ты думал планы запросов могут читать только те, кто самолично своими руками выпиливает в коде волшебное слово "SELECT"?
О каких извращениях идет речь? Приведите пример запроса-"извращения".
Ну да это отличная идея — build application каждый раз и смотреть что там понаделал этот костыльный уродец-фрэймворк. Это сколько же вы времени тратите на оптимизационные процессы? По полгода?
IT>Это называется косностью мышления. Слышали про такой термин? Эффективная разработка программного обеспечения подразумевает не только знание инструментов 15-ти летней давности, но и владение современными технологиями и, что ещё важнее, умение их использовать, а в идеале понимание причин по которым они появились. Впрочем с последним сложнее, сначала нужно одолеть предыдущий пункт.
Эффективная разработка программного обеспечения подразумевает знание frameworks для доставки features для customer. Если фича работает крайне медленно, то фича не доставлена кастомеру. Каким бы не был новым такой framework он бесполезен для разработчика.
Используя вашу аллегорию — представьте что вы покупаете новый красивый авто, но внутри не ДВС а велосипедные педали, а руль уже заранее отвалился. Готовы вы использовать такой продукт? Сомневаюсь. Хороший пример — ObjectSpaces.Net. Тоже бы новейший продукт, и где он теперь?
Не зацикливайтесь на одних продуктах MS & .Net, как 18-летний юноша. Мыслите шире, выбирайте лучшие решения для своего кастомера на MS, Oracle, Linux, C++. Именно тогда вы будете эффективны как разработчик и сможете похвастать "некостностью" мышления.
IT>Кто бы сомневался. Это не тянет вообще ни на какую премию, даже на квартальную.
Ну откуда же вам знать? Вы же не цыганка.
Здравствуйте, a_g_99, Вы писали:
IT>>Что касается быстроты, то по этой ветке выше давали пример где как раз переписывание прямого SQL на LINQ дало прирост производительности на порядки. Догадаешься почему? __>Не догадаюсь. Объясните дураку? Прежде не забудьте посмотреть на тесты производительности dapper между SqlDataReader, NHibernate, EF. Чтобы не ошибиться в объяснениях.
Ну по поводу dapper-а, это какая-то массовая истерия вокруг него разбредается по интернетам. Ну сделали крутые перцы себе ровно то что они хотели — но они далеко не единственные в мире, кто умеет писать на C#.
1. Dapper это прежде всего маппер и экстеншн методы вокруг ADO.NET.
2. Многим человекам этого просто недостаточно, т.к. вокруг ADO.NET нужна ещё вменяемая контроллируемая обвязка.
3. Данные тестов сильно устарели.
4. Одни и те же тесты банально выполняют разные действия.
5. Ещё есть мелкие описки в тестах, кардинально влияющие на результаты.
Running 500 iterations that load up a post entity
hand coded took 164ms
OrmLite QueryById took 175ms // а ребята из ServiceStack всё таки молодцы :)
DataTable via IDataReader.GetValues took 178ms
Mapper Query (buffered) took 182ms
Dynamic Mapper Query (buffered) took 184ms
Dapper.Cotrib took 187ms
PetaPoco (Normal) took 191ms
PetaPoco (Fast) took 191ms
Dynamic Massive ORM Query took 193ms
BLToolkit LINQ (CompiledQuery) took 195ms
BLToolkit ExecuteObject took 211ms
BLToolkit ExecuteList took 216msDynamic Mapper Query (non-buffered) took 222ms
Mapper Query (non-buffered) took 237ms
Linq 2 SQL Compiled took 258ms
Simple.Data took 299ms
BLToolkit LINQ took 310ms
SubSonic Coding Horror took 354ms
NHibernate Session.Get took 368ms
NHibernate SQL took 393ms
NHibernate HQL took 418ms
Entity framework CompiledQuery took 439ms
Soma took 452ms
NHibernate Criteria took 481ms
Linq 2 SQL ExecuteQuery took 509ms
Entity framework No Tracking took 568ms // EntityFramework версия 4 - старовато.
Entity framework took 573ms
Entity framework ESQL took 576ms
Linq 2 SQL took 1218ms
Entity framework ExecuteStoreQuery took 1306ms
NHibernate LINQ took 1334ms
SubSonic ActiveRecord.SingleOrDefault took 6436ms
(end of tests; press any key)
Интересные тесты выделены жирным.
Выводы:
1. Тест Dynamic Mapper Query (non-buffered) эквивалентен тесту BLToolkit ExecuteList — и время выполнения у них одинаковое.
2. На микровытаскиваниях микрообъектов Dapper или OrmLite может дать небольшой выигрыш в скорости.
3. Но этот выигрыш скорости незначителен по сравнению с BLToolkit LINQ Compiled Query, хотя тут всё таки уже LINQ.
А вообще — разница во всём этом настолько ничтожна, что на любом запросе чуть-чуть посложнее да на базе поболее — это станет невидимой шелухой.
Поэтому — ну хочется — тренируйтесь в эффективном маппинге. Ещё лучше hand coded маппинг делать — он самый быстрый.
Ну а веткой выше было не про маппинг, а человеческое написание запросов. И то что LINQ позволяет это сделать без написания уродливых SQL запросов, которые из-за этого исполняются с неэффективным планом, и прочих "вкусностей". А возможности комбинирования позволяют избавится от тупой копипасты в SQL.
Здравствуйте, fddima, Вы писали:
F>1. Тест Dynamic Mapper Query (non-buffered) эквивалентен тесту BLToolkit ExecuteList — и время выполнения у них одинаковое.
Очепятка — вместо выделенного нужно смотреть на Mapper Query (non-buffered) (он в таблице сразу под выделенным).
Здравствуйте, IT, Вы писали:
IT>Текущий C# от N не выдержал моих извращений и пошёл подумать над своим поведением
Не будете ли вы любезны описать причины?
По мне паттерн-матчинг куда гуманее визиторов. Н или так какой Фшарп сильно сократили бы количество усилий.
Так почему же не они?
Здравствуйте, Flem1234, Вы писали:
IT>>Текущий C# от N не выдержал моих извращений и пошёл подумать над своим поведением F>Не будете ли вы любезны описать причины?
Мы с Владом практически довели N и linq2db (точнее на тот момент это был просто клон BLToolkit) до состояния компилируемости. Некоторые вещи правда пришлось переписать, чтобы N их понимал, но это всё мелочи. Влад в результате довёл поддержку C# в N до более менее приемлемого уровня, но случилась одна неприятная засада. Вот в этом файле задан маппинг стандартных фрейморковских методов на различные диалекты SQL. Это несколько сот пар лямбд. После того как проект начал компилироваться оказалось, что N его компилирует больше двух минут. Раньше на этом файле и решарпер существенно притормаживал, но потом в нём видимо что-то подкрутили. Так вот. Две минуты — это приговор. C# на это тратит не более 10 секунд. Влад предложил в качестве решения разбить проект на две части, одну писать на N, а вторую на C# и вынести туда все подобные штуки. Я в свою очередь предложил такую фигню мне не предлагать, т.к. это не соответсвует моему чуткому восприятию прекрасного окружающей действительности.
Всё это мы затеяли в рамках подготовки к конференции в Осло, а время поджимало. В результате мы решили всё это отложить на потом. А потом N перешёл в режим разработки новой версии, ускорять его сейчас никто не соберается, да и мне смысла писать что-то под старую версию особого нет. Что-то рабочее по словам разработчиков появится не раньше, чем через год, а linq2db итак уже застоялся на запасном аэродроме и дальшейший простой может убить саму идею. Так что либо писать его на C# и сейчас, либо забить на это дело совсем.
К тому же для реализации полноценного функционала мне нужна поддержка генерации кода под Silverlight, которой в N нет и опять же неизвестно когда будет.
F>По мне паттерн-матчинг куда гуманее визиторов. Н или так какой Фшарп сильно сократили бы количество усилий. F>Так почему же не они?
ПМ рулит со страшной силой. Я бы легко на порядок увеличил количество оптимизаций генерируемого SQL, которые сейчас есть. Но пока видимо не судьба.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, a_g_99, Вы писали:
IT>>Что касается быстроты, то по этой ветке выше давали пример где как раз переписывание прямого SQL на LINQ дало прирост производительности на порядки. Догадаешься почему? __>Не догадаюсь. Объясните дураку?
Объясняю. Но для начала бородатый анекдот.
Приходит сын к отцу-программисту:
– Папа, а почему солнце всходит на востоке, а заходит на западе?
– Ты проверял?
– Да…
– Каждый день всходит?
– Да, и каждый день заходит…
– СЫНОК! НИЧЕГО НЕ ТРОГАЙ!!!
Так вот. Есть такая штука — сложность разработки и сопровождения ПО. А писать и сопровождать SQL в разы сложнее, чем типизированный код. В результате проще не трогать то, что каждый день хоть как-то всходит и заходит. Но переписать это на Linq оказалось делом 20-ти минут. Ну может ещё столько же на анализ планов и эксперименты с производительностью запросов.
__>Прежде не забудьте посмотреть на тесты производительности dapper между SqlDataReader, NHibernate, EF. Чтобы не ошибиться в объяснениях.
Это синтетические тесты для наивных юношей. Да, dapper быстр и что с того? SqlDataReader ещё быстрее. Что касается EF, то это, конечно же, редкосный тормоз. Т.е. не dapper быстр, а EF жутко медленен. Разницу понимаешь?
Объясняю как пишутся такие тесты. Берётся максимально примитивнейший запрос, по минимуму нагружающий БД, и, фактически замеряется работа клиентской части, которая в dapper'е эффективна за счёт своего примитивизма. Ты вообще в курсе функциональных возможностей dapper? Теперь берём среднестатистический запрос к БД и прогоняем тот же тест. В результате EF по-проежнему будет тормозить, потому что тормоз по жизни, но по сравнению с другими решениями преимущество dapper в производительности начинет потихоньку растворяться. А после его использования в реальных, опять же, среднестатистических приложениях его производительность вообще перестаёт играть какую-то роль, но зато начинает серьёзно сказываться отсутствие необходимой функциональности.
Конечно, напрашивается вопрос: а что в SO совсем идиоты и этого не понимают? Всё они понимают. Только у любой задачи есть три проблемы, одной из которых приходится жертвовать: цена, качество, сроки. Ценой в SO пожертвовали. Вот и вся разгадка. Если можно поднять производительность на несколько процентов, то им плевать на то, сколько разработчиков будут сначала выпиливать, а потом поддерживать прямой SQL. И я их прекрасно понимаю. С их нагрузками производительность у них на первом месте. Гугль вон вообще из-за этого свою базу данных написал.
IT>>Я удивлён, что во времена, когда есть автомобили? некоторые считают, что передвижение на телеге предпочтительней. __>Исходя из Вашей аллегории, ваш автомобиль Медленнее телеги в 3-6 раз минимум. У меня сразу возникает вопрос, что тут автомобиль а что телега?
Если ты конкретно про EF, то это не автомобиль. Это ошибка мироздания. Продукт кривомозгих архитекторов, загубивших в своё время не один проект в MS и приложивших руку даже к дискредитации .NET при попытке его использония в Longhorn. Даже отданный им на откуп Linq 2 SQL с каждой новой версией работает всё медленнее и медленне, хотя казалось бы всё должно быть совсем наоборот. Если бы орлы из команды NH так не тормозили с реализацией Linq провайдера для NH, то EF мог бы вообще не взлететь.
Для всего остального можно посмотреть раскладку производительности здесь. Результаты немного устаревшие, но тем не менее видно, что даже на этих синтетических тестах для некоторых Linq решений прямой SQL даёт прибавку всего в 30%, а не в 3-6 раз минимум. При усложнении запросов это сведётся к нескольким процентам, а при конструировании реально сложных запросов Linq может дать выигрышь за счёт оптимизаций, которые человек просто поленится делать. Хотя всё это касается не всех Linq провайдеров.
IT>>Ржунимагу. Query Analyser существует правктически в неизменном виде уже лет 15. После разбора полётов в нём оптимизация запросов сводится как правило к двум вещам: либо в 80% случаев к обновлению статистики (но при чём тут тогда LINQ?), либо к устранению извращений, которые на LINQ написать значительно сложнее. __>Что за глупость. Вы точно владеете optimization skills & SQL refactoring для modern серверов большой тройки (я владею только Sql Server & Oracle)? Обновление статистики в 80% случаев? Я все эти годы использовал сложные методы построения индексов/битовых карт в зависимости от различных факторов (селективности, стратегий соединения), рефакторил SQL по SARG/GROUP_BY исходя из планов исполнения, статы по физич./логическим чтениям и т.д. А всего-то надо было статистику обновлять ?
Ключевое слово я выделил. 'Рефакторил' в данном контексте означает ни что иное как устранял глупости, археологические наслоения в коде и последсвия роста объёма БД. За базой данных надо следить практически как за домашним животным, постоянно её лелеять и периодически не забывать подсыпать корм в миску. Это как раз нормально. Не нормально, когда этим занимаешься постоянно и непрерывно. Это говорит о запутанности и сильной связности решения. Подправил в одном месте, что-то упало в другом.
__>О каких извращениях идет речь? Приведите пример запроса-"извращения".
Да их тысячи. Посмотри у себя что ты там рефакторишь. Например, вот один из часто исползуемых приёмов, который легко устраняется с помощью Linq:
SELECT ...
WHERE @param IS NULL OR FieldX = @param
Это называется захардкоженный императивный IF в декларативный SQL.
А вот как это решается на Linq:
var query = ...
if (@param != null)
query = query.Where(t => t.FieldX == @param);
В результате имеем чистенький и наиболее оптимальный SQL для разных видов запросов.
__>Ну да это отличная идея — build application каждый раз и смотреть что там понаделал этот костыльный уродец-фрэймворк. Это сколько же вы времени тратите на оптимизационные процессы? По полгода?
Ты видимо переоптимизировался процессов. Неужели всё так плохо? У меня после завершения работы над каким-либо функционалом, требующем доступа к БД, на анализ запросов уходит пара минут. Это может быть после нескольких часов работы. В 99% случаев проблем вообще никаких не возникает.
IT>>Это называется косностью мышления. Слышали про такой термин? Эффективная разработка программного обеспечения подразумевает не только знание инструментов 15-ти летней давности, но и владение современными технологиями и, что ещё важнее, умение их использовать, а в идеале понимание причин по которым они появились. Впрочем с последним сложнее, сначала нужно одолеть предыдущий пункт. __>Эффективная разработка программного обеспечения подразумевает знание frameworks для доставки features для customer. Если фича работает крайне медленно, то фича не доставлена кастомеру. Каким бы не был новым такой framework он бесполезен для разработчика.
Золотые слова.
__>Используя вашу аллегорию — представьте что вы покупаете новый красивый авто, но внутри не ДВС а велосипедные педали, а руль уже заранее отвалился. Готовы вы использовать такой продукт? Сомневаюсь. Хороший пример — ObjectSpaces.Net. Тоже бы новейший продукт, и где он теперь?
Теперь это EF!!! ТА-ДА!!! После неудачной попытки запихать его в Longhorn и провала проекта в целом, команда, делавшая ObjectSpaces занялась разработкой EF. Результат был в общем-то предсказуем.
__>Не зацикливайтесь на одних продуктах MS & .Net, как 18-летний юноша. Мыслите шире, выбирайте лучшие решения для своего кастомера на MS, Oracle, Linux, C++. Именно тогда вы будете эффективны как разработчик и сможете похвастать "некостностью" мышления.
Я могу похвастаться даже большим. Лучшие решения для своих кастомеров я не просто выбираю, а создаю сам. Если не я, то кто? (печально вздыхает...)
IT>>Кто бы сомневался. Это не тянет вообще ни на какую премию, даже на квартальную. __>Ну откуда же вам знать? Вы же не цыганка.
Неужели тянет?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>ПМ рулит со страшной силой. Я бы легко на порядок увеличил количество оптимизаций генерируемого SQL, которые сейчас есть. Но пока видимо не судьба.
Сделай внутри оптимизатора extension point и напиши продвинутые расширения на немерлах отдельно. Или на F#.
Здравствуйте, Ночной Смотрящий, Вы писали:
IT>>ПМ рулит со страшной силой. Я бы легко на порядок увеличил количество оптимизаций генерируемого SQL, которые сейчас есть. Но пока видимо не судьба. НС>Сделай внутри оптимизатора extension point и напиши продвинутые расширения на немерлах отдельно. Или на F#.
Для этого надо затачивать SQL Builder под ПМ. Хотя идея интересная.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Сделай внутри оптимизатора extension point и напиши продвинутые расширения на немерлах отдельно. Или на F#.
Впрочем, этих точек там уже в количестве.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Так вот. Есть такая штука — сложность разработки и сопровождения ПО. А писать и сопровождать SQL в разы сложнее, чем типизированный код. В результате проще не трогать то, что каждый день хоть как-то всходит и заходит. Но переписать это на Linq оказалось делом 20-ти минут. Ну может ещё столько же на анализ планов и эксперименты с производительностью запросов.
Откуда такая боязнь SQL? Т.е. конечно, вы правы это сложнее чем какая-то упрощенная бангладешская генерилка/обертка, но в руках опытного профессионала он дает вам максимальную производительности и почти все возможности используемого database engine. Может вам на курсы следует походить, чтобы преодолеть свои страхи? В NY кстати неплохие курсы по Oracle есть.
IT>Это синтетические тесты для наивных юношей. Да, dapper быстр и что с того? SqlDataReader ещё быстрее. Что касается EF, то это, конечно же, редкосный тормоз. Т.е. не dapper быстр, а EF жутко медленен. Разницу понимаешь?
Сэр, я открою вам страшную тайну. Я dapper в жизни не пользовал. Просто привел его в качестве успешного примера микро OM. Мой выбор SqlDataReader + собственный DL. Но с вами согласен на 100% в вашей формулировке — ef жутко медленный. Продукт не работает out-of-box. Это уже не исправить. Поэтому не могу рекомендовать это поделие в качестве data lib кому бы то ни было .
IT>Конечно, напрашивается вопрос: а что в SO совсем идиоты и этого не понимают? Всё они понимают. Только у любой задачи есть три проблемы, одной из которых приходится жертвовать: цена, качество, сроки. Ценой в SO пожертвовали. Вот и вся разгадка. Если можно поднять производительность на несколько процентов, то им плевать на то, сколько разработчиков будут сначала выпиливать, а потом поддерживать прямой SQL. И я их прекрасно понимаю. С их нагрузками производительность у них на первом месте. Гугль вон вообще из-за этого свою базу данных написал.
Это проблема любого principal developer. Нет если вы конечно разрабатываете сайт кошачьего корма для 10 кастомеров, то вам наверное все равно — часом больше или часом меньше будет выполняться ваш запрос. Но если вы разрабатываете ПО для какого-нибудь инвестбанка или highload web app, вам нужна исходная производительность и возможность масштабирования — и SQL + dbnetlib вам ее предоставят. А ef как мы с вами уже выяснили не может тупо оптимально работать из коробки.
IT>Если ты конкретно про EF, то это не автомобиль. Это ошибка мироздания. Продукт кривомозгих архитекторов, загубивших в своё время не один проект в MS и приложивших руку даже к дискредитации .NET при попытке его использония в Longhorn. Даже отданный им на откуп Linq 2 SQL с каждой новой версией работает всё медленнее и медленне, хотя казалось бы всё должно быть совсем наоборот. Если бы орлы из команды NH так не тормозили с реализацией Linq провайдера для NH, то EF мог бы вообще не взлететь.
Так и я категорически против ! Вот видите мы же с вами соратники
IT>Ключевое слово я выделил. 'Рефакторил' в данном контексте означает ни что иное как устранял глупости, археологические наслоения в коде и последсвия роста объёма БД. За базой данных надо следить практически как за домашним животным, постоянно её лелеять и периодически не забывать подсыпать корм в миску. Это как раз нормально. Не нормально, когда этим занимаешься постоянно и непрерывно. Это говорит о запутанности и сильной связности решения. Подправил в одном месте, что-то упало в другом.
Это реальная жизнь . Часто databases поддерживаются и дорабатываются десятки лет, кочуют из версий в версии и используются десятками и сотнями различных приложений. Люди приходят и уходят, код остается. Важно иметь методику поддержки таких архитектурных решений с возможностью улучшения параметров ПО (производительности, качества кода и т.п.). И здесь очень важно иметь глубокие знания SQL basically и продукта конкретно. ef скорее всего исчезнет в ближайшие 3-4 года но SQL будет существовать еще очень долго.
IT>Ты видимо переоптимизировался процессов. Неужели всё так плохо? У меня после завершения работы над каким-либо функционалом, требующем доступа к БД, на анализ запросов уходит пара минут. Это может быть после нескольких часов работы. В 99% случаев проблем вообще никаких не возникает.
Вы просто не представляете масштабы databases, с которыми приходилось работать. Внутри целые массивы legacy SQL code которые требуется улучшить, доработать и т.д. Иногда на анализ и дальнейшую оптимизацию с учетом всех факторов уходят недели. Самому аж страшно . И так все плохо, а вы еще костыльный тормозной фрэймворк предлагаете пользовать
IT>Неужели тянет?
Поживем, увидим.
Здравствуйте, a_g_99, Вы писали:
IT>>Так вот. Есть такая штука — сложность разработки и сопровождения ПО. А писать и сопровождать SQL в разы сложнее, чем типизированный код. В результате проще не трогать то, что каждый день хоть как-то всходит и заходит. Но переписать это на Linq оказалось делом 20-ти минут. Ну может ещё столько же на анализ планов и эксперименты с производительностью запросов. __>Откуда такая боязнь SQL?
Откуда такие домыслы про такую боязнь? Или это уже включился режим демагогии?
__>Т.е. конечно, вы правы это сложнее чем какая-то упрощенная бангладешская генерилка/обертка, но в руках опытного профессионала он дает вам максимальную производительности и почти все возможности используемого database engine. Может вам на курсы следует походить, чтобы преодолеть свои страхи? В NY кстати неплохие курсы по Oracle есть.
Да, похоже точно включился. А жаль.
__>Сэр, я открою вам страшную тайну. Я dapper в жизни не пользовал. Просто привел его в качестве успешного примера микро OM.
Пастернака не читал, но одобряю — это что-то новенькое. Успешность dapper — это на 99% успешность StackOverflow и лишь 1% неплохая реализация. Уверен, что таких дапперов по репозиториям исходников разных компаний валяется сотни.
__>Это проблема любого principal developer. Нет если вы конечно разрабатываете сайт кошачьего корма для 10 кастомеров, то вам наверное все равно — часом больше или часом меньше будет выполняться ваш запрос. Но если вы разрабатываете ПО для какого-нибудь инвестбанка или highload web app, вам нужна исходная производительность и возможность масштабирования — и SQL + dbnetlib вам ее предоставят.
Непременная нужность исходной производительности — это заблуждение. Нужно адекватное соотношение цены, качества и сроков разработки. Производительность имеет отношение только к одной части — качеству. Пожертвовать несколькими процентами производительности ради существенного улучшения соотношения цены/сроков вполне разумное решение в подавляющем большинстве случаев. Тем более, что на практике оказывается, что никакого падения производительности и нет, а вполне можно получить прирост за счёт использования более выразительных и высокоуровневых средств, что высвободит время на более качественную проработку дизайна.
__>Так и я категорически против ! Вот видите мы же с вами соратники
С EF проблем нет, но ты начал клеймить Linq, а это вообще-то не одно и то же. Более того, в EF пренебрегли всем, чем только можно пренебречь. Например, за каким-то фигом они продублировали все методы из Queriable и написали свои реализации. Козлы, короче.
IT>>Ключевое слово я выделил. 'Рефакторил' в данном контексте означает ни что иное как устранял глупости, археологические наслоения в коде и последсвия роста объёма БД. За базой данных надо следить практически как за домашним животным, постоянно её лелеять и периодически не забывать подсыпать корм в миску. Это как раз нормально. Не нормально, когда этим занимаешься постоянно и непрерывно. Это говорит о запутанности и сильной связности решения. Подправил в одном месте, что-то упало в другом. __>Это реальная жизнь .
Это не жизнь, это привычка так жить.
__>Часто databases поддерживаются и дорабатываются десятки лет, кочуют из версий в версии и используются десятками и сотнями различных приложений. Люди приходят и уходят, код остается. Важно иметь методику поддержки таких архитектурных решений с возможностью улучшения параметров ПО (производительности, качества кода и т.п.). И здесь очень важно иметь глубокие знания SQL basically и продукта конкретно.
Всё это мы проходили. Это бег по кругу, от бага к багу, от проблемы к проблеме. После того как мой текущий проект погрязв таких вот "методиках поддержки архитектурных решений" было принято решение в пользу перехода на Linq (заметь, не на EF) и тотального отказа от прямого SQL, включая сохранённые процедуры. Всё что нужно было переписано и в результате — "методики", "улучшения параметров", "постоянное копание в SQL овне", вы где? Аууу!
Я ожидал положительного эффекта, но результат превзошёл все ожидания. Если раньше соотношение зартрат в разработке UI/Server+DB было где-то 70/30 при разработке и 30/70 при сопровождении и доработках, то теперь это соотношение 95/5 в обоих случаях. И всё это результат перехода на типизированный SQL.
__>ef скорее всего исчезнет в ближайшие 3-4 года но SQL будет существовать еще очень долго.
Не исчезнет. Инертность мышления, знаете ли, очень забавная штука.
__>Вы просто не представляете масштабы databases, с которыми приходилось работать. Внутри целые массивы legacy SQL code которые требуется улучшить, доработать и т.д. Иногда на анализ и дальнейшую оптимизацию с учетом всех факторов уходят недели. Самому аж страшно . И так все плохо, а вы еще костыльный тормозной фрэймворк предлагаете пользовать
Я как раз не предлагаю использовать EF. Сам я его внимательно поизучал, и именно по этой причине никогда в реальных проектах не использовал. Кроме EF есть другие вполне приемлемые решения.
Если нам не помогут, то мы тоже никого не пощадим.
R>Выскажите пожалуйста свои мнения!
Формируемые запросы не оптимальны.
Сложные запросы превращаются в нечитабельную кашу.
Грабли с ключами для представлений, если не обратить вовремя внимание, то глюки вылазят весьма странные.
Нет пакетного удаления.
Мало реализованных стандартных функций sql.
Использую только для простых запросов, или когда лень создавать еще одно представление.
Здравствуйте, namespace, Вы писали:
R>>Выскажите пожалуйста свои мнения! N>Формируемые запросы не оптимальны. N>Сложные запросы превращаются в нечитабельную кашу. N>Грабли с ключами для представлений, если не обратить вовремя внимание, то глюки вылазят весьма странные. N>Нет пакетного удаления. N>Мало реализованных стандартных функций sql.
N>Использую только для простых запросов, или когда лень создавать еще одно представление.
Здравствуйте, Ночной Смотрящий, Вы писали:
H>>Вообще-то немерлевый умеет иерархии классов ПМить за вычетом контроля полноты НС>Без контроля полноты проку от ПМ не очень много.
Для эвристик контроль полноты не нужен. Там если не нашёл паттерн, то и фиг с ним. А вот выразительность ПМ крайне критична.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, hardcase, Вы писали:
H>>Вообще-то немерлевый умеет иерархии классов ПМить за вычетом контроля полноты
НС>Без контроля полноты проку от ПМ не очень много.
Как ты по открытой иерархии классов полноту-то проверишь?
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
G>>Гы. А говорил что смотрел недавно совсем А по сути не туда смотрел.
НС>IB и IT это разные люди.
Точно, надо перестать на форумах в час ночи сидеть.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Так я и не предлагаю ее проверять. Просто без такой проверки ПМ из мегавещи превращается во вполне обыденный синтаксический сахарок.
Тем не менее он очень неслабо сокращает количество говнокода.
Здравствуйте, gandjustas, Вы писали:
G>Можно прямо сейчас посмотреть на http://entityframework.codeplex.com/ — много нового для себя откроешь про EF.
Ничего нового, те же проблемы в тех же местах.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, Serginio1, Вы писали:
S>>Кстати а не пробовал EF 5.0 IB>Как был отстоем, так и остался, там врожденные генетические проблемы.
можно их список?
сейчас выбираю между им и не им, и было бы очень интересно услышать аргументы...
Здравствуйте, Enomay, Вы писали:
E>можно их список?
Я уже писал недавно. В краце, POCO на самом деле нефига не POCO, LazyLoading хрен отключишь, Linq провайдер мало того что неполноценный и половину нормальных запросов не поддерживает, так еще и запросы генерит хуже чем старый-добрый Linq2SQL.
И, самое главное, корень всех этих проблем в том, что идеологически он так и остался монструозным Full Blown ORM, непонятно для каких задач предназначенным, который внутри себя строит некоторую абстрактную модель и всю работу делает через нее.
E>сейчас выбираю между им и не им, и было бы очень интересно услышать аргументы...
его не советую.
а ссылку не подскажите?
IB>В краце, POCO на самом деле нефига не POCO,
в каком смысле? имется в виду что он возвращает класс наследник от POCO?
IB>LazyLoading хрен отключишь,
я его не трогал, но у меня по умолчанию он не работает.
IB>Linq провайдер мало того что неполноценный и половину нормальных запросов не поддерживает,
в каком смысле не полноценный? слишком извращенных запросов не писал, но интерестно, с чем возможно придется столкнуться.
IB>так еще и запросы генерит хуже чем старый-добрый Linq2SQL.
я смотрел местами он запросы генерирует лучше чем linq2sql. однако же linq2sql всё же удобнее бывает так как лучше отражает реляционную модель.
но хорошо это или плохо отдельный вопрос.
E>>сейчас выбираю между им и не им, и было бы очень интересно услышать аргументы... IB>его не советую.
а что советуете? на данный момент интересует поддержка mssql с дальнейшим переходом на postgress/mysql.
я склоняюсь в сторону NHibernate.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, Enomay, Вы писали:
E>>можно их список? IB>краце, POCO на самом деле нефига не POCO,
Configuration.ProxyCreationEnabled = false;
IB>LazyLoading хрен отключишь
Configuration.LazyLoadingEnabled = false;
IB>Linq провайдер мало того что неполноценный и половину нормальных запросов не поддерживает, так еще и запросы генерит хуже чем старый-добрый Linq2SQL.
Тут вроди тоже стало немного лучше, но в таки он кривоват .
IB>И, самое главное, корень всех этих проблем в том, что идеологически он так и остался монструозным Full Blown ORM, непонятно для каких задач предназначенным, который внутри себя строит некоторую абстрактную модель и всю работу делает через нее.
Сейчас наружу торчит простой и совсем не монструозный API, которого достаточно для решения 80% типичных задач.
E>>сейчас выбираю между им и не им, и было бы очень интересно услышать аргументы... IB>его не советую.
Не фонтан конечно, но альтернатив не особо. Из плюсов — ет мейнстрим и почти любая проблема гуглится за 5 минут.
Здравствуйте, hardcase, Вы писали:
НС>>Так я и не предлагаю ее проверять. Просто без такой проверки ПМ из мегавещи превращается во вполне обыденный синтаксический сахарок. H>Тем не менее он очень неслабо сокращает количество говнокода.
Я бы даже сказал, что разницы практически нет.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Enomay, Вы писали:
E>в каком смысле? имется в виду что он возвращает класс наследник от POCO?
Да, плюс есть ограничения на вид самого класса.
E>я его не трогал, но у меня по умолчанию он не работает.
Работает в полный рост. Да, еще дополнительные классы со всякой обвязкой.
E>в каком смысле не полноценный? слишком извращенных запросов не писал, но интерестно, с чем возможно придется столкнуться.
Там особых извращений и не надо, шаг в сторону и "не могу построить запрос, проблемы с моделью"
E>я смотрел местами он запросы генерирует лучше чем linq2sql.
То что я смотрел — хуже, проверял по планам. С банальной связкой родитель-потомки не справился — это клиника.
E>но хорошо это или плохо отдельный вопрос.
Это прекрасно.
E>а что советуете?
Linq2SQL, ну или BLT.
E>на данный момент интересует поддержка mssql с дальнейшим переходом на postgress/mysql.
Тогда лучше BLT, так как L2S держит только MSSQL
E>я склоняюсь в сторону NHibernate.
Та же хрень, что и EF, только в профиль.
Здравствуйте, itslave, Вы писали:
IB>>краце, POCO на самом деле нефига не POCO, I>
I>Configuration.ProxyCreationEnabled = false;
I>
IB>>LazyLoading хрен отключишь I>
I>Configuration.LazyLoadingEnabled = false;
I>
Хрен там, это только чуть лучше маскирует то что там в реальности происходит, проблемы никуда не деваются.
I>Тут вроди тоже стало немного лучше, но в таки он кривоват .
Не стало.
I>Сейчас наружу торчит простой и совсем не монструозный API,
Через этот API все равно потроха в разные стороны торчат и этот API на каждом шагу исключения кидает, так как внутренний сложный механизм с его простотой почему-то не справляется.
I>которого достаточно для решения 80% типичных задач.
Для решения 90% типичных задач достаточно Linq2SQL, так какого хрена?
I>Не фонтан конечно, но альтернатив не особо.
Linq2SQL, BLT.
I> Из плюсов — ет мейнстрим и почти любая проблема гуглится за 5 минут.
Категорически не интересно ходить по граблям, даже если по ним уже прошли миллионы леммингов, если можно по ним не ходить.
IB>Хрен там, это только чуть лучше маскирует то что там в реальности происходит, проблемы никуда не деваются.
Конкретно это работает: не генерирует прокси и LazyLoading отрубается.
I>>Тут вроди тоже стало немного лучше, но в таки он кривоват . IB>Не стало.
Перфоманс они подтянули прилично. Прекомпиляцию запросов добавили. навскидку не помню, полезли ли они в linq2EF, но у меня после миграции стало работать ощутимо быстрее.
I>>Сейчас наружу торчит простой и совсем не монструозный API, IB>Через этот API все равно потроха в разные стороны торчат и этот API на каждом шагу исключения кидает, так как внутренний сложный механизм с его простотой почему-то не справляется.
Не без греха, но исключения у меня почему то 'на каждом шагу' не кидает.
I>>которого достаточно для решения 80% типичных задач. IB>Для решения 90% типичных задач достаточно Linq2SQL, так какого хрена?
Потому как не recommended way. С массой ограничений, и без перспектив развития.
I>>Не фонтан конечно, но альтернатив не особо. IB>Linq2SQL, BLT.
В сухом остатке остается BLT. Ожидаемое мнение от автора BLT.
I>> Из плюсов — ет мейнстрим и почти любая проблема гуглится за 5 минут. IB>Категорически не интересно ходить по граблям, даже если по ним уже прошли миллионы леммингов, если можно по ним не ходить.
Миллионы леммингов не могут ошибаться(с)
На самом деле, не так страшен черт как его малюют.
Здравствуйте, itslave, Вы писали:
I>Конкретно это работает: не генерирует прокси и LazyLoading отрубается.
О да! LL очень красиво отрубается, и вообще ничего не загружает. Прокси может и не генерятся, но с произвольным объектом все равно работать нельзя.
I>Перфоманс они подтянули прилично. Прекомпиляцию запросов добавили.
Толку от этого, если запросы все равно строятся хуже чем в L2S?
I>Не без греха, но исключения у меня почему то 'на каждом шагу' не кидает.
А у меня кидает даже на самых примитивных сценариях, типа group join-а.
I>Потому как не recommended way.
Who cares? И, главное, кем не recommended? Теми кто EF разрабатывает? Люди, которые за десяток лет не смогли создать нормальный рабочий продукт, не имеют права что-либо кому-либо рекомендовать.
I> С массой ограничений, и без перспектив развития.
С перспективами развития все понятно, а вот с органичениями пожалуйста по подробнее.
По факту, мы уже много лет с успехом пользуемся L2S и с особыми ограничениями не сталкивались. Прелесть в том, что L2S штука очень простая, легковесная и именно ограничений он не накладывает вообще никаких. Он много чего не может (к счастию), но это не проблема, так как все это спокойно дописыватеся рядом и объем этого дописывания достаточно смешной.
А вот EF, в силу своей врожденной кривизны, как раз и накладывает очень большое количество совершенно необязательных ограничений.
Так повторяю свой вопрос — какого хрена?
I>На самом деле, не так страшен черт как его малюют.
Он не страшен, он убог и уродлив.
Здравствуйте, IB, Вы писали:
I>>LL очень красиво отрубается, и вообще ничего не загружает.
Загружает все что скажешь ему загрузить. там есть специальный extension method — Include и специальное понятие — navigation property. И все загружается.
IB>но с произвольным объектом все равно работать нельзя.
Можно пример "произвольного объекта", с которым оно не работает? У меня работает с самописными POCO обьектами аж бегом.
IB>Толку от этого, если запросы все равно строятся хуже чем в L2S?
Толку то, что стало работать быстрей. Если уж совсем все печально, то есть воркэраунды. Костыли, согласен, но они далеко не каждый день нужны.
I>>Не без греха, но исключения у меня почему то 'на каждом шагу' не кидает. IB>А у меня кидает даже на самых примитивных сценариях, типа group join-а. http://msdn.microsoft.com/en-us/library/bb397895.aspx
Ничего не кидает.
I>>Потому как не recommended way. IB>Who cares? И, главное, кем не recommended? Теми кто EF разрабатывает? Люди, которые за десяток лет не смогли создать нормальный рабочий продукт, не имеют права что-либо кому-либо рекомендовать.
Очевидно не рекомендуется теми, кто бюджеты и прочие ресурсы распределяет.
IB>С перспективами развития все понятно, а вот с органичениями пожалуйста по подробнее.
Сходу — провайдеры к разным СУБД.
IB>А вот EF, в силу своей врожденной кривизны, как раз и накладывает очень большое количество совершенно необязательных ограничений. IB>Так повторяю свой вопрос — какого хрена?
Пока что ограничения больше декларируемые чем реальные. И акцент на "неправильной" архитектуре, чем на реальных юзкейсах. Мир несовершенен, селяви.
I>>На самом деле, не так страшен черт как его малюют. IB>Он не страшен, он убог и уродлив.
Ты необьективен.
Здравствуйте, itslave, Вы писали:
I>Загружает все что скажешь ему загрузить. там есть специальный extension method — Include и специальное понятие — navigation property. И все загружается.
Ну и какое отсутствие ограничений с extension method-ом и какой POCO с navigation property? Нафига все это надо, если можно (и нужно) обходиться обычным linq запросом? Это называется "мы придумали афигенские подпорки к нашим прекрасным костылям" (с)
I>Толку то, что стало работать быстрей.
Пойми — тормоза маппинга, это другой порядок малости по сравнению с тормозами от неэффективного SQL запроса. Так что нет — быстрее не стало.
I>Если уж совсем все печально, то есть воркэраунды. Костыли, согласен, но они далеко не каждый день нужны.
Ровно все тот же вопрос — задлянафига все это, если можно туда вообще не наступать?
I>http://msdn.microsoft.com/en-us/library/bb397895.aspx I>Ничего не кидает.
Объясни это моему эксепшену. Ты left join и group join не перепутал?
I>Очевидно не рекомендуется теми, кто бюджеты и прочие ресурсы распределяет.
Тут, понимаешь, есть такой момент, очень показательный. По факту, "не рекомендованный" L2S написанный за год и положенный на полку уже года 3, по прежнему эффективнее, функциональнее и, как следствие, полезнее в реальных практических задачах, чем "рекомендованный" EF, общая история которого насчитывает лет десять и в который по прежнему вкладывают ресурсы.
Что довольно однозначно говорит как о ресурсах, так и о тех кто их распределяет.
I>Сходу — провайдеры к разным СУБД.
Это не ограничения, это просто всем кроме сиквела не повезло.
I>Пока что ограничения больше декларируемые чем реальные.
Неэффективные запросы и невозможность нормальным образом эти запросы формировать — это очень реальные ограничения, с которыми лично я мириться не собираюсь, не говоря уже об ограничениях на мои объекты.
А вот возражения против L2S которые заключаются в том, что он "не рекомендован" смотрятся действительно довольно забавно.
I>И акцент на "неправильной" архитектуре, чем на реальных юзкейсах.
Акцент как раз на реальных юзкейсах, неприменимость в которых EF, явилась следствием кривой EF-овой архитектуры, что очень хорошо видно. Просто очень наглядный пример, к каким последствиям может привести кривая архитектура и упертость в идеологию, так что грех было не упомянуть.
I>Ты необьективен.
Я более чем объективен. Я честно потратил кучу времени пытаясь оценить полезность перехода наших продуктов с L2S на EF. Не абстрактных юзкейсов, а вполне реальных продуктов с реальными сценариями, как уже написанных, так и находящихся в стадии проектирования. Я ооочень надеялся, что из него все-таки получилось хоть что-то приличное... Однако вывод для EF весьма не утешителен — L2S до сих пор уделывает его, по удобству и эффективности, как гайдар плохиша. Причем разочарование мое этим убожеством столь велико, что у меня до сих пор цензурных слов не очень много находится, как можно заметить.
Необъективен тут скорее ты, так как, похоже, сидишь на EF уже довольно плотно и оправдываешь себя отсутствием альтернатив.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, itslave, Вы писали:
I>>Загружает все что скажешь ему загрузить. там есть специальный extension method — Include и специальное понятие — navigation property. И все загружается. IB>Ну и какое отсутствие ограничений с extension method-ом и какой POCO с navigation property? Нафига все это надо, если можно (и нужно) обходиться обычным linq запросом? Это называется "мы придумали афигенские подпорки к нашим прекрасным костылям" (с)
У тебя каждый раз новые претензии. Сначала lazy loading не отключался, оказалось что отключается. Затем "а если отключается то ничего не грузит". Теперь оказывается грузит, но не так как тебе хотелось бы. Определись как нить, в чем собственно говоря претензии. Индусами написано? Ну и примера POCO, с которым "не работает" EF я наверно не дождусь.
Ну и кстате считаю навигации удобной фичей. Просто, ясно и декларативно указал что надо загружать, одним запросом вытянул целый граф объектов и делай с ними что хочешь.
I>>Толку то, что стало работать быстрей. IB>Пойми — тормоза маппинга, это другой порядок малости по сравнению с тормозами от неэффективного SQL запроса. Так что нет — быстрее не стало.
Я про маппинг нигде ни слова не говорил. Я говорил про кеширование linq-запросов, т.е. sql-запрос не строится каждый раз из linq. На простых сценариях(много одинаковых простых запросов с разными параметрами) у меня перфоманс вырос в 2 раза. Там история просто писец. Сначала они разводили руками и говорили "ой". Затем придумали воркэраунд, типа вручную прекомпилируйте и будет вам счастье. Затем в новой версии похерили. Теперь от обратно сделали. Дурдом блин
I>>Если уж совсем все печально, то есть воркэраунды. Костыли, согласен, но они далеко не каждый день нужны. IB>Ровно все тот же вопрос — задлянафига все это, если можно туда вообще не наступать?
А затем что "яка розумная цьому альтернатыва", как говоривал украинский классик. По сути — только BLToolkit. Но если коснуться маркетинга, саппорта и т.д. — то увы, тут все очень грустно. В смысле надоест тебе его развивать или уедешь ты в отпуск на 3 месяца — и усе. Ни саппорта ни фикса критических багов. опять таки комьюнити, в разы меньше.
I>>http://msdn.microsoft.com/en-us/library/bb397895.aspx I>>Ничего не кидает. IB>Объясни это моему эксепшену. Ты left join и group join не перепутал?
Может и пуьаю, давай свой пример, посмотрим.
I>>Очевидно не рекомендуется теми, кто бюджеты и прочие ресурсы распределяет. IB>Тут, понимаешь, есть такой момент, очень показательный. По факту, "не рекомендованный" L2S написанный за год и положенный на полку уже года 3, по прежнему эффективнее, функциональнее и, как следствие, полезнее в реальных практических задачах, чем "рекомендованный" EF, общая история которого насчитывает лет десять и в который по прежнему вкладывают ресурсы. IB>Что довольно однозначно говорит как о ресурсах, так и о тех кто их распределяет.
Но у этих людей власть.
I>>Сходу — провайдеры к разным СУБД. IB>Это не ограничения, это просто всем кроме сиквела не повезло.
На этом можно и закончить о недостатках l2s.
I>>Пока что ограничения больше декларируемые чем реальные. IB>Неэффективные запросы и невозможность нормальным образом эти запросы формировать — это очень реальные ограничения, с которыми лично я мириться не собираюсь, не говоря уже об ограничениях на мои объекты. IB>А вот возражения против L2S которые заключаются в том, что он "не рекомендован" смотрятся действительно довольно забавно.
Возражение "не мейнстрим" забавны? нуну
I>>И акцент на "неправильной" архитектуре, чем на реальных юзкейсах. IB>Акцент как раз на реальных юзкейсах, неприменимость в которых EF, явилась следствием кривой EF-овой архитектуры, что очень хорошо видно. Просто очень наглядный пример, к каким последствиям может привести кривая архитектура и упертость в идеологию, так что грех было не упомянуть.
Где реальные юзкейсы, приведи хоть один.
I>>Ты необьективен. IB>Я более чем объективен. Я честно потратил кучу времени пытаясь оценить полезность перехода наших продуктов с L2S на EF. Не абстрактных юзкейсов, а вполне реальных продуктов с реальными сценариями, как уже написанных, так и находящихся в стадии проектирования. Я ооочень надеялся, что из него все-таки получилось хоть что-то приличное... Однако вывод для EF весьма не утешителен — L2S до сих пор уделывает его, по удобству и эффективности, как гайдар плохиша. Причем разочарование мое этим убожеством столь велико, что у меня до сих пор цензурных слов не очень много находится, как можно заметить. IB>Необъективен тут скорее ты, так как, похоже, сидишь на EF уже довольно плотно и оправдываешь себя отсутствием альтернатив.
Ты сходу привел несколько вещей которые "нельзя сделать в ef". По факту оказалось что можно. Больше юзкейсов не было, только разговоры о кривизне
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, itslave, Вы писали:
F>Только встретившись с EF лицом к лицу я услышал о том, что существует какая-то надуманная проблема N+1.
ты про это и это?
ну дык все ж решается с ходу прям там и написано как. И гуглится элементарно. Точно, проблема надумана.
Здравствуйте, itslave, Вы писали:
I>ну дык все ж решается с ходу прям там и написано как. И гуглится элементарно. Точно, проблема надумана.
То, что, эта проблема решается — это как раз понятно. Проблема в том, что эти проблемы сначала создаются на ровном месте, и EF этому способствует. Затем эти проблемы профилируются теми или иными инструментами. И только потом они уже они с ходу решаются.
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, itslave, Вы писали:
I>>ну дык все ж решается с ходу прям там и написано как. И гуглится элементарно. Точно, проблема надумана. F> То, что, эта проблема решается — это как раз понятно. Проблема в том, что эти проблемы сначала создаются на ровном месте, и EF этому способствует. Затем эти проблемы профилируются теми или иными инструментами. И только потом они уже они с ходу решаются.
Ну кривоват, не спорю. Однако
во первых с альтернативами не густо
во вторых массовость применения фактически гарантирует то, что найденная проблема уже решена
Здравствуйте, itslave, Вы писали:
I>У тебя каждый раз новые претензии.
Нет, каждый раз одни и те же, я просто разными словами пытаюсь рассказать, чтобы таки дошло.
I>Сначала lazy loading не отключался, оказалось что отключается. Затем "а если отключается то ничего не грузит".
Я вроде бы достаточно ясно излагаю — нет? Еще раз:
LL — не отключается. Команда "LL-отключись!" по факту вовсе не означает, что можно работать так, как буд-то LL нет, она лишь означает, вместо логики LL будет кидаться исключение, но нормально работать со стандартным синтаксисом все равно нельзя.
Поэтому нет, LL — не отключается, его потроха все равно торчат и мешают работать.
Я не знаю чей больной мозг придумал такое поведение, и если ты считаешь, что это нормально, тогда понятно почему тебя устраивает EF. Плохая новость — это не нормально и так быть не должно.
I>Теперь оказывается грузит, но не так как тебе хотелось бы.
Конечно, это все к той же претензии про LL. Изобретение дополнительного синтаксиса, чтобы работать с LL и выдавать рантайм исключения при попытке воспользоваться стандартным (даже если LL формально отключен) — это и есть невозможность отключить LL и работать так, как будто его нет вообще.
I> Индусами написано? Ну и примера POCO, с которым "не работает" EF я наверно не дождусь.
Конечно не дождешься, если игнорировать будешь, я достаточно ясно написал — navigation property это не POCO.
I>Ну и кстате считаю навигации удобной фичей.
Это твои личные заблуждения.
I>Я про маппинг нигде ни слова не говорил. Я говорил про кеширование linq-запросов, т.е. sql-запрос не строится каждый раз из linq.
Твоюжмать. Что в лоб, что полбу. Еще раз: тормоза на построении запроса и получении результата обратно — это другой порядок малости, по сравнению с тормозами от не эффективного SQL-я.
I>На простых сценариях(много одинаковых простых запросов с разными параметрами) у меня перфоманс вырос в 2 раза.
Это говорит лишь о том, что они и здесь умудрились так накосячить, что это стало заметно, но реальную проблему они так и не исправили.
I>Там история просто писец.
Изумительный мэйнстрим! Знаешь, после таких историй я даже рад, что L2S никто не трогает.
I>А затем что "яка розумная цьому альтернатыва", как говоривал украинский классик. По сути — только BLToolkit.
И L2S.
I>Но если коснуться маркетинга, саппорта и т.д. — то увы, тут все очень грустно.
Зачем тебе маркетинг и саппорт, если инструмент just works? Я понимаю зачем нужен саппорт в EF, они каждую версию фигачат заново и делают ее хуже и хуже, но тут-то... Тебе шашечки или ехать?
I> В смысле надоест тебе его развивать или уедешь ты в отпуск на 3 месяца — и усе. Ни саппорта ни фикса критических багов. опять таки комьюнити, в разы меньше.
В BLT код не такой сложный, чтобы критический баг нельзя было поправить самому или быстро догадаться как обойти. Нет, если интересно всем миром в какашках ковыряться, то ктож вам доктор, но мне гораздо интереснее практические задачи решать.
Знаешь, я конечно не люблю аналогии, особенно из автопрома, но тут прямо напрашивается — в девяностых многие кулибины не хотели покупать иномарки потому что "непонятно как работает и запчастей не найдешь, а жигуленок хоть и ломается, зато всегда есть сосед с гаражем, где любую детальку можно выточить"...
I>Но у этих людей власть.
А что толку? Результат этой власти — на лицо.
I>Возражение "не мейнстрим" забавны? нуну
Именно.
I>Где реальные юзкейсы, приведи хоть один.
Я уже целый ворох привел.
I>Ты сходу привел несколько вещей которые "нельзя сделать в ef". По факту оказалось что можно.
Нет, не оказалось. Просто тебе очень хочется чтобы оказалось, но увы.
Здравствуйте, itslave, Вы писали:
I>ну дык все ж решается с ходу прям там и написано как. И гуглится элементарно. Точно, проблема надумана.
Кстати, а кто ответит: зачем пихать все результаты в один запрос вида
SELECT
[Extent1].ABC, ... -- все свойства Extent1
[Extent2].XYZ, ... -- все свойства Extent2FROM [dbo].[Department] AS [Extent1]
LEFT OUTER JOIN [dbo].[Course] AS [Extent2]
ON [Extent1].[DepartmentID] = [Extent2].[DepartmentID]
?
Чем плохи два последовательных select-а для мастера и detail--ов?
*(особенно если учитывать, что у одного "большого" запроса реальный план выполнения будет дороже в два — в три раза).
Здравствуйте, IB, Вы писали:
IB>Я вроде бы достаточно ясно излагаю — нет? Еще раз: IB>LL — не отключается. Команда "LL-отключись!" по факту вовсе не означает, что можно работать так, как буд-то LL нет, она лишь означает, вместо логики LL будет кидаться исключение, но нормально работать со стандартным синтаксисом все равно нельзя. IB>Поэтому нет, LL — не отключается, его потроха все равно торчат и мешают работать.
Иван, позволь уточнить, как именно ты проводишь эти эксперименты. Полагаю, у тебя есть edmx-модель, по которой сгенерирован код. Убедись, плз, что для генерации кода выбран T4 шаблон ADO.NET POCO Entity Generator, например как здесь. В противном случае генерируются классы сущностей, прибитые гвоздями к ДатаКонтексту, и охотно верю, что там при обращении к незагруженному навигационному свойству будет бросаться исключение.
И вообще, свежее веяние в EF — Code-First Development, вот там ты действительно скармливаешь ему свои POCO-классы, возможно уже ранее написанные и использующиеся в приложении.
Да, всё сказанное предполагает, что используется минимум EF v4 (VS 2010). Первая её версия (из VS 2008) действительно ничего вышеперечисленного не позволяла.
Здравствуйте, IB, Вы писали:
IB>LL — не отключается. Команда "LL-отключись!" по факту вовсе не означает, что можно работать так, как буд-то LL нет, она лишь означает, вместо логики LL будет кидаться исключение, но нормально работать со стандартным синтаксисом все равно нельзя. IB>Поэтому нет, LL — не отключается, его потроха все равно торчат и мешают работать.
Еще раз. Если по команде "LL, Отключись" данные не грузятся при первом к ним обращении, то это значит что LL отключается.
IB>Конечно не дождешься, если игнорировать будешь, я достаточно ясно написал — navigation property это не POCO.
Не хошь — не юзай, тебя никто не заставляет. МОжно и без них жить, в чем то понятней и удобней, в чем то нет.
I>>Я про маппинг нигде ни слова не говорил. Я говорил про кеширование linq-запросов, т.е. sql-запрос не строится каждый раз из linq. IB>Твоюжмать. Что в лоб, что полбу. Еще раз: тормоза на построении запроса и получении результата обратно — это другой порядок малости, по сравнению с тормозами от не эффективного SQL-я.
Ышо рас. Генерируемый скл досаточно хорош для 80% случаев. Если он вдруг вышел кривой, этовсегда можно поправить костылями. Генерить оптимальный запрос который будет оптимальным всегда и везде невозможно, ваш кэп.
I>>А затем что "яка розумная цьому альтернатыва", как говоривал украинский классик. По сути — только BLToolkit. IB>И L2S.
Как только провайдеры под большинство популярных субд допилят, так сразу буду доавблять "... и L2S". А их недопилят никогда, потому как большие дяди решили что L2S не нужен.
I>>Но если коснуться маркетинга, саппорта и т.д. — то увы, тут все очень грустно. IB>Зачем тебе маркетинг и саппорт, если инструмент just works? Я понимаю зачем нужен саппорт в EF, они каждую версию фигачат заново и делают ее хуже и хуже, но тут-то... Тебе шашечки или ехать?
Затем, что я тупо не хочу фиксить баги, мигрировать на новые фреймворки и допиливать BLT своими силами, если тебе вдруг надоест.
IB>Знаешь, я конечно не люблю аналогии, особенно из автопрома, но тут прямо напрашивается — в девяностых многие кулибины не хотели покупать иномарки потому что "непонятно как работает и запчастей не найдешь, а жигуленок хоть и ломается, зато всегда есть сосед с гаражем, где любую детальку можно выточить"...
И в 90х это было правильно мнение, если вдруг обламались, то в гаражах любой завсегдатай может подшаманить за поллитры и машина поедет прям щас. Альтернатива — месяцами ищем специалиста и запчасти, платим ногоденег и затем может быть поедем. Если со специалистом не ошиблись. Аналогия налицо
I>>Но у этих людей власть. IB>А что толку? Результат этой власти — на лицо.
Результат этой власти — в l2s нет и никогда не будет родных провайдеров под постгрес, оракл и прочие субд.
I>>Ты сходу привел несколько вещей которые "нельзя сделать в ef". По факту оказалось что можно. IB>Нет, не оказалось. Просто тебе очень хочется чтобы оказалось, но увы.
Скажем так: на деле EF работает, но не соответствует твоему мировоззрению. Это печально, но в общем то не смертельно. Другому человеку напомнил бы пословицу про караван и собак, но в твоем случае надеюсь, что(в том числе) под влиянием BLT, в EF основные косяки поправят.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, itslave, Вы писали:
I>>ну дык все ж решается с ходу прям там и написано как. И гуглится элементарно. Точно, проблема надумана.
S>Кстати, а кто ответит: зачем пихать все результаты в один запрос вида S>
S> SELECT
S> [Extent1].ABC, ... -- все свойства Extent1
S> [Extent2].XYZ, ... -- все свойства Extent2
S> FROM [dbo].[Department] AS [Extent1]
S> LEFT OUTER JOIN [dbo].[Course] AS [Extent2]
S> ON [Extent1].[DepartmentID] = [Extent2].[DepartmentID]
S>
S>?
S>Чем плохи два последовательных select-а для мастера и detail--ов? S>*(особенно если учитывать, что у одного "большого" запроса реальный план выполнения будет дороже в два — в три раза).
Потому что серебряной пули не существуют. Они максимально точно повторили семантику запроса. Никто не запрещает грузить в 2 захода, ручками.
Здравствуйте, itslave, Вы писали:
I>Потому что серебряной пули не существуют. Они максимально точно повторили семантику запроса. Никто не запрещает грузить в 2 захода, ручками.
Текущий вариант отвратительно масштабируется, если нам нужно загружать несколько разных коллекций детей. Лучше уж загружать по умолчанию в несколько запросов, а если кому-то важна точная семантика — вперёд, ручками
Здравствуйте, cerebrate, Вы писали:
C>Иван, позволь уточнить, как именно ты проводишь эти эксперименты. Полагаю, у тебя есть edmx-модель, по которой сгенерирован код.
У меня нет модели и я вообще не хочу генерить код. Я просто создаю объект ручками, дешево и сердито, это и есть POCO )
C>Да, всё сказанное предполагает, что используется минимум EF v4 (VS 2010).
Я смотрел 4.5 и 5.
Здравствуйте, QrystaL, Вы писали:
QL>Здравствуйте, itslave, Вы писали: I>>Результат этой власти — в l2s нет и никогда не будет родных провайдеров под постгрес, оракл и прочие субд.
QL>http://www.devart.com/linqconnect/
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, itslave, Вы писали:
I>>Потому что серебряной пули не существуют. Они максимально точно повторили семантику запроса. Никто не запрещает грузить в 2 захода, ручками.
S>Текущий вариант отвратительно масштабируется, если нам нужно загружать несколько разных коллекций детей. Лучше уж загружать по умолчанию в несколько запросов, а если кому-то важна точная семантика — вперёд, ручками
Твое мнение против мнения команды разработчиков EF. Возможно ты прав, но очень маловероятно что поведение уже поменяют из-за совместимости...
Здравствуйте, itslave, Вы писали:
I>Еще раз. Если по команде "LL, Отключись" данные не грузятся при первом к ним обращении, то это значит что LL отключается.
Если на клетке слона написано "буйвол" — не верь глазам своим. Мне шашечки не важны, мне ехать надо.
LL отключается тогда и только тогда, когда я могу спокойно работать не подозревая о его существовании. К сожалению EF на это не способен. Поэтому — нет, в EF LL не отключается, не смотря на наличие соответствующей команды.
I>Не хошь — не юзай, тебя никто не заставляет. МОжно и без них жить, в чем то понятней и удобней, в чем то нет.
Без них и без EF, иначе туда вообще ничего не загрузишь.
I>Ышо рас. Генерируемый скл досаточно хорош для 80% случаев. Если он вдруг вышел кривой, этовсегда можно поправить костылями. Генерить оптимальный запрос который будет оптимальным всегда и везде невозможно, ваш кэп.
По кругу пойдем? Эти отмазки смотрятся жалко и нелепо, так как уже много лет есть инструмент, который в 90% случаев делает это лучше.
I>Как только провайдеры под большинство популярных субд допилят,
Могу привести тот же аргумент про 80% — в 80%, даже в 90% из под .Net используется MSSQL. Для всех остальных есть BLT.
I>Затем, что я тупо не хочу фиксить баги, мигрировать на новые фреймворки и допиливать BLT своими силами, если тебе вдруг надоест.
Я к BLT никакого отношения не имею )
I>И в 90х это было правильно мнение,
Нет )
I>Результат этой власти — в l2s нет и никогда не будет родных провайдеров под постгрес, оракл и прочие субд.
Ну и болт с ними...
I>Скажем так: на деле EF работает, но не соответствует твоему мировоззрению.
Работает вообще все — это не аргумент. Вопрос в количестве затраченных усилий на реализацию и поддержку + порог вхождения. И здесь, как я уже говорил, EF является редкостным отстоем.
I> Другому человеку напомнил бы пословицу про караван и собак, но в твоем случае надеюсь, что(в том числе) под влиянием BLT, в EF основные косяки поправят.
EF абсолютно беспрспективная технология, сколько бы сил и денег в нее не вкладывали бы. Хотя миллионы мух, по прежнему будут ошибаться. Поэтому я просто пойду с другим караваном. )
В общем, если подытожить — технология абсолютно кривая, как идеологически так и в реализации, и, к счастью, у меня альтернатива есть, поэтому за всем этим цирком я лучше понаблюдаю со стороны.
А дальше — все сами-себе буратины и не говорите, что я не предупреждал...
Здравствуйте, itslave, Вы писали:
IB>>Конечно не дождешься, если игнорировать будешь, я достаточно ясно написал — navigation property это не POCO. I>Не хошь — не юзай, тебя никто не заставляет. МОжно и без них жить, в чем то понятней и удобней, в чем то нет.
А хочется, чтобы в запросах оно все таки работало. Но только в запросах. К примеру, в BLT я запросто могу написать что то вроде:
db
.MyEntities
.Where(me => me.Details.Contains("XXX"))
.Select(me => me.Link.LinkProperty.LinkLinkProperty)
При этом реальные экземпляры будут созданы только для объектов — значений свойства LinkLinkProperty, все остальное превратится в SQL. И BLT гарантирует, что в SQL, а при невозможности будет исключение в момент генерации SQL для этого запроса, а не неявный переезд на клиента и выборка и инстанцирование всей промежуточной хрени для этого. Более того, я тип MyEntity и тех сущностей, на которые он ссылается могу сделать интерфейсами, чтобы уж с гарантией никто их экземпляры не поднял.
А что в случае EF?
I>Ышо рас. Генерируемый скл досаточно хорош для 80% случаев
А в остальных 20 что делать? Писать его руками?
I>Генерить оптимальный запрос который будет оптимальным всегда и везде невозможно, ваш кэп.
А всегда и везде и не нужно, нужно в данном конкретном случае. BLT часто весьма неочевидные запросы генерит, но когда потом проверяешь их план, то он оказывается практически самым оптимальным. И L2S тоже очень неплох в этом плане. А вот в EF все печально.
I>Затем, что я тупо не хочу фиксить баги, мигрировать на новые фреймворки и допиливать BLT своими силами, если тебе вдруг надоест.
Иногда возможность самому поправить в BLT багу и отослать ее авторам существенно лучше, чем ждать у моряМС погоды.
I>но в твоем случае надеюсь, что(в том числе) под влиянием BLT, в EF основные косяки поправят.
Не поправят. Основная проблема в базовой идеологии, и это уже не вылечить.
Здравствуйте, Sinix, Вы писали:
S>Чем плохи два последовательных select-а для мастера и detail--ов?
Слабо представляю как реализовать это на практике на "pure sql" не прибегая к временным таблицам в случае множественных details, особенно если в мастере использовать условия (наиболее часто встречающийся вариант)?
Здравствуйте, alexsoff, Вы писали:
A>Здравствуйте, Sinix, Вы писали:
S>>Чем плохи два последовательных select-а для мастера и detail--ов? A>Слабо представляю как реализовать это на практике на "pure sql" не прибегая к временным таблицам в случае множественных details, особенно если в мастере использовать условия (наиболее часто встречающийся вариант)?
Имелось в виду "1 мастер — несколько таблиц details"? Тогда конечно будет n+1 запросов, только n — это не число записей, а число таблиц detail-ов
Здравствуйте, Sinix, Вы писали:
S>Имелось в виду "1 мастер — несколько таблиц details"? Тогда конечно будет n+1 запросов, только n — это не число записей, а число таблиц detail-ов
Я имел ввиду немного другое, а именно оптимальность использования нескольких запросов вместо одного. например, предположим есть таблицы рабочих и проектов
Employee(ID, Name) Project(ID,EmployeeID, Title )
И есть два бизнес-объекта:
class Employee
{
int ID;
string Name;
ICollection<Project> Projects;
}
class Project
{
int ID;
string Title;
}
Вот как ORM должен сформировать два запроса sql, чтобы выбрать всех рабочих (коллекцию Employee включая в каждый коллекцию detailсов Project) имя у которых начинается на символ "А"?
A>[/c#] A>Вот как ORM должен сформировать два запроса sql, чтобы выбрать всех рабочих (коллекцию Employee включая в каждый коллекцию detailсов Project) имя у которых начинается на символ "А"?
"Имя у которых" — это имя проекта? Для проекта очевидно, для рабочих —
SELECT E.* FROM Employee E WHERE EXISTS (SELECT * FROM Project P WHERE P.Employee_ID = E.ID AND P.Name LIKE '%A%')
?
Если имя — это имя сотрудника, то (для сотрудников очевидно):
SELECT P.* FROM Project P INNER JOIN Employee E ON P.Employee_ID = E.ID WHERE E.Name LIKE '%A%'
Да, при выборке по нескольким спецификациям сложность запросов возрастёт, но это окупится тем, что в результате не будет nMaster * nDetail_1 * nDetail_2 строк
*(nDetail_1(2) — среднее число записей детейлов на одного мастера).
Здравствуйте, Sinix, Вы писали:
S>Если имя — это имя сотрудника, то (для сотрудников очевидно): S>
S> SELECT P.* FROM Project P INNER JOIN Employee E ON P.Employee_ID = E.ID WHERE E.Name LIKE '%A%'
S>
Т.е. по превому запросу проходим по таблице Employee и ищем всех сотрудников у которых имя начинается на 'А' (чтобы получить бизнес объекты типа Employee ) и второй раз — во втором запросе, но уже соединяя их с таблицей детализации Project, чтобы получить коллекцию проектов у каждого сотрудника, а далее в ядре ORM начинаем их агрегировать по признакам "ключ значение". неужели мне одному очевидна неэффективность такого подхода с двумя проходами по одинаковому условию одной и той же таблицы
S>Да, при выборке по нескольким спецификациям сложность запросов возрастёт, но это окупится тем, что в результате не будет nMaster * nDetail_1 * nDetail_2 строк S> *(nDetail_1(2) — среднее число записей детейлов на одного мастера).
Все что Вы выиграли данным подходом так это суммарный объем данных, но проиграли по времени выполнения.
PS
Поправьте, мои рассуждения если можно
Здравствуйте, alexsoff, Вы писали:
A>Т.е. по превому запросу проходим по таблице Employee и ищем всех сотрудников у которых имя начинается на 'А' (чтобы получить бизнес объекты типа Employee ) и второй раз — во втором запросе, но уже соединяя их с таблицей детализации Project, чтобы получить коллекцию проектов у каждого сотрудника, а далее в ядре ORM начинаем их агрегировать по признакам "ключ значение".
На практике запросы будут идти по индексированным столбцам и страницы для них будут уже в кэше, т.е стоимость "лишнего" джойна будет невелика (иначе один запрос или несколько — разницы никакой, мы уже попали). Данные для каждой таблицы выгребаются ровно один раз, стоимость "агрегирования" одной записи на клиенте в любом из вариантов будет ~O(1) (при использовании словарей).
>неужели мне одному очевидна неэффективность такого подхода с двумя проходами по одинаковому условию одной и той же таблицы
Если мы говорим о производительности, то аргументы "очевидно" не подходят, надо мерять. Если есть возможность — возьмите запрос, что генерит EF и сравните стоимость его плана выполнения и стоимость двух "простых" аналогичных запросов.
Здравствуйте, Sinix, Вы писали:
S>На практике запросы будут идти по индексированным столбцам и страницы для них будут уже в кэше,
С чего это вы взяли что в кеше? где гарантия что данные между двумя запросами не изменились? в OLAP мире возможно, а вот в реальных OLTP системах вовсе не гарантируется. И не забывайте, что в реальности СУБД имеют дело с не совсем оптимизированными базами (т.е. где нормально построены индексы и т.д.).
S>Если мы говорим о производительности, то аргументы "очевидно" не подходят, надо мерять. Если есть возможность — возьмите запрос, что генерит EF и сравните стоимость его плана выполнения и стоимость двух "простых" аналогичных запросов.
Ваше утверждение строится на "догадках" что данные будут в кеше, в остальном как-то не прозрачно. Да, если будет время, обязательно построю.
Здравствуйте, alexsoff, Вы писали:
S>>На практике запросы будут идти по индексированным столбцам и страницы для них будут уже в кэше, A>С чего это вы взяли что в кеше? где гарантия что данные между двумя запросами не изменились?
А с чего ты взял, что изменение страницы выкидывает ее из кеша?
A>И не забывайте, что в реальности СУБД имеют дело с не совсем оптимизированными базами (т.е. где нормально построены индексы и т.д.).
Тут такое дело — если делается джойн по полям, у которых нет индекса, то это не просто "не совсем оптимизированная база", это клиника и за такое надо яйца разработчикам и админам БД откручивать.
Здравствуйте, Ночной Смотрящий, Вы писали:
A>>С чего это вы взяли что в кеше? где гарантия что данные между двумя запросами не изменились?
НС>А с чего ты взял, что изменение страницы выкидывает ее из кеша?
А с чего ты взял, что я говорил про изменение страницы? речь шла вообще-то о результатах первой выборки.
НС>Тут такое дело — если делается джойн по полям, у которых нет индекса, то это не просто "не совсем оптимизированная база", это клиника и за такое надо яйца разработчикам и админам БД откручивать.
Опять двадцать пять, я говорил не про поля внешних и первичных ключей, а другие поля таблицы, например в моем примере было ФИО сотрудника. и уже тем более мне не надо доказывать, что на практике индексы нужно лепить повсюду и на каждое поле.
Здравствуйте, alexsoff, Вы писали:
НС>>А с чего ты взял, что изменение страницы выкидывает ее из кеша? A>А с чего ты взял, что я говорил про изменение страницы? речь шла вообще-то о результатах первой выборки.
Ну так изоляция транзакций вроде как. Если она достаточно слабая, надо быть готовым к колизиям вне зависимости от конкретно этого запроса.
НС>>Тут такое дело — если делается джойн по полям, у которых нет индекса, то это не просто "не совсем оптимизированная база", это клиника и за такое надо яйца разработчикам и админам БД откручивать. A>Опять двадцать пять, я говорил не про поля внешних и первичных ключей
Я тоже не говорил.
A>, а другие поля таблицы, например в моем примере было ФИО сотрудника
Sinix предложил простой и действенный вариант. Более того сказал — что в разных случаях — нужно всё равно включать голову и смотреть, что проще и эффективнее (если о эффективности вообще речь стоит — если это запросы UI — то эффективность идёт лесом, совсем не тот порядок нагрузки, в основном).
Я сталкивался в основном с такими ситуациями:
SELECT * FROM Master WHERE Id=XXXX
SELECT * FROM Details WHERE MasterId=YYYY
Заметьте — никакого потом маппинга на клиенте делать не надо — второй селект вообще существует исключительно потому, что реляционная модель. В другом случае это был бы один объект. Более того это предмет для жесткого (но очень заботливого кеширования). Да, в жизни это сложнее, чем я показал — но суть никапли не меняется.
При чём предложение Sinix-а в моём случае себя более чем оправдывает, потому что просто, потому что запросы делают именно то, что я от них я хочу. Да и не делают они никакой просадки. Там хоть сотню таких же навали — не сделают они просадку. А есть такие, которые как раз делают, и там ничего по ФИО не ищется.
Алекс же ж! Тут не хочет читать, что пишут — и пытается навязать своё видение, хотя вроде как и все согласны с тем, что оба варианта более чем применимы, если их применять разумно. Т.е. сделали решение -> имеем ли более-менее реальную базу -> пробуем -> радуемся. В контексте EF — проблема с EF в том, что EF, EF, EF просто таки нагло подталкивает сделать так как он захочет (EF). Особенно с транзакциями (точнее их отсутствием) было вообще не в тему — кто мешает читать в транзакции?
Здравствуйте, Ночной Смотрящий, Вы писали: НС>И ты по ФИО сотрудника делаешь джойн?
Ладно, разговор похож уже на глухого и немого. Мне для моих задач EF хватает за глаза, так где нужны именно эффективные запросы, я делаю ручками и не жалуюсь.
Здравствуйте, IB, Вы писали: E>>а что советуете? IB>Linq2SQL, ну или BLT.
Такой вопрос — как реализовать наследование Table Per Class? (Я так понимаю, поддерживается только Table Per Hierarchy, и соответственно какие-то workarounds нужны...)
Здравствуйте, QrystaL, Вы писали:
QL>Такой вопрос — как реализовать наследование Table Per Class? (Я так понимаю, поддерживается только Table Per Hierarchy, и соответственно какие-то workarounds нужны...)
It appears that MS has deleted the bug on Microsoft Connect.
...
I blogged about this in January 2010, and the bug was opened on 3/17/2010. MS didn’t respond until 6/29/2010, when they said:
... Will keep you posted as we find out more, however. Hope this helps. Entity Framework Team
Apparently “keep you posted” means “we’ll delete your posts”
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, QrystaL, Вы писали:
QL>>Такой вопрос — как реализовать наследование Table Per Class? (Я так понимаю, поддерживается только Table Per Hierarchy, и соответственно какие-то workarounds нужны...)
S>Неа, table per type есть, но такой, что лучше бы не было
Интересно )))
Я наверное неправильно сформулировал — вопрос был про LinqToSql/BLToolkit =)
Здравствуйте, Ringin, Вы писали:
R>... задача стояла работать с базой через ORM, и я остановился на Entity Framework. R>Выскажите пожалуйста свои мнения!
Мнение: Вы — не очень умный человек. Техническая интуиция, при виде бесконечный воплей в тырнете "а как мне сделать ХХХ в EF" или "почему EF делает XXX, а мне нужно YYY", должна была сразу завопить: "Нет! Только если мне доплатит мелкософт!".
Для себя пока лучше BLToolkit ничего не нашёл. Хотя и не искал особо, если честно: зачем, если он и так практически идеально вписывается в код? Прост как мухобойка, быстр как бегущий за пивом и ненавязчив как Медведев — берёшь свои объекты и одной строкой они уже в БД! По-моему, те, кто залезли по гланды в EF, никогда не пробовали, насколько прост BLT — им просто некогда решать бизнес задачи и пробовать новое — носятся по форумам с проблемами, навешанными мелкософтом и думают, что "раз от мелкософта — значит круто!".
Здравствуйте, IT, Вы писали:
IT>Я как раз не предлагаю использовать EF. Сам я его внимательно поизучал, и именно по этой причине никогда в реальных проектах не использовал. Кроме EF есть другие вполне приемлемые решения.
... R>А вот надо мне например вывести пользователю все таблицы базы данных, прочитать констрейнты и показать связи, как это сделать?
INFORMATION_SHEMA ?
Сообщение заговорено потомственным колдуном, целителем и магом в девятом поколении!
Модерирование или минусование сообщения ведет к половому бессилию, венерическим заболеваниям, венцу безбрачия и диарее!
Здравствуйте, rFLY, Вы писали:
IT>>Я как раз не предлагаю использовать EF. Сам я его внимательно поизучал, и именно по этой причине никогда в реальных проектах не использовал. Кроме EF есть другие вполне приемлемые решения. FLY>Например?
Здравствуйте, Кондраций, Вы писали:
R>>А вот надо мне например вывести пользователю все таблицы базы данных, прочитать констрейнты и показать связи, как это сделать? К>INFORMATION_SHEMA ?
Крайне геморойное занятие, особенно учитывая специфику разных БД. В linq2db реализован SchemaProvider, одним вызовом можно получить всю информацию.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Ringin, Вы писали:
R>Разбирался на днях с Entity Framework, точнее сказать задача стояла работать с базой через ORM, и я остановился на Entity Framework. R>У меня сложилось очень двоякое впечатление. Что-то хорошо, а что-то, что можно сделать совершенно простым запросом к бд, через entity framework просто так не сделаешь.
R>Выскажите пожалуйста свои мнения!
Здравствуйте, Ringin, Вы писали:
R>Разбирался на днях с Entity Framework, точнее сказать задача стояла работать с базой через ORM, и я остановился на Entity Framework. R>У меня сложилось очень двоякое впечатление. Что-то хорошо, а что-то, что можно сделать совершенно простым запросом к бд, через entity framework просто так не сделаешь.
R>Выскажите пожалуйста свои мнения!
Асилил ~2/3 мнений.
Я так понял:
1. EF — отстой
2. LINQ — типа рулит
<далее — изделия советских инженеров?>
3. BLT — ваще рулит. Правда на днях я на него ругался, когда пытался запустить Януса на FB. Траблы с квотированными именами. Проблему я ниасилил.
4. LINQ2DB — спасение человечества(?)
---
Я пока не знаю — "кто все эти люди".
Но через пару месяцев надо будет выбирать следующее направление развития для своих игрушек для взаимодействия с FB/IB.
Стоит начать с поддержки LINQ?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
A>>[/c#] A>>Вот как ORM должен сформировать два запроса sql, чтобы выбрать всех рабочих (коллекцию Employee включая в каждый коллекцию detailсов Project) имя у которых начинается на символ "А"? S>"Имя у которых" — это имя проекта? Для проекта очевидно, для рабочих — S>
S> SELECT E.* FROM Employee E WHERE EXISTS (SELECT * FROM Project P WHERE P.Employee_ID = E.ID AND P.Name LIKE '%A%')
S>
S>?
S>Если имя — это имя сотрудника, то (для сотрудников очевидно): S>
S> SELECT P.* FROM Project P INNER JOIN Employee E ON P.Employee_ID = E.ID WHERE E.Name LIKE '%A%'
S>
S>Да, при выборке по нескольким спецификациям сложность запросов возрастёт, но это окупится тем, что в результате не будет nMaster * nDetail_1 * nDetail_2 строк S> *(nDetail_1(2) — среднее число записей детейлов на одного мастера).
зато будут такие артефакты
select top 10000 GETDATE(), * from sometable
select top 10000 GETDATE(), * from sometable
Здравствуйте, SoLame, Вы писали:
S>>Да, при выборке по нескольким спецификациям сложность запросов возрастёт, но это окупится тем, что в результате не будет nMaster * nDetail_1 * nDetail_2 строк S>> *(nDetail_1(2) — среднее число записей детейлов на одного мастера).
SL>зато будут такие артефакты
select top 10000 GETDATE(), * from sometable
select top 10000 GETDATE(), * from sometable
Н
S>>>Да, при выборке по нескольким спецификациям сложность запросов возрастёт, но это окупится тем, что в результате не будет nMaster * nDetail_1 * nDetail_2 строк S>>> *(nDetail_1(2) — среднее число записей детейлов на одного мастера).
SL>>зато будут такие артефакты
S>
S>select top 10000 GETDATE(), * from sometable
S>select top 10000 GETDATE(), * from sometable
S>
S>Зачем? Не, без сарказма — откуда они возьмутся?
например от туда
create view sometable
as
select GETDATE() some_column
--далее всякие джойны по вкусу.
Здравствуйте, SoLame, Вы писали:
S>>Зачем? Не, без сарказма — откуда они возьмутся? SL>например от туда
create view sometable
as
select GETDATE() some_column
--далее всякие джойны по вкусу.
А давайте помедленнее, я за вами не успеваю
Речь шла про подход EF (один запрос вытаскивания для мастера и спецификаций) vs более логичный "1 запрос на каждую таблицу". Итак, откуда возьмётся описанная вами проблема, почему она не возникнет с подходом EF и собственно в чём она заключается?
Особенно с учётом того, что:
1. С вероятноcтью стремящейся к 1 GETDATE() не будет использоваться в запросах (кроме как для основной выборки) и будет выброшен оптимизатором.
2. Использование nondeterministic функций в view — не самая лучшая идея, проблема уже в ней, а не в том как дальше делать запросы.
Здравствуйте, Sinix, Вы писали:
S>Речь шла про подход EF (один запрос вытаскивания для мастера и спецификаций) vs более логичный "1 запрос на каждую таблицу". Итак, откуда возьмётся описанная вами проблема, почему она не возникнет с подходом EF и собственно в чём она заключается?
S>Особенно с учётом того, что: S>1. С вероятноcтью стремящейся к 1 GETDATE() не будет использоваться в запросах (кроме как для основной выборки) и будет выброшен оптимизатором. S>2. Использование nondeterministic функций в view — не самая лучшая идея, проблема уже в ней, а не в том как дальше делать запросы.
"откуда". Мы незнаем. EF у нас тулза-всёмогутер, которая должна покрывать все сценарии использования.
"почему". Потому что EF выполняет sql запрос, именно так, как просил пользователь. одним запросом — значит одним. пользователь напишет два — значит два.
1,2 мы этого не знаем. у нас тулза-всёмогутер. и с каким базами он будет работать — разработчикам не ведомо. кроме GetDate() есть другие функции,
и функции которые написал пользователь на их основе...
а так же вы забываете про уровни изоляции транзакций...
The EF code base has a long history, going back to the WinFS days, with parts of the code base being 10+ years old. [...] EF7 will be a lightweight and extensible version of Entity Framework that just pulls forward the commonly used features. In addition, we’ll be able to include some commonly requested features that would have been difficult to implement in the existing code base, but can be included from the start in EF7.
QL>The EF code base has a long history, going back to the WinFS days, with parts of the code base being 10+ years old. [...] EF7 will be a lightweight and extensible version of Entity Framework that just pulls forward the commonly used features. In addition, we’ll be able to include some commonly requested features that would have been difficult to implement in the existing code base, but can be included from the start in EF7.
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД><далее — изделия советских инженеров?> КД>3. BLT — ваще рулит. Правда на днях я на него ругался, когда пытался запустить Януса на FB. Траблы с квотированными именами. Проблему я ниасилил.
+1 к "ваще рулит". У нас это "продакшн библиотека", наподобие "Си" в языках прог-я: делает ровно то, что скажут и никаких внутренних выкрутасов. Единственная беда — доставание сгенерённого ID для PK, но мы просто прикрутили функцию (исходники открыты и более-менее понятны). Т.к. FireBird не особо распространён, подозреваю, его не особо тестировали, но т.к. исходники доступны, вполне можно вылечить. Да и на форуме есть разработчик.
Я бы рекомендовал именно BLToolkit, т.к. не люблю "развесистых" решений, а BLT прост как молоток.
Не так давно вновь ковырялся и с EF, и c NHibernate. Определённо, NHibernate тоже стал лучше, но я там не нашёл, как mapp'ить на хранимые процедуры. По мне это из самых полезных features в EF, поскольку таким способом можно использовать ORM без существенных потерь производительности по сравнению с чистым SQL.
Здравствуйте, Yoriсk, Вы писали:
>>>Я с линком писал такие запросы, что вручную их почти нереально было родить. И эти запросы проверялись при компиляции. __>>Чушь. Ну напишите мне что я "нереально не могу родить" с помощью T-SQL или PL/SQL, что вы можете сделать с помощью LINQ. Y>Начнём с совcем классики. E2, так сказать: Y>
Y>Incorrect syntax near ') динамический sql не предлагать.
А как вам такой вариант? Используется Razor. При этом есть метод CheckAllQueries, который полностью автоматически находит все запросы в сборке, перебирает все варианты параметров и отправляет запросы на SQL сервер в режиме SchemaOnly.
Здравствуйте, Ilya81, Вы писали:
I>Не так давно вновь ковырялся и с EF, и c NHibernate. Определённо, NHibernate тоже стал лучше, но я там не нашёл, как mapp'ить на хранимые процедуры. По мне это из самых полезных features в EF, поскольку таким способом можно использовать ORM без существенных потерь производительности по сравнению с чистым SQL.
Чтобы "использовать ORM без существенных потерь производительности по сравнению с чистым SQL" нужно правильно писать проекции и делать хорошие индексы.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, Yoriсk, Вы писали:
AP>А как вам такой вариант? Используется Razor. При этом есть метод CheckAllQueries, который полностью автоматически находит все запросы в сборке, перебирает все варианты параметров и отправляет запросы на SQL сервер в режиме SchemaOnly.
Сила Linq в динамической композиции запроса без склейки строк. То что ты предлагаешь все равно склейка строк, которая очень быстро становится неподдерживаемой.
Я уверен что при появлении Roslyn в широких массах такие "активные строки" с проверкой при компиляции будут частым явлением, но вряд ли смогут быть применении в сколь-нибудь сложных случаях.
Кроме того EntityFramework теперь умеет делать миграции, что делает его в 100500 раз круче любого ORM.
Здравствуйте, gandjustas, Вы писали:
G>Кроме того EntityFramework теперь умеет делать миграции, что делает его в 100500 раз круче любого ORM.
О да, это совершенно в духе Microsoft: библиотека делает всё, но всё делает одинаково хреново. Ни уникальных (чего уж о фильтрованных) индексов, ни Unique Constraint'ов. Про что-то отличное от SQL Server.
И "киллер-фича": нет поддержки MSBuild (про migrate.exe знаю, и это костыль).
HgLab: Mercurial Server and Repository Management for Windows
QL>The EF code base has a long history, going back to the WinFS days, with parts of the code base being 10+ years old. [...] EF7 will be a lightweight and extensible version of Entity Framework that just pulls forward the commonly used features. In addition, we’ll be able to include some commonly requested features that would have been difficult to implement in the existing code base, but can be included from the start in EF7.
Да уж, "эту песню не задушишь не убъешь!" (с)
Самое время вспомнить краткую историю EF — давным давно, в далекой-далекой галактике, во времена первых бэтт .Net 1.0 стартовал амбициозный проект под названием ObjectSpaces. Новому языку и экосистеме обязательно же нужен самый лучший на свете ORM? И эти могучие ребята обещали наконец показать всему миру, как нужно работать с БД. Суровые были архитекторы — во всех других ORM-ах был фатальный недостаток — его делали не они.
Долго ли, котротко ли, но ко времени выхода .Net 2 — стали появляться первые публичные сборки, но тут что-то пошло не так и проект прикрыли...
Однако, в это время стартовал проект WinFS, в рамках ОС Longhorn. А объектной файловой системе, конечно же нужен самый лучший ORM! И команда ObjecrSpaces в полном составе мигрирует на новый проект. Конечно же они сразу обнаруживают фатальный недостаток в текущей реализации — ее делали не они.
Долго ли коротко ли, но что-то пошло не так и проект прикрыли...
Тем временем подоспел С# 3.0, и LINQ, и команда компилятора шарпа, примерно за год, реализовала LINQ2SQL с лямбдами и выводом типов.
Но нельзя же оставаться .Net-у без лучшего на свете ORM-а? И команда ObjectSpaces практически полным составом начинает делать EF. Очевидно, во всех существующих системах был фатальный недостаток — его делали не они.
LINQ2SQL пошел в продакшн, получил заслуженную славу, пролез в кучу проектов и стал готовиться второй релиз, а команда ObjectSpaces все так же перепиливала ObjectSpaces под EF.
Когда проекту под названием EF стукнуло 5 лет, LINQ2SQL уже пару лет был в продакшене и стало понятно, что тянуть с релизом больше нельзя — на свет появился EF 4.0 (редкостно сырой был продукт, откровенно говоря). С более низкого номера версии стартовать было попросту не прилично... И им бы до сих пор никто не пользовался, если бы не случилось страшное.
Команде компилятора как-то не по статусу заниматься тулами для работы с БД, когда на фичи языка ресурсов не хватает, и LINQ2SQL попытались передать команде сиквела, но те отпинались и, в конце-концов, LINQ2SQL прибился в горячие объятия команды EF где и был похоронен, так как обладал фатальным недостатком — его писали не они. (и не кого не волновало, что L2S до сих пор эффективнее и удобнее, чем все что писалось командой EF за последний десяток лет)
И вот, к шестой версии EF стало понятно, что что-то пошло не так...
Ждем продолжения истории? =)
Очевидно, команда ObjectSpaces обладает фантастическим даром убеждения. Я не могу придумать других причин — как можно продавать одну и ту же откровенно ущербную идею, и выпускать на ее основе кривые и не рабочие продукты больше десятка лет, и все еще получать финансирование на реализацию своих заблуждений.
Здравствуйте, Нахлобуч, Вы писали:
Н>Здравствуйте, gandjustas, Вы писали:
G>>Кроме того EntityFramework теперь умеет делать миграции, что делает его в 100500 раз круче любого ORM.
Н>О да, это совершенно в духе Microsoft: библиотека делает всё, но всё делает одинаково хреново. Ни уникальных (чего уж о фильтрованных) индексов, ни Unique Constraint'ов. Про что-то отличное от SQL Server.
И что? Все равно всем ОРМам надо как минимум повторит фичи ef.
Н>И "киллер-фича": нет поддержки MSBuild (про migrate.exe знаю, и это костыль).
А зачем тебе поддержка msbuild? Initializer накатит обновление базы при старте.
Здравствуйте, IB, Вы писали:
IB>Очевидно, команда ObjectSpaces обладает фантастическим даром убеждения. Я не могу придумать других причин — как можно продавать одну и ту же откровенно ущербную идею, и выпускать на ее основе кривые и не рабочие продукты больше десятка лет, и все еще получать финансирование на реализацию своих заблуждений.
Я вот наблюдаю похожий процесс 4 года. Архитект команды в почти 30 человек адски харизматичный лидер с очень низкой грамотностью, но хорошо прокачан в баззвордах и умеет писать шикарные proof-of-concept, ни разу не занимался ни серьезным багфиксом ни майнтенансом, основной метод борьбы с проблемами — переписывание с нуля. Рефакторинг проекта в его исполнение может остановить проект на срок от недели до полутора месяцев. Когда включает свой рупор, у команды выключается мозг, любые идеи воспринимаются на ура.
Начиналось с сервелата, "всё есть сервелат". Потом появилась самопальная либа T, и лозунг поменялся "Все есть Т". Далее появился HTML5 и лозунг стал "всё есть HTML5". Потом появился клиенцкая либа О и лозунг стал "всё есть О". Потом появился клиенцко серверный Б и лозунг "Всё есть Б".
Все это сопровождается перетягиванием продуктов на новые рельсы, переписыванием и изобретением старых велосипедов по новому. Самые большие проекты к счастью перетащить не вышло, на бюджетах этих проектов команда и живет.
И вот смотрю, что кастомера постоянно колбасит, то бюджет, то сроки. Оказалсь, что кастомеры тоже попадают под его зомбирование. Ни один проект внятно не был спроектирован, главное найти правильные баззворды.
Щас товарищ добрался до процессов. Разумеется, все процессы оказались неправильными. Теперь с проектами задвигается новый процесс: "МДД — mock(merge) driven development". Судя по всему, продукт-овнеры тоже ведутся на его зомбирование, несмотря на очевидные проблемы с их проектом — писали-писали год, в продакшн не вышли, начали переписывать заново.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, QrystaL, Вы писали:
IB>Очевидно, команда ObjectSpaces обладает фантастическим даром убеждения. Я не могу придумать других причин — как можно продавать одну и ту же откровенно ущербную идею, и выпускать на ее основе кривые и не рабочие продукты больше десятка лет, и все еще получать финансирование на реализацию своих заблуждений.
А ты давно пробовал использовать ef на практике? После допила migrtions и передачи в OpenSource версия 6.0 получилась очень достойная.
Вообще я очень часто вижу как судят продукты\технологии по прошлым "заслугам", если так посмотреть то почти что угодно было говном.
Здравствуйте, gandjustas, Вы писали:
G>И что? Все равно всем ОРМам надо как минимум повторит фичи ef.
Нет. ORM ортогонален миграциям, и наличие последних в первом никакой особенной ценности EF'у как ORM'у не добавляют. А по поводу фич -- NHibernate далеко впереди.
G>А зачем тебе поддержка msbuild? Initializer накатит обновление базы при старте.
Ну здрасти приехали. Т.е. вместо того, чтобы этим занимался, грубо говоря, CI-сервер (который имеет всю полноту информации для того, чтобы откатить потенциально неудачный деплоймент), мы перекладываем ответственность на приложение? И даем ему права DDL Admin'а? Мне кажется, это, мягко говоря, несколько неправильно.
HgLab: Mercurial Server and Repository Management for Windows
Здравствуйте, Yoriсk, Вы писали:
Y>Я чего-то не заметил или теперь и на сервере имеем бессмертное Y>
Y>If @filter1 Is Not Null
Y> Set @SQLQuery = @SQLQuery + ' And (Field1 = @filter1) '
Y>
Y>Зато sql у нас генерит не EF/L2S/BL а Razor. Теперь заживём!
Не совсем понял о чем вы. В СУБД уходят уже прошедшие через Razor строки. Razor используется только как замена StringBuilder-а с кратким синтаксисом.
Y>А в чём профит этой затеи?
Автоматическая проверка всех динамических запросов. Получили фактически то, зачем делался LINQ для баз данных. И при этом работаем с нативным SQL. Для удобной склейки строк используем Razor.
При работе с СУБД изначальная задача так и стоит – сгенерировать строку запроса (плюс коллекцию параметров). Вот и решили ее прозрачным образом. Фактически решили проблемы, связанные с прямым использованием SqlCommand/DataReader, и не добавили своих в отличие от LINQ.
Здравствуйте, gandjustas, Вы писали:
G>А ты давно пробовал использовать ef на практике? После допила migrtions и передачи в OpenSource версия 6.0 получилась очень достойная.
У нас пяток продуктов используют EF. Там плохо всё. Начиная с того, что товарищи пытаются влиять на схему БД (патамушта если сделать правильно, то EF не смогёт), и кончая сгенерированным SQL'ем; этот газенваген словами не живописать.
HgLab: Mercurial Server and Repository Management for Windows
Здравствуйте, gandjustas, Вы писали:
G>Сила Linq в динамической композиции запроса без склейки строк.
Это его слабость. Склейка строк рулит. Просто раньше приходилось склейку строк покрывать тестами, сейчас тесты делаются автоматически.
G> То что ты предлагаешь все равно склейка строк, которая очень быстро становится неподдерживаемой.
Выше предложено склейка строк с автоматической проверкой. Утверждение о "неподдерживаемой" голословная чушь.
G>Кроме того EntityFramework теперь умеет делать миграции, что делает его в 100500 раз круче любого ORM.
Ты думаешь, не у кого не было миграции до этого? В нормальных командах это уже давно решено. Это должно просто быть. Странно это выдавать за мега фичу.
Здравствуйте, Нахлобуч, Вы писали:
Н>Здравствуйте, gandjustas, Вы писали:
G>>И что? Все равно всем ОРМам надо как минимум повторит фичи ef.
Н>Нет. ORM ортогонален миграциям, и наличие последних в первом никакой особенной ценности EF'у как ORM'у не добавляют.
Еще как добавляют, тупо скорость разработки. Создать БД руками, а потом сгенерировать модель и обвесить аннотациями в разы медленнее, чем просто написать код модели и включить миграции. Про обновление бд и модели молчу.
Все разработчики, кроме совсем упоротых, начав использовать миграции хрен с них соскочат.
Н>А по поводу фич -- NHibernate далеко впереди.
Да ладно? Напомни когда в NHibernate появились:
1) Асинхронное выполнение запросов, чтобы await работало
2) Готовая функция или расширение вроде https://github.com/loresoft/EntityFramework.Extended, которые позволяют делать массовые обновления и удаления
3) Локальный кеш в виде ObservableCollection для того чтобы байндить сеты напрямую в UI, а не писать 100500 мапперов
G>>А зачем тебе поддержка msbuild? Initializer накатит обновление базы при старте.
Н>Ну здрасти приехали. Т.е. вместо того, чтобы этим занимался, грубо говоря, CI-сервер (который имеет всю полноту информации для того, чтобы откатить потенциально неудачный деплоймент), мы перекладываем ответственность на приложение?
CI сервер не решает проблем рассинхрона моедли и приложения. А миграции, как ни удивительно, решают.
Н>И даем ему права DDL Admin'а? Мне кажется, это, мягко говоря, несколько неправильно.
Почему это неправильно? В 90% случаев применения ORM в БД никто кроме приложения не ходит, так что вполне нормальный сценарий.
А если у тебя Data Warehouse, куда ходят много приложений, то туда с ORM обычно никто не лезет, да и логика реализована внутри базы, что является проблемой для ORM.
Хотя и в этом случае EF рулит, он позволяет использовать себя как чистый маппер, отображает результаты запросов на объекты.
Буквально пару лет назад ничего этого в ef не было, с тех пор много поменялось.
Здравствуйте, Нахлобуч, Вы писали:
Н>Здравствуйте, gandjustas, Вы писали:
G>>А ты давно пробовал использовать ef на практике? После допила migrtions и передачи в OpenSource версия 6.0 получилась очень достойная.
Н>У нас пяток продуктов используют EF. Там плохо всё. Начиная с того, что товарищи пытаются влиять на схему БД (патамушта если сделать правильно, то EF не смогёт), и кончая сгенерированным SQL'ем; этот газенваген словами не живописать.
Че-то ты путаешь. В EF6 схему можно сделать любую. Если билдера не хватит, то просто напиши DDL команды руками. Скорее всего ты говоришь EF4, где схема генерится по модели и влиять но это нельзя.
По поводу генерированного SQL — обычно решается выкидыванием репозитариев, протаскиванием IQueryable на уровень контроллеров, добавлением проекций в выборки, потом созданием индексов по результатам запроса к missed indexes и все начинает летать. Есть конечно особо запущенные случаи, когда в базе накрутили дохрена всего, что ef не может это прожевать, но в этих случаях вообще ни один ORM прожевать не сможет.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Сила Linq в динамической композиции запроса без склейки строк. AP>Это его слабость. Склейка строк рулит. Просто раньше приходилось склейку строк покрывать тестами, сейчас тесты делаются автоматически.
Конечно рулит, а автоматизированная (безопасная) склейка строк, которую дает Linq рулит втройне. Ты с чем пытаешь спорить?
G>> То что ты предлагаешь все равно склейка строк, которая очень быстро становится неподдерживаемой. AP>Выше предложено склейка строк с автоматической проверкой. Утверждение о "неподдерживаемой" голословная чушь.
Ну не начинай, ты уже в этой теме отличился. Можем повторить:
Форма запроса на входе (source) неизвестна, так может быть как выборка по ключу, так и запрос всех кастомеров, купивших за последние 3 дня.
На выходе надо получить только тех, кто купил более чем на указанную сумму.
Покажи как это сделать склейкой строк.
G>>Кроме того EntityFramework теперь умеет делать миграции, что делает его в 100500 раз круче любого ORM. AP>Ты думаешь, не у кого не было миграции до этого? В нормальных командах это уже давно решено. Это должно просто быть. Странно это выдавать за мега фичу.
В каких нормальных командах? Приведи хоть пару ссылок.
Здравствуйте, Ringin, Вы писали:
R>Выскажите пожалуйста свои мнения!
Стандартный use case такой, работает почти во всех случаях.
Если начинаешь новый проект, то используешь EntityFramework, чтобы быстро начать и запустить проект.
Потом, когда проект уже работает, то ты смотришь и оптимизируешь отдельные части, в которых у тебя есть проблем с производительностью.
Если у тебя проект масштаба StackOverflow, то заменяешь EF на какой-нибудь Dapper и производишь другие оптимизации в архитектуре.
Извините, я сейчас в совсем другой предметной области, а с БД имел плотное общение примерно в 2000-2001. С тех пор нормально помню SQL, без изысков, но что такое outer join помню хорошо.
Я как-то отстал от жизни, зачем пользоваться ORM вообще?
Я пробовал пользоваться ORM в Django и RoR и "как-то не пошлО". С момента написания запросов из хотя бы пары селектов (select from select), или тот же outer join, SQL просто удобнее.
Да, спасибо, что-то подобное я уже читал, хоть и не про .NET.
Таким образом, сложные вещи делать через ORM не надо, а простые... Зачем тогда вообще ORM? Опять же, может, в обсуждаемых тут EF и NHibernate это не так, но в Django/RoR накладываются довольно жёсткие ограничения даже на именование таблиц в БД, что конфликтует с принятыми названиями у меня в голове, например Да, их можно обойти, но тогда синтаксис работы с ORM будет многословней SQL-запроса.
Здравствуйте, Ringin, Вы писали:
R>А вот надо мне например вывести пользователю все таблицы базы данных, прочитать констрейнты и показать связи, как это сделать?
Создаете папочку с моделью данных, делаете свой objectcontext, и все.
Такая штука там очень легко делается.
Там где нужно создавать объектную модель данных я абсолютно за EF.
Хороший инструмент, запросы проходят быстро, не знаю кто и как писал но у меня за 2 секунды грузились 10к очень сложных объектов.
Создание логики и архитектуры с помощью него тоже проходит быстро.
Хранимки и прочий sql предполагается использовать для более сложных операций поиска,создания временных таблиц и так далее.
Здравствуйте, gandjustas, Вы писали:
G>А ты давно пробовал использовать ef на практике? После допила migrtions и передачи в OpenSource версия 6.0 получилась очень достойная.
Ничего там достойного, те же косяки в тех же местах. Там врожденная проблема, которая заключается в неадекватности идеи на которой весь проект строился, плюс не очень удачная реализация, которая не позволяет избавиться от наследия прошлого не переписав большую часть кода.
Я об этом утверждал много лет назад, в том числе и в этом топике. Наконец-то они и сами это признали...
Мое любимое место:
As we look at what we want to achieve in EF7 we’ve had to take a realistic look at our current code base.
<….>
As a result, there are many seldom used features and capabilities in the code base that hamper performance and complicate development, but are not feasible to remove due to the monolithic nature of the implementation. We also have a number of unintuitive behaviors that are engrained into the framework and hard to change or remove for the same reasons
Здравствуйте, Dair, Вы писали:
D>Я как-то отстал от жизни, зачем пользоваться ORM вообще?
Давай на конкретных примерах. Перепиши с идентичным поведением и полным сохранением контроля компилятора этот примитивный код без ORM:
using (var db = new XxxDB())
{
var model =
db
.Messages
.Where(m => m.ID == id && m.Forum.ReadLevel <= Account.AccessLevel)
.Select(
m =>
new MessageModel
{
ID = id,
ForumShortName = m.Forum.ShortName,
CreatedOn = m.CreatedOn,
Subject = m.Subject,
Text = FormatMessageBody(id, m.Account.Origin)
})
.FirstOrDefault();
return model == null ? ErrorMessageBox("Сообщение не найдено") : View(model);
}
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>А ты давно пробовал использовать ef на практике? После допила migrtions и передачи в OpenSource версия 6.0 получилась очень достойная. IB>Ничего там достойного, те же косяки в тех же местах. Там врожденная проблема, которая заключается в неадекватности идеи на которой весь проект строился, плюс не очень удачная реализация, которая не позволяет избавиться от наследия прошлого не переписав большую часть кода.
А конкретнее? Сообщение выглядит как набор лозунгов.
Здравствуйте, gandjustas, Вы писали:
G>Че-то ты путаешь. В EF6 схему можно сделать любую. Если билдера не хватит, то просто напиши DDL команды руками. Скорее всего ты говоришь EF4, где схема генерится по модели и влиять но это нельзя.
Я имел в виду то, что товарищи, вооруженные EF'ом, очень часто жалуются на то, какие схемы (вполне легальные с точки зрения реляционной теории) мы используем. Часто просят, например, сделать некоторые поля nullable'ными. NHibernate всё, что ни сочиняли, проглатывает.
HgLab: Mercurial Server and Repository Management for Windows
Здравствуйте, gandjustas, Вы писали:
G>Да ладно? Напомни когда в NHibernate появились: G>1) Асинхронное выполнение запросов, чтобы await работало
Внимание, вопрос. Что будет в этом случае:
var dbContext = new DbContext();
var something = await dbContext.Foo.FirstOrDefaultAsync(e => e.Id == 1);
var morething = await dbContext.Foo.FirstOrDefaultAsync(e => e.Id == 2);
Правильно, получишь по пальцам. Так что можно считать, что async в EF появилась по недоразумению и ничего особенного из себя не представляет. Загугли NHibernate Futures, которые, хоть и не async, а все равно круты.
G>2) Готовая функция или расширение вроде https://github.com/loresoft/EntityFramework.Extended, которые позволяют делать массовые обновления и удаления
HQL умеет.
G>3) Локальный кеш в виде ObservableCollection для того чтобы байндить сеты напрямую в UI, а не писать 100500 мапперов
Снова фича из нипоймиоткуда. В NHibernate такого нет, но какое отношение это имеет к ORM'ам, которые мы обсуждаем?
G>CI сервер не решает проблем рассинхрона моедли и приложения. А миграции, как ни удивительно, решают.
Что будет, если по каким-то причинам (например, не удастся создать уникальный индекс) миграции не накатятся? В твоем случае получим неработоспособное приложение. В случае с CI-сервером всегда есть возможность восстановить БД из предварительно сделанного бэкапа.
G>Почему это неправильно? В 90% случаев применения ORM в БД никто кроме приложения не ходит, так что вполне нормальный сценарий.
Это неправильно. PLOP.
HgLab: Mercurial Server and Repository Management for Windows
Здравствуйте, gandjustas, Вы писали:
G>А конкретнее? Сообщение выглядит как набор лозунгов.
Ну отмотай выше этот же топик, я устал уже в восьмой раз все озвучивать.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>А конкретнее? Сообщение выглядит как набор лозунгов. IB>Ну отмотай выше этот же топик, я устал уже в восьмой раз все озвучивать.
Все что ты озвучивал конкретное касалось старых версий. Про "неадекватность идеи" как не было ответа, так и нет.
Здравствуйте, Нахлобуч, Вы писали:
Н>Здравствуйте, gandjustas, Вы писали:
G>>Да ладно? Напомни когда в NHibernate появились: G>>1) Асинхронное выполнение запросов, чтобы await работало
Н>Внимание, вопрос. Что будет в этом случае:
Н>
Н>Так что можно считать, что async в EF появилась по недоразумению и ничего особенного из себя не представляет.
Прекрасно работает, если ты не умеешь использовать, то это твои проблемы. EF тут не при чем.
Н>Загугли NHibernate Futures, которые, хоть и не async, а все равно круты.
Фигня там никому не нужная, а не фичи.
G>>2) Готовая функция или расширение вроде https://github.com/loresoft/EntityFramework.Extended, которые позволяют делать массовые обновления и удаления Н>HQL умеет.
HQL это текст, а расширение позволяет писать код, который, например, спокойно переживает рефакторинг переименования, а миграции спокойно обновляют базу.
G>>3) Локальный кеш в виде ObservableCollection для того чтобы байндить сеты напрямую в UI, а не писать 100500 мапперов Н>Снова фича из нипоймиоткуда. В NHibernate такого нет, но какое отношение это имеет к ORM'ам, которые мы обсуждаем?
Потому что есть сценарии, в которых используются ORM наиболее активно — десктопные приложения, работающие с базой и веб-сайты с отображением модели 1-в-1 в базу. Все остальные сценарии для ОРМ встречаются на два порядка реже.
EF отлично реализует фичи для обоих сценариев (на данный момент круче всех в .NET), но совершенно ими не ограничивается.
G>>CI сервер не решает проблем рассинхрона моедли и приложения. А миграции, как ни удивительно, решают.
Н>Что будет, если по каким-то причинам (например, не удастся создать уникальный индекс) миграции не накатятся? В твоем случае получим неработоспособное приложение. В случае с CI-сервером всегда есть возможность восстановить БД из предварительно сделанного бэкапа.
Не говори чушь, DDL транзакции придумали давно, если база не может обновится то просто упадет приложение при старте.
Твое представление о EF застряло на уровне 2010 года, открой глаза, на дворе 2014. Два мажорных релиза было за это время.
G>>Почему это неправильно? В 90% случаев применения ORM в БД никто кроме приложения не ходит, так что вполне нормальный сценарий. Н>Это неправильно. PLOP.
Аргумент!
Здравствуйте, Нахлобуч, Вы писали:
Н>Здравствуйте, gandjustas, Вы писали:
G>>Че-то ты путаешь. В EF6 схему можно сделать любую. Если билдера не хватит, то просто напиши DDL команды руками. Скорее всего ты говоришь EF4, где схема генерится по модели и влиять но это нельзя.
Н>Я имел в виду то, что товарищи, вооруженные EF'ом, очень часто жалуются на то, какие схемы (вполне легальные с точки зрения реляционной теории) мы используем. Часто просят, например, сделать некоторые поля nullable'ными. NHibernate всё, что ни сочиняли, проглатывает.
А в чем проблема в EF написать так:
public class TestEntites : DbContext
{
public DbSet<Foo> Foo { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Foo>().Property(e => e.Data).IsOptional();
base.OnModelCreating(modelBuilder);
}
}
при этом:
public class Foo
{
public int Id { get; set; }
[Required]
public string Data { get; set; }
}
Тогда валидация asp.net на клиенте и сервере не пропустит null в поле Data, а в базе будет Nullable поле. При желании можно еще и валидацию обязательного поля сделать при сохранении в базу.
Судя по твоим постам ты EF последний раз видел 5 лет назад.
Здравствуйте, gandjustas, Вы писали:
G>Покажи как это сделать склейкой строк.
public static QFragment GoldCutomer(Param<decimal> threshold)
{
return new {threshold}.QFragment(@"
(SELECT SUM(Quantity * UnitPrice)
FROM [Order Details] od
JOIN Orders o ON od.OrderID = o.OrderID
WHERE o.CustomerID = c.CustomerID
) > @threshold");
}
По поводу Dapper-а и LINQ. Вот разработчик stackoverflow детально описывает real world код.
700ms только на то, чтобы сформировать строку запроса (до отправки в СУБД).... 700ms ... 700ms ...
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Покажи как это сделать склейкой строк. AP>
AP> public static QFragment GoldCutomer(Param<decimal> threshold)
AP> {
AP> return new {threshold}.QFragment(@"
AP>(SELECT SUM(Quantity * UnitPrice)
AP> FROM [Order Details] od
AP> JOIN Orders o ON od.OrderID = o.OrderID
AP> WHERE o.CustomerID = c.CustomerID
AP>) > @threshold");
AP> }
AP>
Пфф, QFragmet не типизирован. Нет никаких гарантий, что этот фрагмент будет присоединен к выборке из Customer. Более того, нет гарантии что алиас для таблицы Customer будет именно "c". Про проверки при компиляции вообще молчу.
Здравствуйте, gandjustas, Вы писали:
G>Пфф, QFragmet не типизирован. Нет никаких гарантий, что этот фрагмент будет присоединен к выборке из Customer. Более того, нет гарантии что алиас для таблицы Customer будет именно "c". Про проверки при компиляции вообще молчу.
Ты вообще читаешь? Третий раз повторяю, есть автоматическая проверка всех запросов.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Пфф, QFragmet не типизирован. Нет никаких гарантий, что этот фрагмент будет присоединен к выборке из Customer. Более того, нет гарантии что алиас для таблицы Customer будет именно "c". Про проверки при компиляции вообще молчу. AP>Ты вообще читаешь? Третий раз повторяю, есть автоматическая проверка всех запросов.
Да повторять можешь сколько влезет, но на твоем фрагменте SQL выругается на алиас "c". Попробуй скопировать его в Management Studio и проверь.
В этом собственно и проблема текстовых запросов — они должны быть литералами в коде, чтобы их можно было проверить, а это сильно ограничивает возможности программы или множит количество запросов, что усложняет сопровождение.
Здравствуйте, gandjustas, Вы писали:
G>Да повторять можешь сколько влезет, но на твоем фрагменте SQL выругается на алиас "c". Попробуй скопировать его в Management Studio и проверь. G>В этом собственно и проблема текстовых запросов — они должны быть литералами в коде, чтобы их можно было проверить, а это сильно ограничивает возможности программы или множит количество запросов, что усложняет сопровождение.
Ты, кажется, не понимаешь. Если я в GoldCutomer заменю c на c2, то автоматическая проверка мне покажет, где надо еще поправить.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>По поводу Dapper-а и LINQ. Вот разработчик stackoverflow детально описывает real world код. AP>700ms только на то, чтобы сформировать строку запроса (до отправки в СУБД).... 700ms ... 700ms ...
Там такой код для генерации Linq запроса, что сходу руками на SQL его невозможно написать.
Кстати работу с тегами в итоге переписали на отдельный движок, ибо SQL становится плохо от такого количества джоинов.
AP>Процитирую Sam Saffron: AP>
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Да повторять можешь сколько влезет, но на твоем фрагменте SQL выругается на алиас "c". Попробуй скопировать его в Management Studio и проверь. G>>В этом собственно и проблема текстовых запросов — они должны быть литералами в коде, чтобы их можно было проверить, а это сильно ограничивает возможности программы или множит количество запросов, что усложняет сопровождение. AP>Ты, кажется, не понимаешь. Если я в GoldCutomer заменю c на c2, то автоматическая проверка мне покажет, где надо еще поправить.
Да, не понимаю, покажи компилируемый пример с реальной проверкой. Тем более GoldCutomer может быть совсем в другой сборке и вообще не знать о том какой там исходный запрос.
Здравствуйте, gandjustas, Вы писали:
G>Ага, это как раз после написания эффективного запроса с помощью Linq2SQL.
Они перешли на Dapper. Linq2SQL жутко тормозил.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Ага, это как раз после написания эффективного запроса с помощью Linq2SQL. AP>Они перешли на Dapper. Linq2SQL жутко тормозил.
Угу только сначала написали все на Linq2SQL и больше года на нем прожили при нагрузках, которым не видать большинству веб-проектов.
Глупо думать что
1) У тебя будет такая нагрузка что оверхед Linq2SQL или EF будет хоть как-то заметен.
2) Ты сможешь сразу написать все запросы наиболее эффективным образом под каждый сценарий, не сдохнув на поддержке этого дела.
Здравствуйте, gandjustas, Вы писали:
G>Угу только сначала написали все на Linq2SQL и больше года на нем прожили при нагрузках, которым не видать большинству веб-проектов. G>Глупо думать что G>1) У тебя будет такая нагрузка что оверхед Linq2SQL или EF будет хоть как-то заметен. G>2) Ты сможешь сразу написать все запросы наиболее эффективным образом под каждый сценарий, не сдохнув на поддержке этого дела.
О чем ты ....
700 миллисекунд на простейшей страничке с вкладками и одним текстовым полем http://samsaffron.com/archive/2011/09/05/Digging+ourselves+out+of+the+mess+Linq-2-SQL+created
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Угу только сначала написали все на Linq2SQL и больше года на нем прожили при нагрузках, которым не видать большинству веб-проектов. G>>Глупо думать что G>>1) У тебя будет такая нагрузка что оверхед Linq2SQL или EF будет хоть как-то заметен. G>>2) Ты сможешь сразу написать все запросы наиболее эффективным образом под каждый сценарий, не сдохнув на поддержке этого дела. AP>О чем ты .... AP>700 миллисекунд на простейшей страничке с вкладками и одним текстовым полем http://samsaffron.com/archive/2011/09/05/Digging+ourselves+out+of+the+mess+Linq-2-SQL+created
Еще раз: такой запрос как " на простейшей страничке с вкладками и одним текстовым полем " ты в жизни руками на SQL не напишешь. А если напишешь — замучаешься поддерживать и никакой Dapper не поможет.
Кстати в EF вроде как сделали компиляцию запросов на порядок более быстрой.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>О чем ты .... AP>700 миллисекунд на простейшей страничке с вкладками и одним текстовым полем http://samsaffron.com/archive/2011/09/05/Digging+ourselves+out+of+the+mess+Linq-2-SQL+created
Ты упускаешь другое.
Скажем в БД с row-level security — требуется одно.
В SO — требуется совершенно иное. Фактически реально сложных запрсов у них и нет.
Dapper и им подробные — это ошибка природы. Это для тех, кто не понимает, что строки нужно эскейпить, и как правильно это делать. Отстрелить себе яйца с помощью dapper-а — очень легко.
LINQ — же предлагает очень высокоуровненую абстракцию. Со всеми возможными вариантами, я вот делал недавно load testing — я получил, что сервис который генерирует (через linq2db) запросы — тратит <20% процессора (не факт что на LINQ, — вообще). При этом сиквел выжрает — 80% процессора (и то только в том случае если вся база лежит в памяти — а иначе жуткий пенальти по IO который не виден вообще на фоне 700ms).
Так и получаем, что БД — способна обслужить дикое число запросов. Но не стоит забывать что это запросы к реальной БД, к реальному серверу, пусть даже и distributed по новому слову техники. Чем сложнее запрос — тем менее заметны затраты на LINQ.
Ну а если мерить простые запросы (привет dapper) — то и linq2db+реальная БД заточенная на реальную нагрузку на i7-4770 + 32GB RAM позволяет сделать почти 1000 запросов в секунду (по ~10GB БД). При чём итоговая цифра исключительно зависит от того где находятся данные в БД. Если это холодный старт БД и хранилище — HDD — то 3 запроса в секунду. Ну я так, что бы осознали разницу, что дело не в LINQ. А реально дело в RAM и IO.
Да — на фоне — моя тачка показывает теоретический максимум в 20K запросов в секунду. И это кстати на нифига не шустром ASP.NET WebApi. (Правда это с owin-self-hosting — на честном IIS — показатели становятся в 15K). Впрочем это чисто научный интерес — не суть на реал, но даёт ещё одну точку отправки.
Да. Это всё к тому, что — я х.з. что там были у SO проблемы — скорее всего — вылечили какую-то проблему, но не искоренили её. Как уже gandjustas сказал — там были большие бока с тегами. Информация общедоступна если что.
На фоне моих тестов и моих потребностей — я вижу что LINQ в общем — будет тратить <5% от времени обработки запроса. Что тут ещё говорить. При том что я ставлю высокую планку на время обработки запроса — где-то в 30ms.
А самое главное — LINQ-компиляция запросов — отлично масштабируется. Поставить больше "фронтовых" серверов может быть гораздо дешевле (ну а иметь как минимум 2 нужно всё равно иметь, из-за fault tolerance). А вот обеспечить нормальную и правильную логику работы приложения в кластере (при этом по возможности не нагружая медленную БД) — это уже другого характера вопрос.
Поэтмоу для меня — LINQ — отличный инструмент. В нём не всё как мне хочется — но, то что глупо писать хранимки под динамические (или полу-динамические) запросы — это факт. Более того — и у LINQ и у SQL — есть больше шансов выполнить запрос именно так как надо (применив актуальную статистику), нежели когда используем зранимку. Ну а хранимка with recompile будет стоить тоже дорого.
Подитожить я не могу — может gandjustas сможет это сделать более кратко. Заранее, спасибо!
Здравствуйте, fddima, Вы писали:
F> Ну а если мерить простые запросы (привет dapper) — то и linq2db+реальная БД заточенная на реальную нагрузку на i7-4770 + 32GB RAM позволяет сделать почти 1000 запросов в секунду (по ~10GB БД). При чём итоговая цифра исключительно зависит от того где находятся данные в БД. Если это холодный старт БД и хранилище — HDD — то 3 запроса в секунду. Ну я так, что бы осознали разницу, что дело не в LINQ. А реально дело в RAM и IO.
Я извиняюсь — я имел ввиду что не простые запросы. У меня сиквел справляется с почти 1000 запросов в секунду с неочень простыми запросами (они аггрегирующие и затрагивают много данных). Безусловно с простыми запросами навроде select * from something where id = ... справляется крайне быстро, ну от 7000+ (запросов в секунду), и возможно больше.
И то — ессно я не мерял чисто сиквел.
Ты немного удивишься и расстроишься...
Я вот взял Entity Framework последней версии, код из статьи, сгенерировал классы и вот что получилось:
Для начала классы:
Скрытый текст
public enum Filter
{
Active,
Suggested,
Merge
}
public enum Tab
{
Newest,
Master,
Synonym,
Votes,
Creator,
Renames
}
public class DB : DbContext
{
public DbSet<TagSynonym> TagSynonyms { get; set; }
public DbSet<Tag> Tags { get; set; }
public DbSet<UserTagTotal> UserTagTotals { get; set; }
public DbSet<User> Users { get; set; }
}
public class User
{
public int Id { get; set; }
public string DisplayName { get; set; }
}
public class Tag
{
public string Name { get; set; }
public int Id { get; set; }
public int Count { get; set; }
}
public class TagSynonym
{
public DateTime? ApprovalDate { get; set; }
[Key]
[Column(Order = 2)]
public string TargetTagName { get; set; }
public DateTime CreationDate { get; set; }
public string AutoRenameCount { get; set; }
[Key]
[Column(Order = 1)]
public string SourceTagName { get; set; }
public int Score { get; set; }
public int OwnerUserId { get; set; }
}
public class UserTagTotal
{
[Key]
[Column(Order = 1)]
public int TagId { get; set; }
[Key]
[Column(Order = 2)]
public int UserId { get; set; }
public int TotalAnswerScore { get; set; }
}
Сам код выборки из поста, слега адаптированный:
Скрытый текст
static void TestEf(DB db, Filter filter, Tab tab, bool isAnonymous, bool isModerarator, int currentUserId, string search)
{
var baseQuery = db.TagSynonyms as IQueryable<TagSynonym>;
if (filter == Filter.Active)
{
baseQuery = baseQuery.Where(t => t.ApprovalDate != null);
}
else if (filter == Filter.Suggested)
{
baseQuery = baseQuery.Where(t => t.ApprovalDate == null);
if (!isAnonymous && !isModerarator)
{
// exclude ones I can not vote on
baseQuery = from ts in db.TagSynonyms
join tags in db.Tags on ts.TargetTagName equals tags.Name
join stats in db.UserTagTotals on
new { Id = tags.Id, UserId = currentUserId }
equals
new { Id = stats.TagId, UserId = stats.UserId }
where ts.ApprovalDate == null && stats.TotalAnswerScore > 100
select ts;
}
}
switch (tab)
{
case Tab.Newest:
baseQuery = baseQuery.OrderByDescending(s => s.CreationDate);
break;
case Tab.Master:
baseQuery = baseQuery.OrderBy(t => t.TargetTagName).ThenBy(t => t.AutoRenameCount);
break;
case Tab.Synonym:
baseQuery = baseQuery.OrderBy(t => t.SourceTagName).ThenBy(t => t.AutoRenameCount);
break;
case Tab.Votes:
baseQuery = baseQuery.OrderByDescending(t => t.Score).ThenBy(t => t.TargetTagName).ThenBy(t => t.AutoRenameCount);
break;
case Tab.Creator:
baseQuery = (
from s in baseQuery
join users1 in db.Users on s.OwnerUserId equals users1.Id into users1temp
from users in users1temp.DefaultIfEmpty()
orderby users == null ? "" : users.DisplayName
select s
);
break;
case Tab.Renames:
baseQuery = baseQuery.OrderByDescending(t => t.AutoRenameCount).ThenBy(t => t.TargetTagName);
break;
default:
break;
}
if (search != null)
{
baseQuery = baseQuery.Where(t => t.SourceTagName.Contains(search) || t.TargetTagName.Contains(search));
}
var query = from synonym in baseQuery
join sourceTagsTemp in db.Tags on synonym.SourceTagName equals sourceTagsTemp.Name into sourceTagsTemp1
join targetTagsTemp in db.Tags on synonym.TargetTagName equals targetTagsTemp.Name into targetTagsTemp1
from sourceTag in sourceTagsTemp1.DefaultIfEmpty()
from targetTag in targetTagsTemp1.DefaultIfEmpty()
where filter != Filter.Merge || (synonym.ApprovalDate != null && sourceTag != null && sourceTag.Count > 0)
select new { SourceTag = sourceTag, TargetTag = targetTag, TagSynonym = synonym };
query.Load();
}
}
И небольшой тестовый метод, который случайным образом прогоняет выборку для разных значений параметров:
Скрытый текст
Честно переоткрывает контекст и соединение
static TimeSpan RandomTest()
{
using (var db = new DB())
{
var rnd = new Random();
var filterValues = (Filter[]) Enum.GetValues(typeof (Filter));
var filter = filterValues[rnd.Next(filterValues.Length)];
var tabValues = (Tab[]) Enum.GetValues(typeof (Tab));
var tab = tabValues[rnd.Next(filterValues.Length)];
var sw = Stopwatch.StartNew();
TestEf(db, filter, tab, rnd.Next(2) == 0, rnd.Next(2) == 0, rnd.Next(1000),
rnd.Next(2) == 0 ? "aaaa" : "");
sw.Stop();
return sw.Elapsed;
}
}
Функция Main:
static void Main(string[] args)
{
Console.WriteLine("Warming up");
for (int i = 0; i < 1000; i++)
{
RandomTest();
}
Console.WriteLine("Testing");
var results = new List<TimeSpan>();
for (int i = 0; i < 1000; i++)
{
results.Add(RandomTest());
}
Console.WriteLine("Average {0}ms per query", results.Average(ts => ts.TotalMilliseconds));
}
Результат (вдохни поглубже):
Average 2,9131428ms per query
Еще раз по-русски — 2,8 миллисекунд на запрос. Это не только компиляция, это еще открыть соединение (взять из пула, но тоже чего-то стоит) и сбегать в базу (она пустая, но время раундтрипа считается).
Если ты не в курсе, то еще в EF5 прикрутили кеширование скомпилированных Linq запросов, поэтому время амотризированное время компиляции Linq выражений равно нулю.
Если не веришь, то создай консольное приложение в VS2013, установи EF последней версии и скопируй весь код к себе.
Здравствуйте, gandjustas, Вы писали:
G>Еще раз по-русски — 2,8 миллисекунд на запрос. Это не только компиляция, это еще открыть соединение (взять из пула, но тоже чего-то стоит) и сбегать в базу (она пустая, но время раундтрипа считается). G>Если ты не в курсе, то еще в EF5 прикрутили кеширование скомпилированных Linq запросов, поэтому время амотризированное время компиляции Linq выражений равно нулю.
Ох как. Ну в BLT/linq2db такое то давно уже было. Я имел небольшой опыт с EF, скорее всего с 5-ым. Не могу сказать, что супер плохо — но удовольствия тоже не доставил.
PS: Миграции — бред. Не нужны они. Ими заниматься на первом этапе — дольше. На последующих — нужны всё равно нормальные скрипты. Ну и ессно, мы не ведем речь о приложениях которые сами собой там что-то могут преобразовать — им такого позволения "свыше" не дают. Поэтому — механизм интересный (известный опять же задолго до EF) — но муторный.
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, gandjustas, Вы писали:
G>>Еще раз по-русски — 2,8 миллисекунд на запрос. Это не только компиляция, это еще открыть соединение (взять из пула, но тоже чего-то стоит) и сбегать в базу (она пустая, но время раундтрипа считается). G>>Если ты не в курсе, то еще в EF5 прикрутили кеширование скомпилированных Linq запросов, поэтому время амотризированное время компиляции Linq выражений равно нулю. F> Ох как. Ну в BLT/linq2db такое то давно уже было. Я имел небольшой опыт с EF, скорее всего с 5-ым. Не могу сказать, что супер плохо — но удовольствия тоже не доставил.
Где было?
F> PS: Миграции — бред. Не нужны они. Ими заниматься на первом этапе — дольше.
Да ладно? я вот в примере не создавал базу, ef сам сгенерил. Если я реальный проект буду делать, то включу автомагические миграции и первый месяц вообще не буду думать о том как базу на продакшене обновлять.
F>На последующих — нужны всё равно нормальные скрипты.
Миграции в EF генерят скрипты, причем офигенные скрипты, руками так не будешь писать.
F>Ну и ессно, мы не ведем речь о приложениях которые сами собой там что-то могут преобразовать — им такого позволения "свыше" не дают.
Откуда это "свыше" ? Какие-то религиозные убеждения.
F>Поэтому — механизм интересный (известный опять же задолго до EF) — но муторный.
Наоборот, снимает нереальное количество геморроя при разработке и деплое.
Вообще удивительно что 90% комментаторов тупо не доверяют EF, но никаких объективных факторов привести не могут.
Причем не только тут, вот на хабре сегодня же: http://habrahabr.ru/post/227351/#comment_7713649
Здравствуйте, gandjustas, Вы писали:
F>>На последующих — нужны всё равно нормальные скрипты. G>Миграции в EF генерят скрипты, причем офигенные скрипты, руками так не будешь писать.
Что с данными во время миграции?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, gandjustas, Вы писали:
F>> Ох как. Ну в BLT/linq2db такое то давно уже было. Я имел небольшой опыт с EF, скорее всего с 5-ым. Не могу сказать, что супер плохо — но удовольствия тоже не доставил. G>Где было?
Ты сейчас про что? Кеширование запросов было и есть в BLToolkit/linq2db. Есть подобие автоматического, есть и ручное. Насчет ручного — я точно не ошибаюсь — а там дальше — нужно IT призывать. Благо ж форумчанин наш.
G>Да ладно? я вот в примере не создавал базу, ef сам сгенерил. Если я реальный проект буду делать, то включу автомагические миграции и первый месяц вообще не буду думать о том как базу на продакшене обновлять.
А что потом? С таблицами миллионниками не справлялись даже database project от МС (они тупо их рекрейтили, что ессно недопустимо). Я весьма не против такого механизма, но — он должен быть жостко контролируемым. То, из того что я видел в EF — было из рук вон плохо. Что касается сложных конверсий — то это вообще издевательство — заставлять разработчика хренячить скрипты где-то там в приложении (а автоматически модель просто не сможет измениться, т.к. таки да — реструктуризация) — то я так и не понял. Ничего миграции нового, кроме как выполнить реструктуризационные скрипты — не предлагают. Ну и ессно не могут. А примитивыне вещи навроде добавили колонку — с этим благо справляются не только миграции, но и всякие внешние тулзы, которые работают только с БД. Так что х.з. х.з. х.з.
F>>На последующих — нужны всё равно нормальные скрипты. G>Миграции в EF генерят скрипты, причем офигенные скрипты, руками так не будешь писать.
Руками писать так и не надо. Руками нужно писать скрипты создания таблиц и только. И они нужны для последователей. Никому нафиг не нужны эти миграции через 10 лет. Если ты не работал в проекте которому более 20 лет — то наверное не поймёшь важность и исторических решений, и вообще на саппорт смотришь иначе. Я имел такое удовольствие вот. Хотя и твой опыт я под сомнение не ставлю. (Ну честно, не обессуть).
F>>Ну и ессно, мы не ведем речь о приложениях которые сами собой там что-то могут преобразовать — им такого позволения "свыше" не дают. G>Откуда это "свыше" ? Какие-то религиозные убеждения.
Да. Свыше — значит что новая версия продукта разворачивается у клиента, и никакого там DDL в принципе быть не может. Т.е. оно может, но только по согласованию. Соответственно приходим к тому что пофигу каким именно образом накатить изменения. Но точно что неприемлимо — это натихую накатить новую версию продукта которая начнёт чудить в БД.
F>>Поэтому — механизм интересный (известный опять же задолго до EF) — но муторный. G>Наоборот, снимает нереальное количество геморроя при разработке и деплое.
Часть снимет. В перспективе — только добавит. Хотя — зависит от размера.
G>Вообще удивительно что 90% комментаторов тупо не доверяют EF, но никаких объективных факторов привести не могут. G>Причем не только тут, вот на хабре сегодня же: http://habrahabr.ru/post/227351/#comment_7713649
Я резко против EF. Я его могу воспринять только как неизбежное зло. С другой стороны, что какасается технологии/идеи в целом (я о LINQ) — то тут я вижу только преимущества. В мире котором мы живём, и так часто нет выбора — а тут — хочешь — "правильный" linq2sql, хочешь — EF, — хочешь linq2db. В общем — выбирай, что хочешь называется. Конечной принципиальной разницы нет. Поэтому я могу понять кто неприемлит EF — но пока только ты его защищаешь, и требуешь аргументов от других. В этом смысле — тебе никто и ничего не должен и как это водится — все останутся при своём мнении.
Более того — аргументы ни за ни против не нужны — нужен комплексный анализ. По фичам. По скорости. По х.з. чем ещё, до чего мой мозг даже не додумается.
Поэтому именно EF — нахваливать — нет уж. Бред. У них всегда был бред. И модель у них бредовая. Это лично мой взгляд, как ты видишь — в этом конструктива нет — так что не нужно даже пытаться переубеждать.
PS: Неудачный опыт с EF был неудачен не сколько с сами EF, а сколько со спорными решениями вокруг него. На самом деле — отличный инструмент, что бы взять и заюзать. Мне допустим EF абсолютно не подходит, потому что, в случае проблем (а практика показала — что они всегда есть и везде, особенно с такими сложными штуками) — в предпочту код, в котором я хоть немного, но понимаю — а это — linq2db.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
F>>>На последующих — нужны всё равно нормальные скрипты. G>>Миграции в EF генерят скрипты, причем офигенные скрипты, руками так не будешь писать.
IT>Что с данными во время миграции?
Если удаляешь колонки — данные удаляются, если меняешь тип, то пытается конвертировать, если не получается — отваливается. Никаких пересозданий колонок сам не делает.
Так как все в DDL транзакции, то вполне безопасно.
Если связи меняешь, то пишешь скрипт руками.
EF генерит скрипт миграции, который можно посмотреть.
Здравствуйте, gandjustas, Вы писали:
G>Если удаляешь колонки — данные удаляются, если меняешь тип, то пытается конвертировать, если не получается — отваливается. Никаких пересозданий колонок сам не делает. G>Так как все в DDL транзакции, то вполне безопасно. G>Если связи меняешь, то пишешь скрипт руками. G>EF генерит скрипт миграции, который можно посмотреть.
Я тебе скажу из практики. Реальных "миграций", т.е. с серьёзным затрагиванием структуры БД я написал штук 5. При этом даже с этими всеми миграциями — наши продукты жили так как их и не было. Везло. Правда. Но при этом — бред из EF — был бы абсолютно бесполезный.
Но была одна совсем сильная миграция.
Так вот — суть её — это из Nx профилей сделать Mx профилей, где M<N, при том, что в профиле X записей (может отличаться для любого профиля). Уменьшаем их количество по принципу полного совпадения. Соответственно где-то вообще вводится понятие как профиль, и проставляется. Иначе говоря структура БД меняется кардинально, а конечные пользователи вообще вновь видят новое понятие, как профиль. Учитывая, что такая конверсия, даже на топовом железе могла занять скажем минут 30 — то выкладывать такие вещи в миграции — бред. Прежде чем такое сотворить — нужно как минимум сделать бэкап БД (а иначе вообще никто не будет обновляться). И т.п. Поэтому миграции — они круты при мелочах. А реальные изменения — они всё равно покрыть не могут. Возможность исполнять скрипты — я отмечу — у нас у всех и так была. В том числе делать это версионно (хоть руками, хоть с помощью других средств). Поэтому особо ахрененного преимущества в миграциях — я не вижу. Мы о ком забоится? Разработчик до 1 версии всегда способен пересоздать базу хоть 100 раз на день (и нагенерить данные, если необходимо). А в нормальном прадакшне — могут (и будут) требовать вменяемые скрипты апгрейда. А скрипты апгрейда в разработке как раз и не нужны.
В то же время — тулзы которые автоматом деплоят структуру БД — работают. И от МС куча. И вообще. Но работают они именно так же паршиво как я описал.
Учитесь культуре разных проектов, и не навязывайте всем свою. Ваша — многим не подходит.
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, gandjustas, Вы писали:
F>>> Ох как. Ну в BLT/linq2db такое то давно уже было. Я имел небольшой опыт с EF, скорее всего с 5-ым. Не могу сказать, что супер плохо — но удовольствия тоже не доставил. G>>Где было? F> Ты сейчас про что? Кеширование запросов было и есть в BLToolkit/linq2db. Есть подобие автоматического, есть и ручное. Насчет ручного — я точно не ошибаюсь — а там дальше — нужно IT призывать. Благо ж форумчанин наш.
Ручное в EF и Linq2SQL всегда было.
G>>Да ладно? я вот в примере не создавал базу, ef сам сгенерил. Если я реальный проект буду делать, то включу автомагические миграции и первый месяц вообще не буду думать о том как базу на продакшене обновлять. F> А что потом? С таблицами миллионниками не справлялись даже database project от МС (они тупо их рекрейтили, что ессно недопустимо). Я весьма не против такого механизма, но — он должен быть жостко контролируемым.
В ef нет пересоздания вообще. Database project пересоздает таблицы только если ему явно разрешишь, по умолчанию никогда данные не трогает. Я знаю что многие ставили флаги, не зная их смысла, а потом удивлялись.
F>То, из того что я видел в EF — было из рук вон плохо.
Что именно?
F>Что касается сложных конверсий — то это вообще издевательство — заставлять разработчика хренячить скрипты где-то там в приложении (а автоматически модель просто не сможет измениться, т.к. таки да — реструктуризация) — то я так и не понял. Ничего миграции нового, кроме как выполнить реструктуризационные скрипты — не предлагают. Ну и ессно не могут. А примитивыне вещи навроде добавили колонку — с этим благо справляются не только миграции, но и всякие внешние тулзы, которые работают только с БД. Так что х.з. х.з. х.з.
То ест писать скрипты используя EF это плохо, а писать скрипты, не используя EF это нормально?
F>>>На последующих — нужны всё равно нормальные скрипты. G>>Миграции в EF генерят скрипты, причем офигенные скрипты, руками так не будешь писать. F> Руками писать так и не надо. Руками нужно писать скрипты создания таблиц и только. И они нужны для последователей.
Есть такое важное свойство, как идемпотентность. накатывание скрипта миграции можно повторять много раз, а результат будет такой же, как от одного (успешного). Скрипты по умолчанию не сохраняются, накатываются и все.
F> Никому нафиг не нужны эти миграции через 10 лет. Если ты не работал в проекте которому более 20 лет — то наверное не поймёшь важность и исторических решений, и вообще на саппорт смотришь иначе. Я имел такое удовольствие вот. Хотя и твой опыт я под сомнение не ставлю. (Ну честно, не обессуть).
В чем смысл этой фразы? "Давайте не использовать удобный инструмент, ибо через 10 лет не нужен будет". Странно что вообще интернет появился при таком подходе.
F>>>Ну и ессно, мы не ведем речь о приложениях которые сами собой там что-то могут преобразовать — им такого позволения "свыше" не дают. G>>Откуда это "свыше" ? Какие-то религиозные убеждения. F> Да. Свыше — значит что новая версия продукта разворачивается у клиента, и никакого там DDL в принципе быть не может. Т.е. оно может, но только по согласованию. Соответственно приходим к тому что пофигу каким именно образом накатить изменения. Но точно что неприемлимо — это натихую накатить новую версию продукта которая начнёт чудить в БД.
Почему не может? Если это DWH, который клиентом и создан, то в любом случае надо ориентироваться на его структуру, а не пилить свою. А если это база единолично приложением управляется (наиболее частый сценарий), то на кой там что-то согласовывать? И с кем? DBA, которые нифига не понимают в ваших таблицах?
F>>>Поэтому — механизм интересный (известный опять же задолго до EF) — но муторный. G>>Наоборот, снимает нереальное количество геморроя при разработке и деплое. F> Часть снимет. В перспективе — только добавит. Хотя — зависит от размера.
Не вижу причин почему может добавить. Рано или поздно придется писать SQL, других способов нет. Чем позднее придется, тем больше времени заниматься полезными вещами.
G>>Вообще удивительно что 90% комментаторов тупо не доверяют EF, но никаких объективных факторов привести не могут. G>>Причем не только тут, вот на хабре сегодня же: http://habrahabr.ru/post/227351/#comment_7713649 F> Я резко против EF. Я его могу воспринять только как неизбежное зло. С другой стороны, что какасается технологии/идеи в целом (я о LINQ) — то тут я вижу только преимущества. В мире котором мы живём, и так часто нет выбора — а тут — хочешь — "правильный" linq2sql, хочешь — EF, — хочешь linq2db. В общем — выбирай, что хочешь называется. Конечной принципиальной разницы нет. Поэтому я могу понять кто неприемлит EF — но пока только ты его защищаешь, и требуешь аргументов от других. В этом смысле — тебе никто и ничего не должен и как это водится — все останутся при своём мнении.
Профессионалы тем и отличаются от дилетантов, что могут мнение аргументировать. К сожалению ни одного объективного аргумента от противников EF и Linq-to-Database-ORM не увидел вообще. Тем не менее хочется с профессионалами общаться, иначе бы сидел в баре, а не на форуме.
F> Более того — аргументы ни за ни против не нужны — нужен комплексный анализ. По фичам. По скорости. По х.з. чем ещё, до чего мой мозг даже не додумается.
Разве анализ помогает против религиозных аргументов?
F> Поэтому именно EF — нахваливать — нет уж. Бред. У них всегда был бред. И модель у них бредовая. Это лично мой взгляд, как ты видишь — в этом конструктива нет — так что не нужно даже пытаться переубеждать.
Я вот и фичи приводил, и тест производительности и все равно ни одного объективного аргумента, только "бред".
F> PS: Неудачный опыт с EF был неудачен не сколько с сами EF, а сколько со спорными решениями вокруг него. На самом деле — отличный инструмент, что бы взять и заюзать. Мне допустим EF абсолютно не подходит, потому что, в случае проблем (а практика показала — что они всегда есть и везде, особенно с такими сложными штуками) — в предпочту код, в котором я хоть немного, но понимаю — а это — linq2db.
В чем же такая огромная разница между EF и linq2db? Последний я, к сожалению, юзал еще до старта этой темы.
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, gandjustas, Вы писали:
G>>Если удаляешь колонки — данные удаляются, если меняешь тип, то пытается конвертировать, если не получается — отваливается. Никаких пересозданий колонок сам не делает. G>>Так как все в DDL транзакции, то вполне безопасно. G>>Если связи меняешь, то пишешь скрипт руками. G>>EF генерит скрипт миграции, который можно посмотреть. F> Я тебе скажу из практики. Реальных "миграций", т.е. с серьёзным затрагиванием структуры БД я написал штук 5. При этом даже с этими всеми миграциями — наши продукты жили так как их и не было. Везло. Правда. Но при этом — бред из EF — был бы абсолютно бесполезный.
F> Но была одна совсем сильная миграция. F> Так вот — суть её — это из Nx профилей сделать Mx профилей, где M<N, при том, что в профиле X записей (может отличаться для любого профиля). Уменьшаем их количество по принципу полного совпадения. Соответственно где-то вообще вводится понятие как профиль, и проставляется. Иначе говоря структура БД меняется кардинально, а конечные пользователи вообще вновь видят новое понятие, как профиль.
Всего-то?
F>Учитывая, что такая конверсия, даже на топовом железе могла занять скажем минут 30 — то выкладывать такие вещи в миграции — бред. Прежде чем такое сотворить — нужно как минимум сделать бэкап БД (а иначе вообще никто не будет обновляться). И т.п.
Какой-то неправильный подход.
Надо было:
1) Создать таблицу для M
2) Сделать триггер\эвент в приложении, который при добавлении\изменении записи в N реплицирует данные в M
3) Выкатить эту версию, отладить, проверить что в M данные корректные
4) Сделать скрипт для миграции всех записей N в M
5) Перелить данные, проверить что все ОК
6) Поменять код для работы с новой таблицей, задеплоить изменения.
Можно даже без бекапа, вероятность что-то сломать при таком подходе гораздо ниже, чем при ломающей миграции. Схему данных при этом легко накатывать миграциями.
У меня были миграции, которые длились по 48 часов без права на ошибку. Бекапы то были, но остановить работу сервиса было нельзя. Там я навегда расстался с мыслью об "одной большой реструктуризации базы".
F>Поэтому миграции — они круты при мелочах.
Правильно, вот и разбивай крупные миграции, на мелочи.
F>А реальные изменения — они всё равно покрыть не могут.
Ну смотря что считать "реальными изменениями".
F>Возможность исполнять скрипты — я отмечу — у нас у всех и так была. В том числе делать это версионно (хоть руками, хоть с помощью других средств). Поэтому особо ахрененного преимущества в миграциях — я не вижу.
Миграции синхронизируют исполнение скриптов с изменением кода. Для этого они и были придуманы.
F>Мы о ком забоится? Разработчик до 1 версии всегда способен пересоздать базу хоть 100 раз на день (и нагенерить данные, если необходимо). А в нормальном прадакшне — могут (и будут) требовать вменяемые скрипты апгрейда. А скрипты апгрейда в разработке как раз и не нужны.
Вот и получается ситуация что в базе разработчика одна структура, на продакшене другая, а в коде третья. И не ясно кто прав, хотя в команде только 3 человека.
F> В то же время — тулзы которые автоматом деплоят структуру БД — работают. И от МС куча. И вообще. Но работают они именно так же паршиво как я описал.
Какая куча? У МС ровно один такой инструмент — Database Project. В ef второй, и все.
F> Учитесь культуре разных проектов, и не навязывайте всем свою. Ваша — многим не подходит.
Я никому культуру не навязываю, я спрашиваю аргументы.
Здравствуйте, gandjustas, Вы писали:
G>Результат (вдохни поглубже): G>
G>Average 2,9131428ms per query
G>
Сначала надо воспроизвести "багу", потом уже демонстрировать ее устранение. Покажи сначала 700ms на LINQtoSQL, потом 2,9ms на EF. Или покажи, что Sam Saffron врет.
А так не понятно, что за цифры ты привел. Скриншотам MiniProfiler-а с реального продакшена от Sam Saffron более убедительны, чем твои выдуманные примеры.
G>Все что ты озвучивал конкретное касалось старых версий.
И по прежнему актуально для текущей.
G>Про "неадекватность идеи" как не было ответа, так и нет.
Было — почитай внимательнее. Неадекватность идеи заключается в попытке создать FullBlown ORM с попыткой полностью абстрагироваться от БД с не явным LazyLoading-ом и шлюхами. Первое понимание того, что эта абстракция дырявая стало приходить еще лет 10-15 назад по опыту использования EJB, а к моменту факапа WinFS это стало очевидно большинству практикующих разработчиков, но некоторые теоретики до сих пор упорствуют в своем заблуждении... А в данном случае, все было реализовано еще и в гипертрофированном варианте, когда создается некоторая промежуточная метамодель данных через которую и ведется вся работа с БД и кодом. Именно эта идея дожила со времен ObjecSpaces, и именно этот кусок прибит к EF гвоздями и не позволяет сделать из него приличный продукт.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>Все что ты озвучивал конкретное касалось старых версий. IB>И по прежнему актуально для текущей.
Нет, не актуально.
G>>Про "неадекватность идеи" как не было ответа, так и нет. IB>Было — почитай внимательнее. Неадекватность идеи заключается в попытке создать FullBlown ORM с попыткой полностью абстрагироваться от БД с не явным LazyLoading-ом и шлюхами.
Что такое FullBlown ORM, чем он отличается от не-FullBlown ?
LL по умолчанию выключен для code-first.
IB>Первое понимание того, что эта абстракция дырявая стало приходить еще лет 10-15 назад по опыту использования EJB, а к моменту факапа WinFS это стало очевидно большинству практикующих разработчиков, но некоторые теоретики до сих пор упорствуют в своем заблуждении... А в данном случае, все было реализовано еще и в гипертрофированном варианте, когда создается некоторая промежуточная метамодель данных через которую и ведется вся работа с БД и кодом.
Метамодель есть в любом ORM, так как одни и те же Linq запросы могут по разному мапиться в разных СУБД. Ты считаешь что это плохо?
IB>Именно эта идея дожила со времен ObjecSpaces, и именно этот кусок прибит к EF гвоздями и не позволяет сделать из него приличный продукт.
Эта фраза ни о чем, ибо программист, использующий Code First никогда эту метамодель не увидит. Вообще modеl-first подход, который ты пытаешься ругать, не используется по факту нигде. Даже из готовой базы ef предлагает сгенерировать code-first модель и не париться с edmx.
Повторю — твое мнение основано на ef версии 1.0, которая была 5 лет назад. Конечно можно использовать ef6 так же как первую версию, но никто тебя не заставляет это делать.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Результат (вдохни поглубже): G>>
G>>Average 2,9131428ms per query
G>>
AP>Сначала надо воспроизвести "багу", потом уже демонстрировать ее устранение. Покажи сначала 700ms на LINQtoSQL, потом 2,9ms на EF. Или покажи, что Sam Saffron врет.
Хорошая идея, сделал модель Linq2SQL по базе, сгенерированной ef, оставил тот же тестовый код и получилось 9мс на запрос.
После этого перечитал пост Сэма и выяснил несколько вещей:
Во-первых 700мс это время между предыдущим событием в логе и следующим, даже если принять на веру что все это Linq2SQL, то...
Во-вторых причины исходного тормозняка остались неизвестны, это могло быть:
1) Тупо тормоза в СУБД из-за неэффективного плана
2) Старая версия Linq2SQL до .NET 4.5 работала значительно медленнее (от генерации SQL, то материализации объектов), хотя пост и написан в 2011 году, могли использовать еще .NET 3.5
3) Проблемы, связанные с конкурентным доступом
Да, переход на Dapper исправляет всю пачку проблем, но вполне возможно что значительного ускорения можно было бы добиться другими средствами. Но, к сожалению, у Сэма большой bias в сторону Dapper.
В-третьих — нету результатов "забегов", только декларация что стало сильно быстрее. Есть подозрение, что кроме переписывания на Dapper еще много чего было подкручено.
Кстати на сегодня в EF подавляющее большинство проблем, которые возникали в Linq2SQL были поправлены.
AP>А так не понятно, что за цифры ты привел. Скриншотам MiniProfiler-а с реального продакшена от Sam Saffron более убедительны, чем твои выдуманные примеры.
Специально для тебя опубликовал все исходники. Скопируй их в свое решение и прогони тесты.
Здравствуйте, gandjustas, Вы писали:
G>Если связи меняешь, то пишешь скрипт руками. G>EF генерит скрипт миграции, который можно посмотреть.
Понятно. Всё как обычно, в простейших случаях, особенно годных для демонстраций, работает, а что-то чуть сложнее, то нужно самому закатывать рукава. Чудес всё-таки не бывает. В таком случае мне лично кажутся более предпочтительными традиционные решения.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, fddima, Вы писали:
F> Ты сейчас про что? Кеширование запросов было и есть в BLToolkit/linq2db. Есть подобие автоматического, есть и ручное. Насчет ручного — я точно не ошибаюсь — а там дальше — нужно IT призывать. Благо ж форумчанин наш.
Кеширование ET было изначально. А вот ручной Compile появился не сразу и то, только потому, что публика хотела. В реальности в L2DB/BLT он даёт прирост всего в несколько процентов.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
G>>Если связи меняешь, то пишешь скрипт руками. G>>EF генерит скрипт миграции, который можно посмотреть.
IT>Понятно. Всё как обычно, в простейших случаях, особенно годных для демонстраций, работает, а что-то чуть сложнее, то нужно самому закатывать рукава. Чудес всё-таки не бывает. В таком случае мне лично кажутся более предпочтительными традиционные решения.
От написания скриптов не денешься никуда, миграции лишь синхронизируют запуск скриптов и обновление кода.
Здравствуйте, gandjustas, Вы писали:
G>Нет, не актуально.
Актуально.
G>LL по умолчанию выключен для code-first.
mode=off, вовсе не означает, что этот механизм не вмешивается в работу. Мне реально лень повторять то, что я писал два года назад — отмотай топик, там подробно расписаны все мои претензии к LL и тому как он якобы "отключается".
G>Метамодель есть в любом ORM, так как одни и те же Linq запросы могут по разному мапиться в разных СУБД.
В твоем утверждении сразу несколько ошибок. Во-первых далеко не все ORM рассчитаны на работу с несколькими СУБД, а во-вторых — наличие метамодели не является необходимым условием для маппинга из линка в SQL, так как POCO классы в купе с метаданными — вполне себе универсальная модель и нет совершенно никаких причин придумывать еще какого-то посредника.
G>Ты считаешь что это плохо?
Да. Так как лишняя косвенность, только усугубляет проблемы трансляции из одного языка в другой.
G>Эта фраза ни о чем, ибо программист, использующий Code First никогда эту метамодель не увидит.
Совершенно не важно, видит он ее или нет. Важно что эта модель занимает память и время, и ухудшает качество генерируемого SQL. Так что нет, эта фраза очень даже о чем.
code-first — это вообще отдельный бред, ну да и без него проблем хватает, так что даже не буду начинать.
G>Повторю — твое мнение основано на ef версии 1.0, которая была 5 лет назад.
Мое мнение основано на последней версии EF, которую я весьма подробно изучил с целью перехода на нее наших продуктов, после чего выкинул и вымыл руки с мылом.
IT>Кеширование ET было изначально. А вот ручной Compile появился не сразу и то, только потому, что публика хотела. В реальности в L2DB/BLT он даёт прирост всего в несколько процентов.
С EF все еще хуже, там выигрыш за счет кеширования — просто другой порядок малости по сравнению с тем на сколько неэффективный SQL он генерит.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>Нет, не актуально. IB>Актуально.
Ни капли.
G>>LL по умолчанию выключен для code-first. IB>mode=off, вовсе не означает, что этот механизм не вмешивается в работу.
Не вмешивается вообще, не генерируются прокси, для всех коллекций просто значение null.
IB>Мне реально лень повторять то, что я писал два года назад — отмотай топик, там подробно расписаны все мои претензии к LL и тому как он якобы "отключается".
Это уже давно не актуально. Ты вообще видел code-first в EF6?
G>>Метамодель есть в любом ORM, так как одни и те же Linq запросы могут по разному мапиться в разных СУБД. IB>В твоем утверждении сразу несколько ошибок. Во-первых далеко не все ORM рассчитаны на работу с несколькими СУБД, а во-вторых — наличие метамодели не является необходимым условием для маппинга из линка в SQL, так как POCO классы в купе с метаданными — вполне себе универсальная модель и нет совершенно никаких причин придумывать еще какого-то посредника.
А метаданные и метамодель чем отличаются?
G>>Ты считаешь что это плохо? IB>Да. Так как лишняя косвенность, только усугубляет проблемы трансляции из одного языка в другой.
Ты code-first видел? Там нет никакой косвенности.
G>>Эта фраза ни о чем, ибо программист, использующий Code First никогда эту метамодель не увидит. IB>Совершенно не важно, видит он ее или нет. Важно что эта модель занимает память и время, и ухудшает качество генерируемого SQL. Так что нет, эта фраза очень даже о чем.
А метаданные для мепинга не занимаюсь память и время? И улучшают SQL?
Особенно интересно как это происходит когда классы мапятся 1-в-1 на базу.
Пример приведешь? Или только голословные утверждения будут?
IB>code-first — это вообще отдельный бред, ну да и без него проблем хватает, так что даже не буду начинать.
О, да, одни факты.
G>>Повторю — твое мнение основано на ef версии 1.0, которая была 5 лет назад. IB>Мое мнение основано на последней версии EF, которую я весьма подробно изучил с целью перехода на нее наших продуктов, после чего выкинул и вымыл руки с мылом.
Знаешь что странно, ты говорил тоже самое два года назад (слово в слово). Про те же самые проблемы. Проблемы исправили (с тем же LL), а слова ты продолжаешь повторять.
Это наводит на мысль, что 2 года назад крайний раз ты и видел ef, причем видимо версии 4.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, IT, Вы писали:
IT>>Кеширование ET было изначально. А вот ручной Compile появился не сразу и то, только потому, что публика хотела. В реальности в L2DB/BLT он даёт прирост всего в несколько процентов. IB>С EF все еще хуже, там выигрыш за счет кеширования — просто другой порядок малости по сравнению с тем на сколько неэффективный SQL он генерит.
Покажи пример где EF последней версии генерит неэффективный запрос.
Здравствуйте, gandjustas, Вы писали:
G>От написания скриптов не денешься никуда, миграции лишь синхронизируют запуск скриптов и обновление кода.
Не совсем так. В подавляющем большинстве случаев удаётся изменить структуру базы с сохранением данных путём пошагового применения тулов и несложных скриптов. Написание же одного сложного скрипта связано с одной серьёзной проблемой — его отладкой.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
G>>От написания скриптов не денешься никуда, миграции лишь синхронизируют запуск скриптов и обновление кода.
IT>Не совсем так. В подавляющем большинстве случаев удаётся изменить структуру базы с сохранением данных путём пошагового применения тулов и несложных скриптов. Написание же одного сложного скрипта связано с одной серьёзной проблемой — его отладкой.
Ну так заверни тоже самое в миграции и все эти шаги будут еще и синхронно с обновлением кода идти. Кто тебе сказал что надо писать сложные скрипты? Наоборот, в миграциях надо писать очень простые скрипты.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
G>>Метамодель есть в любом ORM, так как одни и те же Linq запросы могут по разному мапиться в разных СУБД.
IT>А в чём тут проблема, если не секрет?
Неправильно написал. Я имел ввиду что в одном случае могут использоваться DML операторы, а в другом будет мапинг сущностей на хранимки.
Здравствуйте, gandjustas, Вы писали:
G>Ни капли.
Вера — страшная штука, мне совершенно не интересно тебя убеждать, если веришь что там проблем нет, значит для тебя это так.
G>Не вмешивается вообще, не генерируются прокси, для всех коллекций просто значение null.
проблема не в null, а в том, что когда пытаешься построить запрос — летит исключение.
G>Это уже давно не актуально. Ты вообще видел code-first в EF6?
Да задрал уже. Да, я видел 6.0, я смотрел code-first. Очевидно там где-то завелся генератор ущербных идей, они берут все худшее из других проектов и доводят это до абсурда.
G>А метаданные и метамодель чем отличаются?
Тем, что метамодель это дополнительный набор сущностей, которые служат посредниками между POCO с метаданными и базой. И весь маппинг выполняется через этого посредника. Ни скорости, ни оптимальности запросам этот посредник не добавляет, а делает совсем наоборот.
G>Ты code-first видел? Там нет никакой косвенности.
Да-да, нет никакой ложки.
G>Пример приведешь? Или только голословные утверждения будут?
Не веришь мне — поверь самим разработчикам. " As a result, there are many seldom used features and capabilities in the code base that hamper performance and complicate development, but are not feasible to remove due to the monolithic nature of the implementation."
У них, конечно, тоже только голословные утверждения, но к счастью они обладают возможностью выкинуть это изделие на свалку, что они с сделали.
G>Знаешь что странно, ты говорил тоже самое два года назад (слово в слово). Про те же самые проблемы.
Так с тех пор ничего принципиально не поменялось. А говорить я это начал не два года назад, а практически с момента появления EF, при этом относительно тщательно изучая каждый их новый релиз. Но поскольку проблемы там скорее идеологические, то хвосты ObjectSpaces там торчат до сих пор, как следствие, суть моих претензий не поменялась. А теперь наконец и разработчики признали, что зашли в тупик.
G>Всетаки изучи ef6, начни отсюда: http://msdn.microsoft.com/en-US/data/ee712907#codefirst
Изучать EF нет никакого смысла, его наконец-то похоронили. Даже разработчики признали, что фигня получилась, так что не понимаю чего ты тут с таким жаром защищаешь.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>Ни капли. IB>Вера — страшная штука, мне совершенно не интересно тебя убеждать, если веришь что там проблем нет, значит для тебя это так.
Это ты уверяешь что проблемы есть, но примеры не приводишь. Воистину — вера страшная штука.
G>>Не вмешивается вообще, не генерируются прокси, для всех коллекций просто значение null. IB>проблема не в null, а в том, что когда пытаешься построить запрос — летит исключение.
Покажи пример
G>>Это уже давно не актуально. Ты вообще видел code-first в EF6? IB>Да задрал уже. Да, я видел 6.0, я смотрел code-first. Очевидно там где-то завелся генератор ущербных идей, они берут все худшее из других проектов и доводят это до абсурда.
Судя по тому что ты пишешь — нет.
G>>А метаданные и метамодель чем отличаются? IB>Тем, что метамодель это дополнительный набор сущностей, которые служат посредниками между POCO с метаданными и базой. И весь маппинг выполняется через этого посредника. Ни скорости, ни оптимальности запросам этот посредник не добавляет, а делает совсем наоборот.
А атрибуты не добавляют? Такие же классы, также через них маппинг делется.
G>>Знаешь что странно, ты говорил тоже самое два года назад (слово в слово). Про те же самые проблемы. IB>Так с тех пор ничего принципиально не поменялось. А говорить я это начал не два года назад, а практически с момента появления EF, при этом относительно тщательно изучая каждый их новый релиз. Но поскольку проблемы там скорее идеологические, то хвосты ObjectSpaces там торчат до сих пор, как следствие, суть моих претензий не поменялась. А теперь наконец и разработчики признали, что зашли в тупик.
Ты как-то хитро отбросил часть моей фразы про исправление конкретных проблем. Твои идеи по поводу "идеологии" не интересуют вообще, я про конкретику уже хрен знает какой раз спрашиваю, а ответа все нет, ты все про идеологию.
G>>Всетаки изучи ef6, начни отсюда: http://msdn.microsoft.com/en-US/data/ee712907#codefirst IB>Изучать EF нет никакого смысла, его наконец-то похоронили. Даже разработчики признали, что фигня получилась, так что не понимаю чего ты тут с таким жаром защищаешь.
Не похоронили, а наконец собрались переписать. Текущая версия отлично работает для тех сценариев, для которых она заточена.
С точки зрения API в новой версии мало что изменится, будет вполне нормальный upgrade path.
Здравствуйте, gandjustas, Вы писали:
G>Да, не понимаю, покажи компилируемый пример с реальной проверкой. Тем более GoldCutomer может быть совсем в другой сборке и вообще не знать о том какой там исходный запрос. Вот тут код. Если в строке с номером 29 заменить "c" на "c2", то автоматическая проверка укажет, что надо внести изменения в запросы в строках с номерами 5 и 12.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Да, не понимаю, покажи компилируемый пример с реальной проверкой. Тем более GoldCutomer может быть совсем в другой сборке и вообще не знать о том какой там исходный запрос. AP>Вот тут код. Если в строке с номером 29 заменить "c" на "c2", то автоматическая проверка укажет, что надо внести изменения в запросы в строках с номерами 5 и 12.
1) чем это компилировать?
2) где гарантия что GoldCutomer надо вызвать для списка кастомеров?
3) что будет если GoldCutomer будет определен в другой сборке?
Здравствуйте, gandjustas, Вы писали:
G>1) чем это компилировать?
Приведенный код компилируется обычным C# компилятором. Для проверки запросов надо дернуть метод CheckAllQueries
G>2) где гарантия что GoldCutomer надо вызвать для списка кастомеров?
Метод GoldCutomer просто подставляет кусок текста. Проверяется лишь, что итоговый запрос валидный. Т.е. если "с" будет иметь нужные колонки, то проверка пройдет.
G>3) что будет если GoldCutomer будет определен в другой сборке?
При компиляции Razor шаблона подставляются все сборки, на которые ссылается сборка с запросом. Можно и явно задавать набор сборок и using-ов, привязывая их к (MethodBase method, string file, int line). method -- метод, в котором находится запрос.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Да, не понимаю, покажи компилируемый пример с реальной проверкой. Тем более GoldCutomer может быть совсем в другой сборке и вообще не знать о том какой там исходный запрос. AP>Вот тут код. Если в строке с номером 29 заменить "c" на "c2", то автоматическая проверка укажет, что надо внести изменения в запросы в строках с номерами 5 и 12.
Ну и самый главный косяк. У тебя по сути нет комбинирования запросов. Если добавить в Cutomer поле, то его надо будет прописать во все релевантные запросы. Для linq надо будет поправить функцию, накладывающую проекцию на запрос.
Здравствуйте, gandjustas, Вы писали:
G>Ну и самый главный косяк. У тебя по сути нет комбинирования запросов. Если добавить в Cutomer поле, то его надо будет прописать во все релевантные запросы. Для linq надо будет поправить функцию, накладывающую проекцию на запрос.
Комбинирование запросов было в SQL испокон веков. А склейка строк позволяет реюзать код, т.е. текст.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>1) чем это компилировать? AP>Приведенный код компилируется обычным C# компилятором. Для проверки запросов надо дернуть метод CheckAllQueries AP>
G>>2) где гарантия что GoldCutomer надо вызвать для списка кастомеров? AP>Метод GoldCutomer просто подставляет кусок текста. Проверяется лишь, что итоговый запрос валидный. Т.е. если "с" будет иметь нужные колонки, то проверка пройдет.
Ну вот, кусок текста... получается что тот кто вызывает функцию goldCustomer должен знать что она возвращает и специальным образом адаптировать исходный запрос. Такому подходу до удобства linq как дол Китая.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>... развитые средства декомпозиции дают вполне неиллюзорные бенефиты.
Подожди, о каких "развитых" средствах декомпозиции идет речь?
Вот если у меня IEnumerable<T>, то, да, декомпозиция, действительно развитая, это факт. Например,
IEnumerable<int> ints = ...;
ints.Where(x => MyMethod(x, c1, c2) || (x > c3 && x < c4));
private static bool MyMethod(int x, int c1, int c2)
{
return (x > c1 && x < c2);
}
Буквально, выделяю фрагмент кода, и ReSharper мне делает декомпозицию. Красота!
А если у нас IQueryable<T>? Упс, уже совсем не так всё радужно. Как мне кусок кода выделить в отдельную единицу -- метод MyMethod?
Для IQueryable<T> у нас остаются довольно убогие средства декомпозиции.
1. Подать экспрешен на в ход в другой экспрешен.
2. В логических выражениях "вырезать" подвыражение, объединяя его с какой-нибудь внешней переменной через оператор &&, полагаясь на оптимизатор linq провайдера.
Разве еще что-то есть для декомпозиции?
Сам Anders Hejlsberg для динамических запросов предлагает склейку строк. О каких развитых средствах декомпозиции вы толкуете, не дизайнился LINQ для динамических запросов к БД.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>А если у нас IQueryable<T>? Упс, уже совсем не так всё радужно. Как мне кусок кода выделить в отдельную единицу -- метод MyMethod?
Очень странный вопрос. В чем проблема?
AP>Для IQueryable<T> у нас остаются довольно убогие средства декомпозиции. AP>1. Подать экспрешен на в ход в другой экспрешен.
Здравствуйте, gandjustas, Вы писали:
G>Выложи куданить проект.
Собираюсь выложить на github.
G>Ну вот, кусок текста... получается что тот кто вызывает функцию goldCustomer должен знать что она возвращает и специальным образом адаптировать исходный запрос. Такому подходу до удобства linq как дол Китая.
Во-первых, ничего адаптировать не надо, это ты бредишь.
А если поразмышлять, то сколько-нибудь значимой проблемы либо нет, либо это даже бонус. Вот в TypeScript переменная имеет тип интерфейс, и этой переменной можно присваивать объекты, которые и не знают об этом интерфейсе. Только само присвоение вызывает проверку. А в моем примере пошли еще чуть дальше, и интерфейс объявлять не надо, интерфейс определяется из использования столбцов. Я бы и в C# от такого не отказался, но, наверное, это сильно дорого делать такое на больших объемах кода, поэтому и прописывают декларации в явном виде.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Очень странный вопрос. В чем проблема?
Приведи свой вариант кода для IQueryable того, что я сделал для IEnumerable. Выдели метод MyMethod.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Выложи куданить проект. AP>Собираюсь выложить на github.
G>>Ну вот, кусок текста... получается что тот кто вызывает функцию goldCustomer должен знать что она возвращает и специальным образом адаптировать исходный запрос. Такому подходу до удобства linq как дол Китая. AP>Во-первых, ничего адаптировать не надо, это ты бредишь. AP>А если поразмышлять, то сколько-нибудь значимой проблемы либо нет, либо это даже бонус. Вот в TypeScript переменная имеет тип интерфейс, и этой переменной можно присваивать объекты, которые и не знают об этом интерфейсе. Только само присвоение вызывает проверку. А в моем примере пошли еще чуть дальше, и интерфейс объявлять не надо, интерфейс определяется из использования столбцов. Я бы и в C# от такого не отказался, но, наверное, это сильно дорого делать такое на больших объемах кода, поэтому и прописывают декларации в явном виде.
Самое главное find usages и рефакторинг работают, а остальное всё словоблудие.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Выложи куданить проект. AP>Собираюсь выложить на github.
G>>Ну вот, кусок текста... получается что тот кто вызывает функцию goldCustomer должен знать что она возвращает и специальным образом адаптировать исходный запрос. Такому подходу до удобства linq как дол Китая. AP>Во-первых, ничего адаптировать не надо, это ты бредишь.
во-первых бредишь ты, во вторых в запросе к Customers обязательно надо прописать алиас «c», причем из скомпилированной сборки ты этого не узнаешь, в третьих GoldCustomer не будет проверяться без основного запроса, ибо даже не является корректным sql.
AP>А если поразмышлять, то сколько-нибудь значимой проблемы либо нет, либо это даже бонус.
Можно и поразмышлять, но проблемы никуда не денутся. Затраты на написание, бакфикс и поддержку с идеологией никак не связаны, как бы не казалось обратное.
AP> Вот в TypeScript переменная имеет тип интерфейс, и этой переменной можно присваивать объекты, которые и не знают об этом интерфейсе. Только само присвоение вызывает проверку. А в моем примере пошли еще чуть дальше, и интерфейс объявлять не надо, интерфейс определяется из использования столбцов. Я бы и в C# от такого не отказался, но, наверное, это сильно дорого делать такое на больших объемах кода, поэтому и прописывают декларации в явном виде.
Как коррелирует то что ты написал со склейкой строк?
Здравствуйте, Alexander Polyakov, Вы писали:
AP>А если у нас IQueryable<T>? Упс, уже совсем не так всё радужно. Как мне кусок кода выделить в отдельную единицу -- метод MyMethod?
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали:
G>>Ну и самый главный косяк. У тебя по сути нет комбинирования запросов. Если добавить в Cutomer поле, то его надо будет прописать во все релевантные запросы. Для linq надо будет поправить функцию, накладывающую проекцию на запрос. AP>Комбинирование запросов было в SQL испокон веков. А склейка строк позволяет реюзать код, т.е. текст.
Да ну? Подскажи как в sql взять запрос (как объект) и применить к нему функцию, добавляющую например предикат к запросу и возвращающую новый «объект» запроса. Аналог where в Linq.
Любой кто познал выгоду между параметризированными запросами и перед запросами с константами — тот поймет и всю силу статистики и прочу ересь которая в кверике выполняется моментально — а в приложении — нет.
Так вот — я к чему — LINQ — это как раз инструмент, который, особенно если очень захотеть, заставит исполнять запросы с параметризаций as-is. А это значит и с применением статистики. Это именно то чего не дают процедуры (хотя процедуры дают своё в другом) — тем не менее — если взять в среднем по палате — ну у меня не получается сиквел загрузить. А вот загрузить его тупыми запросами которые скомпилированы (в случае проц) под общий случай — этого говна было навалом. Безусловно WITH RECOMPILE помогает везде и всем — только как только защитники SP спускаются к WITH RECOMPILE — это значит что те кто юзают LINQ — имеют такое же право. А это всё в своё очередь означает следующее:
1) Сиквел ахриненно вычисляет совсем уж похожие запросы и так (даже с другими параметрами), хотя это — критиковать можно
2) Поборники хранимок — очнитесь — мир давно перевернулся, и реально запросы легче писать тем же LINQ. Более того — они имеют шанс выполняться более эффективно.
Насчет второго — я расскажу так. Запрос в хранимке компилируется обычно и хана. Пока никто не наступит на то, что его параметры совсем не подходят к их плану — WITH RECOMPILE — процу не метит. Только прежде чем обнаружить такую проблему — ну это скажем так часов 2-8 простоя весьма немалых организаций. Поэтому рассказывать о том что там надо или не надо следить — не нужно тут мне. Следить надо. По факту — специалистов которые знают за чем *можно* следить — нет.
Как тут выигрывает LINQ? Если есть нетривиальные запросы — он просто будет константно выигрывать, против старого доброго процедурного подхода. Будет сиквет перекомпилировать запрос всегда? Да. Ну почти да.
Будет ли это быстрее? Ну скорее всего да. Самое главное не в этом — при появлении входных данных которые выбиваются из общей канвы — всё по прежнему будет работать.
Ну а знатоки проц — знают — без WITH RECOMPILE — это не победимо — кто первый дернул её со своими параметрами — того и план. А эффективен он или нет — сиквелу как бы пофигу.
PS: Я знаю, что тема немного о другом — но и об этом тоже. Выгоднее ли исполнять хранимки — конечно да. Выгоднее ли всегда — далеко не факт. Можно ли забить на этот анархизм? Конечно нет! Но LINQ в любом своём проявлении особенно с linq2db — точно показывает себя более чем достойно.
Да. Поборники достойности — мой десктоп способен обслужить 7K+ запросов весьма нифика не простых запросов. И это всё через LINQ. RAW — будет быстрее. Но — ещё быстрее — будет без SQL вообще. Так что заранее прошу — глупости тут не городить. Да. Без сиквела — 20K+.
Здравствуйте, gandjustas, Вы писали:
AP>>А если у нас IQueryable<T>? Упс, уже совсем не так всё радужно. Как мне ку7сок кода выделить в отдельную единицу -- метод MyMethod? G>Да легко http://gandjustas.blogspot.ru/2010/06/expression-tree.html7
Отлично, те "развитые" средства декомпозиции, которые преподносятся как основное killer application для linq к БД, оказывается изложены в русскоязычном блоге некоего gandjustas. Это еще раз подтверждает, что разработчики linq не дизайнели его для динамических запросов к БД.
То такой код даже не скомпилируется, потому что e1.Entity2 не реализует интерфейс IQueryable<T>. Даже если бы такой ко компилировался, то наверняка отвалился бы в runtume, потому что Linq провайдер не знает что делать с методом Visible.
...
Но какой тип должен быть у предиката Visible? ...
Т.е. боремся с этими несчастными экспрешенами, вместо того, чтобы писать запрос, который реализует бизнес-логику (реализацию, которой нам и оплачивает заказчик). Голова программиста занята борьбой с экспрешенами, типами и т.д., вместо того, чтобы заниматься прямыми обязанностями по реализации бизнес-логики.
Слишком дорого. За что мы платим такую цену? За проверку ошибок на этапе компиляции, find usages и рефакторинг. Но есть вариант всё это получить гораздо дешевле.
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, gandjustas, Вы писали:
F>Ребята, я всем очень благодарен за участие.
F>Но спорите не о том.
F>Любой кто познал выгоду между параметризированными запросами и перед запросами с константами — тот поймет и всю силу статистики и прочу ересь которая в кверике выполняется моментально — а в приложении — нет.
F>Так вот — я к чему — LINQ — это как раз инструмент, который, особенно если очень захотеть, заставит исполнять запросы с параметризаций as-is. А это значит и с применением статистики. Это именно то чего не дают процедуры (хотя процедуры дают своё в другом) — тем не менее — если взять в среднем по палате — ну у меня не получается сиквел загрузить. А вот загрузить его тупыми запросами которые скомпилированы (в случае проц) под общий случай — этого говна было навалом. Безусловно WITH RECOMPILE помогает везде и всем — только как только защитники SP спускаются к WITH RECOMPILE — это значит что те кто юзают LINQ — имеют такое же право. А это всё в своё очередь означает следующее: F> 1) Сиквел ахриненно вычисляет совсем уж похожие запросы и так (даже с другими параметрами), хотя это — критиковать можно F> 2) Поборники хранимок — очнитесь — мир давно перевернулся, и реально запросы легче писать тем же LINQ. Более того — они имеют шанс выполняться более эффективно.
F> Насчет второго — я расскажу так. Запрос в хранимке компилируется обычно и хана. Пока никто не наступит на то, что его параметры совсем не подходят к их плану — WITH RECOMPILE — процу не метит. Только прежде чем обнаружить такую проблему — ну это скажем так часов 2-8 простоя весьма немалых организаций. Поэтому рассказывать о том что там надо или не надо следить — не нужно тут мне. Следить надо. По факту — специалистов которые знают за чем *можно* следить — нет. F> Как тут выигрывает LINQ? Если есть нетривиальные запросы — он просто будет константно выигрывать, против старого доброго процедурного подхода. Будет сиквет перекомпилировать запрос всегда? Да. Ну почти да. F> Будет ли это быстрее? Ну скорее всего да. Самое главное не в этом — при появлении входных данных которые выбиваются из общей канвы — всё по прежнему будет работать. F> Ну а знатоки проц — знают — без WITH RECOMPILE — это не победимо — кто первый дернул её со своими параметрами — того и план. А эффективен он или нет — сиквелу как бы пофигу.
F> PS: Я знаю, что тема немного о другом — но и об этом тоже. Выгоднее ли исполнять хранимки — конечно да. Выгоднее ли всегда — далеко не факт. Можно ли забить на этот анархизм? Конечно нет! Но LINQ в любом своём проявлении особенно с linq2db — точно показывает себя более чем достойно. F> Да. Поборники достойности — мой десктоп способен обслужить 7K+ запросов весьма нифика не простых запросов. И это всё через LINQ. RAW — будет быстрее. Но — ещё быстрее — будет без SQL вообще. Так что заранее прошу — глупости тут не городить. Да. Без сиквела — 20K+.
В этой ветке никто не спорит о нужности динамических запросов. Обсуждаются способы их реализации.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Здравствуйте, gandjustas, Вы писали: AP>Т.е. боремся с этими несчастными экспрешенами, вместо того, чтобы писать запрос, который реализует бизнес-логику (реализацию, которой нам и оплачивает заказчик). Голова программиста занята борьбой с экспрешенами, типами и т.д., вместо того, чтобы заниматься прямыми обязанностями по реализации бизнес-логики. AP>Слишком дорого. За что мы платим такую цену? За проверку ошибок на этапе компиляции, find usages и рефакторинг. Но есть вариант всё это получить гораздо дешевле.
Еще раз повторю, идеология и затраты на разработку и поддержку не связаны. По факту linq знают 90% программистов на c#, а sql, хотя бы на уровне написания джоинов, от силы 50%. Linq позволяет делать меньше ошибок при написании и экономит на поддержке за счет декомпозиции. Так что в среднем linq эффектинее на порядок, то есть получает тот же результат при гораздо меньших затратах. А такие вещи, как миграции в ef, экономят время настолько, что перекрывают любые преимущества, которые могут быть у текстовых запросов.
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, gandjustas, Вы писали:
F>Ребята, я всем очень благодарен за участие.
F>Но спорите не о том.
F> ... поскипано...
Не очень понял зачем ты мне это написал.
F> Как тут выигрывает LINQ? Если есть нетривиальные запросы — он просто будет константно выигрывать, против старого доброго процедурного подхода. Будет сиквет перекомпилировать запрос всегда? Да. Ну почти да.
Нет, потому что SqlCommand, используемый Linq2SQL, EF и всеми остальными orm, вызывает sp_executesql, который форсирует параметризацию. Это хорошо, когда есть покрывающий индекс с высокой селективность, и ужасно когда такового нет, потому что закеширует план с index\table scan, и начнет тормозить когда количество данных вырастет.
Кстати основная причина использования хранимок для выборок — возможность написать руками with(nolock), чтобы при больших выборках не лочить таблицы.
Здравствуйте, fddima, Вы писали:
F> Насчет второго — я расскажу так. Запрос в хранимке компилируется обычно и хана. Пока никто не наступит на то, что его параметры совсем не подходят к их плану — WITH RECOMPILE — процу не метит. Только прежде чем обнаружить такую проблему — ну это скажем так часов 2-8 простоя весьма немалых организаций. Поэтому рассказывать о том что там надо или не надо следить — не нужно тут мне. Следить надо. По факту — специалистов которые знают за чем *можно* следить — нет.
Эмм???
Я сейчас могу гнать, по памяти, как минимум в ms sql 2008r2 execution plan кэшируется одинаково и для хранимок, и для параметризованных sql-забросов — после вылета из кэша происходит рекомпиляция. Например, вот подтверждение (см "Reasons Stored Procedures Recompile")
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, fddima, Вы писали:
F>> Насчет второго — я расскажу так. Запрос в хранимке компилируется обычно и хана. Пока никто не наступит на то, что его параметры совсем не подходят к их плану — WITH RECOMPILE — процу не метит. Только прежде чем обнаружить такую проблему — ну это скажем так часов 2-8 простоя весьма немалых организаций. Поэтому рассказывать о том что там надо или не надо следить — не нужно тут мне. Следить надо. По факту — специалистов которые знают за чем *можно* следить — нет.
S>Эмм???
S>Я сейчас могу гнать, по памяти, как минимум в ms sql 2008r2 execution plan кэшируется одинаково и для хранимок, и для параметризованных sql-забросов — после вылета из кэша происходит рекомпиляция. Например, вот подтверждение (см "Reasons Stored Procedures Recompile")
S>А вот пример похожих проблем с параметризованными запросами: S>http://stackoverflow.com/questions/13635531/optimizing-execution-plans-for-parameterized-t-sql-queries-containing-window-fun
S>Причём в кеш могут попасть и автопараметризованные запросы (для самых простых случаев), например, см секцию Auto-Parameterization в sql perf distilled
Как обычно все немного сложнее. Процедуры компилируются в момент первого вызова, причем с учетом параметров, которые передали в процедуру. План, оптимальный для этих параметров, может быть крайне неоптимальным для других. При вызове sqlcommand с параметрами запрос попадает в sp_executesql, где принудительно параметизуется. Таким образом для linq запросов создается план который работает одинаково (хорошо или плохо — зависит от кучи факторов), а для хранимок может быть закеширован план, который работает хорошо на одном значении параметра и ужасно на другом.
Здравствуйте, Alexander Polyakov, Вы писали:
НС>>Очень странный вопрос. В чем проблема? AP>Приведи свой вариант кода для IQueryable того, что я сделал для IEnumerable. Выдели метод MyMethod.
private static Expression<Func<int, bool>> MyMethod(int c1, int c2)
{
return x => x > c1 && x < c2;
}
Здравствуйте, gandjustas, Вы писали:
G>Как обычно все немного сложнее. Процедуры компилируются в момент первого вызова, причем с учетом параметров, которые передали в процедуру. План, оптимальный для этих параметров, может быть крайне неоптимальным для других. При вызове sqlcommand с параметрами запрос попадает в sp_executesql, где принудительно параметизуется. Таким образом для linq запросов создается план который работает одинаково (хорошо или плохо — зависит от кучи факторов), а для хранимок может быть закеширован план, который работает хорошо на одном значении параметра и ужасно на другом.
Так, я всё-таки торможу
Для хранимок:
план строится по первому запуску, строится по переданным аргументам, кэшируется до выпадения из кэша.
Для параметризованного sql (sp_executesql):
план строится по первому запуску, строится по переданным аргументам, кэшируется до выпадения из кэша.
* про авто-параметризацию пока забудем, считаем что в executesql пришёл запрос с явно прописанными параметрами.
В чём разница?
Выше приводил ссылку, что-то похожее наблюдал лично на ms sql 2008r2: что для хранимых процедур, что для sp_executesql мог использоваться неоптимальный план. Возможно это было просто совпадение, в документации тогда толком не копался.
Быстро поискал — вот ещё пруф.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, gandjustas, Вы писали:
G>>Как обычно все немного сложнее. Процедуры компилируются в момент первого вызова, причем с учетом параметров, которые передали в процедуру. План, оптимальный для этих параметров, может быть крайне неоптимальным для других. При вызове sqlcommand с параметрами запрос попадает в sp_executesql, где принудительно параметизуется. Таким образом для linq запросов создается план который работает одинаково (хорошо или плохо — зависит от кучи факторов), а для хранимок может быть закеширован план, который работает хорошо на одном значении параметра и ужасно на другом.
S>Так, я всё-таки торможу
S>Для хранимок: S> план строится по первому запуску, строится по переданным аргументам, кэшируется до выпадения из кэша.
S>Для параметризованного sql (sp_executesql): S> план строится по первому запуску, строится по переданным аргументам, кэшируется до выпадения из кэша.
S> * про авто-параметризацию пока забудем, считаем что в executesql пришёл запрос с явно прописанными параметрами.
S>В чём разница?
Опять все немного сложнее. если внутри процедуры обычный select, то разницы нет. Но часто в процедуре много действий, которые делают план очень нестабильным (в разных случаях оптимальный путь исполнения будет сильно отличаться). В sp_executesql всегда прилетает один запрос (при использовании linq), для которого почти всегда можно построить стабильный план (особенно за счет добавления покрывающих индексов), что чаще всего и происходит.
Здравствуйте, gandjustas, Вы писали:
G>Опять все немного сложнее. если внутри процедуры обычный select, то разницы нет. Но часто в процедуре много действий, которые делают план очень нестабильным (в разных случаях оптимальный путь исполнения будет сильно отличаться).
Угу, с таким объяснением согласен. Спасибо!
Здравствуйте, gandjustas, Вы писали:
G>Это ты уверяешь что проблемы есть, но примеры не приводишь. Воистину — вера страшная штука.
Главное, что моя вера совпадает с верой разработчиков, так что мое кун-фу круче =)
G>Судя по тому что ты пишешь — нет.
Ты видимо что-то не то читаешь..
G>А атрибуты не добавляют? Такие же классы, также через них маппинг делется.
Не прикидывайся. Если не понятно, можешь еще раз прочитать пресс-релиз о причинах закрытия EF6 или почитать текст исключения при попытках составить не тривиальный linq запрос... Очень показательно, кстати, выдает что-то типа "внутренняя модель так не может". Это при том что code-first и прямой маппинг, и никакой такой модели не видно — нет никакой ложки.
G>Ты как-то хитро отбросил часть моей фразы про исправление конкретных проблем. Твои идеи по поводу "идеологии" не интересуют вообще, я про конкретику уже хрен знает какой раз спрашиваю, а ответа все нет, ты все про идеологию.
Если ты не понимаешь, что корни всех конкретных проблем лежат именно в идеологии, то я тут бессилен. При кривой изначальной идее можно заткнуть конкретную проблему.. Одну, может две. Но что-то отвалится в другом месте. А при попытке добавить новый функционал — совсем все развалится.
Что, собственно, с EF и произошло — очень наглядный пример, что кривую идеологию никакая реализация не исправит.
G>Не похоронили, а наконец собрались переписать.
Что в лоб, что полбу =)
G>Текущая версия отлично работает для тех сценариев, для которых она заточена.
Она заточена под несуществующие сценарии и совсем не работает в реальной жизни — there are many seldom used features and capabilities in the code base that hamper performance and complicate development. Или вот — We also have a number of unintuitive behaviors that are engrained into the framework.
G>С точки зрения API в новой версии мало что изменится, будет вполне нормальный upgrade path.
Свежо придание )
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>Это ты уверяешь что проблемы есть, но примеры не приводишь. Воистину — вера страшная штука. IB>Главное, что моя вера совпадает с верой разработчиков, так что мое кун-фу круче =)
Тем не менее твоя вера расходится с фактами. Как бы тебе не верилось обратное.
G>>Судя по тому что ты пишешь — нет. IB>Ты видимо что-то не то читаешь..
Ты же ни одного факта не привел, а религиозный бред уже фильтрую не задумываясь.
G>>А атрибуты не добавляют? Такие же классы, также через них маппинг делется. IB>Не прикидывайся. Если не понятно, можешь еще раз прочитать пресс-релиз о причинах закрытия EF6 или почитать текст исключения при попытках составить не тривиальный linq запрос... Очень показательно, кстати, выдает что-то типа "внутренняя модель так не может". Это при том что code-first и прямой маппинг, и никакой такой модели не видно — нет никакой ложки.
Так приведи запрос который не может осилить ef в принципе, но легко осиливается другим linq провайдером.
Или ты оцениваешь технологии исключительно о пресс-релизам? Это верх профессионализма сейчас?
G>>Ты как-то хитро отбросил часть моей фразы про исправление конкретных проблем. Твои идеи по поводу "идеологии" не интересуют вообще, я про конкретику уже хрен знает какой раз спрашиваю, а ответа все нет, ты все про идеологию. IB>Если ты не понимаешь, что корни всех конкретных проблем лежат именно в идеологии, то я тут бессилен.
Ну естественно бессилен, ибо ты веришь, а я проверяю. Попробуй тоже проверить, сразу развенчаешь свои заблуждения.
IB>При кривой изначальной идее можно заткнуть конкретную проблему.. Одну, может две. Но что-то отвалится в другом месте. А при попытке добавить новый функционал — совсем все развалится. IB>Что, собственно, с EF и произошло — очень наглядный пример, что кривую идеологию никакая реализация не исправит.
Опять идеологическая чушь. Почему-то при кривой идеологии чуваки смогли прикрутить к ef кучу фич, тип асинхронности, code-first, миграций, повысили быстродействие на порядки, создали community с кучей расширений и провайдеров. Дай бог каждому такие «кривые» идеи придумывать.
G>>Не похоронили, а наконец собрались переписать. IB>Что в лоб, что полбу =)
То есть roslyn == похоронили c#, asp.net vnext == похоронили asp.net, любой мажорный релиз продукта == похоронили продукт?
Отличная логика
G>>Текущая версия отлично работает для тех сценариев, для которых она заточена. IB>Она заточена под несуществующие сценарии и совсем не работает в реальной жизни — there are many seldom used features and capabilities in the code base that hamper performance and complicate development. Или вот — We also have a number of unintuitive behaviors that are engrained into the framework.
Я уже понял что ты технологии по пресс-релизам оцениваешь. Можешь не повторять.
G>>С точки зрения API в новой версии мало что изменится, будет вполне нормальный upgrade path. IB>Свежо придание )
Я бы мог тебе рассказать как прекрасно database-first из 4.1 мигрировался на code-first в 6, но чувствую вера твоя все равно сильнее.
G>Ты же говоришь о решении, а не о проблеме, думаешь за 7 лет ничего не изменилось?
Поменялось, у меня за окном деревья подросли. Но, к сожалению, на механизм декомпозиции эекспрешенов это не повлияло.
Здравствуйте, IB, Вы писали:
IB>Она заточена под несуществующие сценарии и совсем не работает в реальной жизни — there are many seldom used features and capabilities in the code base that hamper performance and complicate development. Или вот — We also have a number of unintuitive behaviors that are engrained into the framework.
Что же они так? Спросили бы меня как надо было делать EF с самого начала. Я бы им ещё лет 5 назад рассказал. Стоило выпускать 6 релизов, чтобы понять, что 7-й нужно переписывать с нуля.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, IB, Вы писали:
IB>>Она заточена под несуществующие сценарии и совсем не работает в реальной жизни — there are many seldom used features and capabilities in the code base that hamper performance and complicate development. Или вот — We also have a number of unintuitive behaviors that are engrained into the framework.
IT>Что же они так? Спросили бы меня как надо было делать EF с самого начала. Я бы им ещё лет 5 назад рассказал. Стоило выпускать 6 релизов, чтобы понять, что 7-й нужно переписывать с нуля.
В .NET дофига компонент, которые лет 5 назад стоило переписать с нуля, но менеджмент видимо не позволял.
С появлением Roslyn и K Runtime перепишут под шумок кучу всего.
Здравствуйте, gandjustas, Вы писали:
IT>>Что же они так? Спросили бы меня как надо было делать EF с самого начала. Я бы им ещё лет 5 назад рассказал. Стоило выпускать 6 релизов, чтобы понять, что 7-й нужно переписывать с нуля.
G>В .NET дофига компонент, которые лет 5 назад стоило переписать с нуля, но менеджмент видимо не позволял.
EF — это всё же отдельно от всего лежащий кусок кала. Ваня правильнос сказал, что практикующим девелоперам ещё лет 10 назад стало понятно каким должно быть средство работы с БД. Но команда EF шла на пролом своим путём.
G>С появлением Roslyn и K Runtime перепишут под шумок кучу всего.
Новый компилятор позволяет переписать устаревший код и сделать его лучше. Но новый компилятор не поможет сделать лучше новую архитектуру. После прочтения их пресс-релиза у меня уже возникают какие-то смутные сомнения. Особенно по поводу "EF7 is Lightweight and Extensible". Один из самых "Extensible" продуктов MS — WCF, хрень, с которой без гугля работать невозможно в принципе. Куда заведут ребят из команды EF новые возможности Рослина не знает никто.
Если нам не помогут, то мы тоже никого не пощадим.
НС>Решается несложным хелпером:
Т.е. всю красоту синтаксиса linq теряем и видим старый неуклюжий Query Object паттерн. Query Object-ов написано куча и на C# и на Java, и все они говно.
НС>Но можно и немножко похитрее, в более общем виде. linq2db.
Т.е. из коробки от Microsoft такого нет. О чем я и говорил, не дизайнился linq для динамических запросов.
Убого это всё выглядит MyMethod, MyMehodExpr, да еще атрибутом надо пометить, фу, простейший Extract Method такой громоздкое убожество вызывает. И это для простоты сопровождения говорите, ну ну. И это вы называли "развитые" средства декомпозиции?
Если сделаю MyMehod и ничего больше писать не буду, то упадет это всё отнюдь не при компиляции, а как раз в рантайме. За что боролись на то и напоролись.
Короче, слишком дорого обходится статическая проверка запросов. Хочется того же, но подешевле.
НС>Давай на конкретных примерах. Перепиши с идентичным поведением и полным сохранением контроля компилятора этот примитивный код без ORM:
А что такое ORM? Вот этот код без ORM:
private static void Example1(DateTime? date)
{
using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();
using (var command = connection.CreateCommand())
{
var builder = new StringBuilder(@"
SELECT Id, CreationDate
FROM Post
WHERE 1 = 1");
if (date.HasValue)
{
builder.Append(@"
AND CreationDate >= @Date");
command.Parameters.AddWithValue("@Date", date);
}
command.CommandText = builder.ToString();
using (var reader = command.ExecuteReader())
{
var idOrdinal = reader.GetOrdinal("Id");
var creationDateOrdinal = reader.GetOrdinal("CreationDate");
while (reader.Read())
{
var id = reader.GetInt32(idOrdinal);
var creationDate = reader.GetDateTime(creationDateOrdinal);
}
}
}
}
}
Теперь пары Пары [id, Int32] и [CreationDate, DateTime] представляем в виде интерфейса:
public interface IPostInfo
{
int Id { get; }
DateTime CreationDate { get; }
}
Тогда, используя runtime кодогенерацию (Emit), код можно переписать следующим образом.
private static void Example1(DateTime? date)
{
using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();
using (var command = connection.CreateCommand())
{
var builder = new StringBuilder(@"
SELECT Id, CreationDate
FROM Post
WHERE 1 = 1");
if (date.HasValue)
{
builder.Append(@"
AND CreationDate >= @Date");
command.Parameters.AddWithValue("@Date", date);
}
command.CommandText = builder.ToString();
using (var reader = command.ExecuteReader())
{
var ordinals = reader.GetOrdinals<IPostInfo>();
while (reader.Read())
{
IPostInfo postInfo = ordinals.Materialize(reader);
}
}
}
}
}
AP>>Т.е. всю красоту синтаксиса linq теряем НС>Нет. Контроль компилятора остается ровно тот же. AP>> и видим старый неуклюжий Query Object паттерн. НС>Тебе показалось.
Query Object тоже дает проверку во время компиляции. Из последнего http://www.jooq.org/
НС>>>Но можно и немножко похитрее, в более общем виде. linq2db. AP>>Т.е. из коробки от Microsoft такого нет НС>И что?
А то, что linq не разрабатывался для динамических запросов к БД, а вы это преподносите как главную фичу.
AP>>Убого это всё выглядит MyMethod, MyMehodExpr НС>Если сравнивать со склейкой строк ...
Если строки автоматически проверяются, то строки проще читать, сопровождать и т.д.
НС>Смысл твоих вопросов и их связь с моим постом непонятна.
У тебя написано "без ORM". Вот я и хочу выяснить смысл этого слова у тебя. Если метод "ordinals.Materialize(reader)" еще не является ORM-ом, то на твой вопрос можно ответить и переписать твой код без ORM.
Здравствуйте, Alexander Polyakov, Вы писали:
НС>>Смысл твоих вопросов и их связь с моим постом непонятна. AP>У тебя написано "без ORM". Вот я и хочу выяснить смысл этого слова у тебя.
AP>>А то, что linq не разрабатывался для динамических запросов НС>Заладил как истукан. Это все ни о чем. Есть конкретные задачи и есть их решения.
Ха, задача ... А как там насчет Вьетнама компьютерной науки?
AP>>Если метод "ordinals.Materialize(reader)" еще не является ORM-ом, НС>Вообще то уже является.
Тогда и в таком коде уже есть ORM "new Post(reader.GetInt32(idOrdinal), reader.GetDateTime(creationDateOrdinal))". Relation есть, Object есть, Mapping тоже есть. Т.е. без ORM, действительно, очень сложно написать.
AP>> то на твой вопрос можно ответить и переписать твой код без ORM. НС>Перепиши.
Если Materialize это уже ORM, то у меня нет варианта без ORM.
Всё это так, да. Но вот Фаулер пишет о том, что relation-ы в памяти не всегда прокатывают, ему нужны какие-то Объекты.
Avoiding the problem
...
To use a relational model in memory basically means programming in terms of relations, right the way through your application. In many ways this is what the 90's CRUD tools gave you. They work very well for applications where you're just pushing data to the screen and back, or for applications where your logic is well expressed in terms of SQL queries. Some problems are well suited for this approach, so if you can do this, you should. But its flaw is that often you can't. http://martinfowler.com/bliki/OrmHate.html
Т.е. Фаулер пишет, что если релейшенов в памяти достаточно, то это позволяет избежать ORM проблем. Materialize всего лишь вытаскивает релешен в память.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
IT>>>Что же они так? Спросили бы меня как надо было делать EF с самого начала. Я бы им ещё лет 5 назад рассказал. Стоило выпускать 6 релизов, чтобы понять, что 7-й нужно переписывать с нуля.
G>>В .NET дофига компонент, которые лет 5 назад стоило переписать с нуля, но менеджмент видимо не позволял.
IT>EF — это всё же отдельно от всего лежащий кусок кала.
Года два назад отдали в ASP.NET
IT>Ваня правильнос сказал, что практикующим девелоперам ещё лет 10 назад стало понятно каким должно быть средство работы с БД. Но команда EF шла на пролом своим путём.
Если всем понятно, то почему никто не сделал?
G>>С появлением Roslyn и K Runtime перепишут под шумок кучу всего.
IT>Новый компилятор позволяет переписать устаревший код и сделать его лучше. Но новый компилятор не поможет сделать лучше новую архитектуру.
Да ладно? Например с помощью compiler as service можно сделать compile time генерация маппинга DataReader на объекты как минимум или запросто компилировать в реальный IL edmx-модель, убрав весь оверхед, или делать compile-time проверяемые текстовые запросы с декомпозицией (как мечтает Поляков).
IT>После прочтения их пресс-релиза у меня уже возникают какие-то смутные сомнения. Особенно по поводу "EF7 is Lightweight and Extensible".
Ты тоже оцениваешь технологии по пресс-релизам? Лучше посмотри исходники на гитхабе.
IT>Один из самых "Extensible" продуктов MS — WCF, хрень, с которой без гугля работать невозможно в принципе. Куда заведут ребят из команды EF новые возможности Рослина не знает никто.
Вот сделали WebAPI, фактически замена WCF, можно написать SOAP форматтер и роутинг через SOAP пакет и получится почти тоже самое.
WebAPI вроде как всем нравится, никто не жалуется.
Самые важные отличия WebAPI от WCF
1) У WCF очень многослойный API, у WebAPI довольно мало вызовов между котроллером и HttpHandler\HttpListener
2) У обоих куча Extensibility Points, но в WebAPI почти все делается через встроенный IoC, а WCF для каждого расширения применяется свой метод (конфиги, атрибуты, классы итп)
3) У WCF очень много конфигурации, даже для запуска простого сервиса нужно создать кучу объектов с кучей параметров или прописать дофига всего в конфигах, в WebAPI большая часть построена на "соглашениях". Причем соглашения можно настроить, но по умолчанию они покрывают самые распространенные случаи.
По сути в WebAPI используется сервисно-ориентированная архитектура, тогда как WCF — образец классического ООП.
Возвращаясь к теме EF — начиная с версии 5 активно внедряется такой же сервисный подход. Тоже есть встроенный IoC, тоже куча подменяемых сервисов и соглашения (положительное влияние asp.net). Но под капотом там еще остался старый EF, построенный на принципах ООП, который и хотят в версии 7 выкорчевать из EF.
Если бы строк было достаточно для использования SQL в программе, то linq никогда бы не придумали. Если ты веришь что все можно сделать используя только строки, то мне тебя искренне жаль.
Здравствуйте, gandjustas, Вы писали:
G>Да ладно? Например с помощью compiler as service можно сделать compile time генерация маппинга DataReader на объекты как минимум
Для этого компилятор не нужен, вполне достаточно генерировать маппинг по IL. Это, заоодно, еще и универсально по отношению к конкретному языку будет.
Ковырятся с интеграцией в компилятор нужно строго в том случае, где нам необходимо вмешательство в алгоритмы работы компилятора по основному коду. Например введение новых типов. Для маппера это все без особой надобности.
G> или запросто компилировать в реальный IL edmx-модель, убрав весь оверхед
Это можно, но пользы от этого немного.
IT>>Один из самых "Extensible" продуктов MS — WCF, хрень, с которой без гугля работать невозможно в принципе. Куда заведут ребят из команды EF новые возможности Рослина не знает никто. G>Вот сделали WebAPI, фактически замена WCF
Конечно же нет. WebAPI решает существенно более узкие задачи, не особо с WCF пересекающиеся. Если у него RESTful сервисы — основная задача, то для WCF это побочная фича.
G>а WCF для каждого расширения применяется свой метод (конфиги, атрибуты, классы итп)
Это тоже неверно. Все эти методы параллельные, а не взаимоисключающие.
G>3) У WCF очень много конфигурации, даже для запуска простого сервиса нужно создать кучу объектов с кучей параметров или прописать дофига всего в конфигах
И это неверно. Для типовых юзкейсов есть готовые наборы конфигураций. Самому их собирать нужно только если типовые не позволяют сконфигурироваться в то что нужно.
G>По сути в WebAPI используется сервисно-ориентированная архитектура, тогда как WCF — образец классического ООП.
А это просто вранье. SOA, собственно, оформилась как архитектура именно при создании WCF и была положена в его основу.
G>Если бы строк было достаточно для использования SQL в программе, то linq никогда бы не придумали. Если ты веришь что все можно сделать используя только строки, то мне тебя искренне жаль.
Мне искренне жаль тех, кто слепо верит в то, что, закрывая SQL linq-ом получается якобы улучшение: быстрота разработки, maintenance, развитие и т.д. На самом деле, linq решает одни проблемы и создает другие. Совокупно становится не лучше, а чаще maintenance и развитие становится только хуже. Очередной виток Вьетнама компьютерной науки.
Точнее таких девелоперов мне не жаль, поскольку сами виноваты, занимаются самообманом. Жаль их заказчиков, они то не о чем не подозревают, что нанятые девелоперы не занимаются их бизнес логикой, а тратят время на экспрешены.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Тогда и в таком коде уже есть ORM "new Post(reader.GetInt32(idOrdinal), reader.GetDateTime(creationDateOrdinal))".
Нет.
AP>>> то на твой вопрос можно ответить и переписать твой код без ORM. НС>>Перепиши. AP>Если Materialize это уже ORM, то у меня нет варианта без ORM.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Мне искренне жаль тех, кто слепо верит в то, что, закрывая SQL linq-ом получается якобы улучшение: быстрота разработки, maintenance, развитие и т.д.
Это не вопрос веры, это результат конкретного опыта. У меня, к примеру, был проект, написанный на BLT со склейкой строк. Потом его переписали на LINQ. Объем кода и сложность его модификации уменьшились в разы. А вот у тебя именно что вера, что твой велосипед круче линка. Ну и правда, зря что ли ты его делал?
НС>Это не вопрос веры, это результат конкретного опыта. У меня, к примеру, был проект, написанный на BLT со склейкой строк. Потом его переписали на LINQ. Объем кода и сложность его модификации уменьшились в разы. А вот у тебя именно что вера, что твой велосипед круче линка. Ну и правда, зря что ли ты его делал?
Ну, ну, зря делал... Я что мазохист что ли от хорошей жизни бесплатно делать библиотеку. Нахрена мне это надо? ... С большим удовольствием взял бы EF и занимался бы на работе реализацией бизнес логики, за которую мне платят. ... А опыт показывает, что при использовании LINQ всегда чувствуется профессиональная неловкость: блин, да, дайте мне уже самому написать SQL, который я знаю как должен выглядеть, а не заставляете меня извращаться через посредника в виде linq. Короче с удовольствием выкинул бы свой проект, если бы было чем заменить.
НС>Опять какие то твои персональные психологические выверты. Ни о чем.
Ты сам свернул на дорожку обсуждения моей личности: "Ну и правда, зря что ли ты его делал?".
НС>Это не вопрос веры, это результат конкретного опыта. У меня, к примеру, был проект, написанный на BLT со склейкой строк. Потом его переписали на LINQ. Объем кода и сложность его модификации уменьшились в разы. А вот у тебя именно что вера, что твой велосипед круче линка. Ну и правда, зря что ли ты его делал?
Т.е. вопрос лишь в том, что тебе нужно приобрести опыт работы с автоматической проверкой строковых запросов? Только после этого ты сможешь давать оценку. Может оказаться аналогично "сложность его написания и модификации уменьшится в разы" относительно linq.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>1) чем это компилировать? AP>Приведенный код компилируется обычным C# компилятором. Для проверки запросов надо дернуть метод CheckAllQueries AP>
этот подход не взлетит, если нет доступа к имплементации оригинального запроса.
а такое встречается сплош и рядом — севременные приложения без DI/IOC уже давно не пишут.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
G>>Да ладно? Например с помощью compiler as service можно сделать compile time генерация маппинга DataReader на объекты как минимум
НС>Для этого компилятор не нужен, вполне достаточно генерировать маппинг по IL. Это, заоодно, еще и универсально по отношению к конкретному языку будет. НС>Ковырятся с интеграцией в компилятор нужно строго в том случае, где нам необходимо вмешательство в алгоритмы работы компилятора по основному коду. Например введение новых типов. Для маппера это все без особой надобности.
Повторяю — compile-time генерация мапперов, чтобы убрать весь оверхед в рантайме, и чтобы работать могло в средах где генерация невозможна, типа winrt.
G>> или запросто компилировать в реальный IL edmx-модель, убрав весь оверхед
НС>Это можно, но пользы от этого немного.
Как минимум IB не будет потом рассказывать про тормознутую модель. Тоже польза
А по факту в ef долгое время была проблема генерации mapping view. Начиная с ef5 оно генерируется один раз и кешируется, но это происходит в рантайме и добавляет тормозов при первом запуске.
IT>>>Один из самых "Extensible" продуктов MS — WCF, хрень, с которой без гугля работать невозможно в принципе. Куда заведут ребят из команды EF новые возможности Рослина не знает никто. G>>Вот сделали WebAPI, фактически замена WCF
НС>Конечно же нет. WebAPI решает существенно более узкие задачи, не особо с WCF пересекающиеся. Если у него RESTful сервисы — основная задача, то для WCF это побочная фича.
Это идеология. на практике прикрутить к webapi soap-форматтер, sop-ротуы и генератор wsdl, то будет решать те же задачи.
G>>а WCF для каждого расширения применяется свой метод (конфиги, атрибуты, классы итп)
НС>Это тоже неверно. Все эти методы параллельные, а не взаимоисключающие.
Я написал что они взаимоисключающие? Самая проблема что они все разные.
G>>3) У WCF очень много конфигурации, даже для запуска простого сервиса нужно создать кучу объектов с кучей параметров или прописать дофига всего в конфигах
НС>И это неверно. Для типовых юзкейсов есть готовые наборы конфигураций. Самому их собирать нужно только если типовые не позволяют сконфигурироваться в то что нужно.
Эти типовые конфигурации тоже надо прописывать в кофиге или в коде. Нету нормальной системы умолчаний.
G>>По сути в WebAPI используется сервисно-ориентированная архитектура, тогда как WCF — образец классического ООП.
НС>А это просто вранье. SOA, собственно, оформилась как архитектура именно при создании WCF и была положена в его основу.
Ты по ссылке внимательно прочитай для начала.
Здравствуйте, gandjustas, Вы писали:
G>Повторяю — compile-time генерация мапперов, чтобы убрать весь оверхед в рантайме
Генерировать мапперы по IL можно и в компайл-тайме. То что EF этого не умеет вовсе не означает, что это вообще невозможно.
НС>>Это можно, но пользы от этого немного. G>Как минимум IB не будет потом рассказывать про тормознутую модель.
Это никак не избавляет от того, о чем говорит IB.
НС>>Конечно же нет. WebAPI решает существенно более узкие задачи, не особо с WCF пересекающиеся. Если у него RESTful сервисы — основная задача, то для WCF это побочная фича. G>Это идеология. на практике прикрутить к webapi soap-форматтер, sop-ротуы и генератор wsdl, то будет решать те же задачи.
При чем тут SOAP?
НС>>Это тоже неверно. Все эти методы параллельные, а не взаимоисключающие. G>Я написал что они взаимоисключающие? Самая проблема что они все разные.
Не вижу проблемы.
НС>>И это неверно. Для типовых юзкейсов есть готовые наборы конфигураций. Самому их собирать нужно только если типовые не позволяют сконфигурироваться в то что нужно. G>Эти типовые конфигурации тоже надо прописывать в кофиге или в коде.
Это одна строчка.
G> Нету нормальной системы умолчаний.
Есть.
НС>>А это просто вранье. SOA, собственно, оформилась как архитектура именно при создании WCF и была положена в его основу. G>Ты по ссылке внимательно прочитай для начала.
Ты лучше сам сходи и прочитай официальное введение в архитектуру WCF, а не пиши здесь ерунду.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Если бы строк было достаточно для использования SQL в программе, то linq никогда бы не придумали. Если ты веришь что все можно сделать используя только строки, то мне тебя искренне жаль. AP>Мне искренне жаль тех, кто слепо верит в то, что, закрывая SQL linq-ом получается якобы улучшение: быстрота разработки, maintenance, развитие и т.д. На самом деле, linq решает одни проблемы и создает другие. Совокупно становится не лучше, а чаще maintenance и развитие становится только хуже.
Если бы это было правдой то не изобрели бы linq и query object вообще.
Очередной виток Вьетнама компьютерной науки.
AP>Точнее таких девелоперов мне не жаль, поскольку сами виноваты, занимаются самообманом. Жаль их заказчиков, они то не о чем не подозревают, что нанятые девелоперы не занимаются их бизнес логикой, а тратят время на экспрешены.
Как раз те кто пишут linq — экономят. Особенно на поддержке. А такие как ты тратят, прикрываясь тем что занимаются «бинес-логикой».
Ты ведь сколько не написал в этой теме, но по факту не привел ни одного довода почему linq использовать неэффективно. Все что ты привел доказывает обратное, особенно примеры с «проверяемыми запросами».
G>Ты ведь сколько не написал в этой теме, но по факту не привел ни одного довода почему linq использовать неэффективно. Все что ты привел доказывает обратное, особенно примеры с «проверяемыми запросами».
Я привел достаточно доводов. linq не способен просто сделать базовую операцию декомпозиции: выделение фрагмента кода. Вы показали либо заворачивание краткого синтаксиса linq в хелперные методы (и получение громоздкого синтаксиса аля Query Object)?, либо самопальные костыли из linq2db.
G>Все что ты привел доказывает обратное, особенно примеры с «проверяемыми запросами».
Каким образом ты видишь обратное? Пока голословное утверждение.
T>этот подход не взлетит, если нет доступа к имплементации оригинального запроса. T>а такое встречается сплош и рядом — севременные приложения без DI/IOC уже давно не пишут.
IOC совершенно параллелен CheckAllQueries. Выложу на github всё станет ясно по коду.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Ты ведь сколько не написал в этой теме, но по факту не привел ни одного довода почему linq использовать неэффективно. Все что ты привел доказывает обратное, особенно примеры с «проверяемыми запросами». AP>Я привел достаточно доводов. linq не способен просто сделать базовую операцию декомпозиции: выделение фрагмента кода.
Я тебе привел ссылку как это делается. Копируй себе и выделяй сколько влезет.
AP>Вы показали либо заворачивание краткого синтаксиса linq в хелперные методы (и получение громоздкого синтаксиса аля Query Object)?, либо самопальные костыли из linq2db.
Любые костыли лучше склейки строк, ибо компилятором проверяются. А ты попробуй текстовые запросы разобрать на кусочки так, чтобы предикаты были в одной сборке, проекции в другой, а собирался запрос в третьей и все три части проверялись компилятором.
G>>Все что ты привел доказывает обратное, особенно примеры с «проверяемыми запросами». AP>Каким образом ты видишь обратное? Пока голословное утверждение.
Я тебе писал про добавление проекций. Ты забыл уже?
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
G>>Повторяю — compile-time генерация мапперов, чтобы убрать весь оверхед в рантайме
НС>Генерировать мапперы по IL можно и в компайл-тайме. То что EF этого не умеет вовсе не означает, что это вообще невозможно.
Только сейчас это нельзя включить в библиотеку.
НС>>>Это можно, но пользы от этого немного. G>>Как минимум IB не будет потом рассказывать про тормознутую модель.
НС>Это никак не избавляет от того, о чем говорит IB.
Он говорит о тормознутом мепинге, при компиляции модели в код и генерации mapping view во время компиляции можно устранить тормоза полностью.
НС>>>Конечно же нет. WebAPI решает существенно более узкие задачи, не особо с WCF пересекающиеся. Если у него RESTful сервисы — основная задача, то для WCF это побочная фича. G>>Это идеология. на практике прикрутить к webapi soap-форматтер, sop-ротуы и генератор wsdl, то будет решать те же задачи.
НС>При чем тут SOAP?
При то что это основа ws-* вебсервисов, на которые wcf рассчитан в первую очередь.
НС>>>Это тоже неверно. Все эти методы параллельные, а не взаимоисключающие. G>>Я написал что они взаимоисключающие? Самая проблема что они все разные.
НС>Не вижу проблемы.
Ну попробуй сходу написать код для хоста wcf с di в классы сервисов. Что для этого нужно? Толи factory сделать, толи service behavior поменять и это настолько разные апи, что хрен разберешься как правильно.
НС>>>И это неверно. Для типовых юзкейсов есть готовые наборы конфигураций. Самому их собирать нужно только если типовые не позволяют сконфигурироваться в то что нужно. G>>Эти типовые конфигурации тоже надо прописывать в кофиге или в коде.
НС>Это одна строчка.
Это больше, особенно когда у тебя хост не в asp.net
G>> Нету нормальной системы умолчаний.
НС>Есть.
По сравнению с webapi считай что нет. А уж поменять умолчания, которые зашиты в 100500 разных классов это вообще жесть.
НС>>>А это просто вранье. SOA, собственно, оформилась как архитектура именно при создании WCF и была положена в его основу. G>>Ты по ссылке внимательно прочитай для начала.
НС>Ты лучше сам сходи и прочитай официальное введение в архитектуру WCF, а не пиши здесь ерунду.
Зачем мне официальное чтото читать? Я в ilspy код читаю, он говорит гораздо больше.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>А опыт показывает, что при использовании LINQ всегда чувствуется профессиональная неловкость: блин, да, дайте мне уже самому написать SQL, который я знаю как должен выглядеть, а не заставляете меня извращаться через посредника в виде linq.
А что же ты на ассемблере не пишешь? Ты же знаешь что компьютер должен делать, зачем извращаться через посредника?
Если ты знаешь как sql должен выглядеть, то ты или ясновидящий, или запросы примитивные. Но скорее всего ты только думаешь что знаешь.
НС>Перепиши с ним.
Печатал без компиляции и без CheckAllQueries, возможны опечатки.
return Query<IMessageInfo>.New(new {id}, @"
SELECT f.ShortName ForumShortName, m.CreatedOn, m.Subject, a.Origin
FROM Message m
JOIN Forum f ON f.Id = m.ForumId
OUTER JOIN Account a ON a.Id = m.AccountId
WHERE m.Id = @id AND f.ReadLevel <= @Account.AccessLevel
").SingleOrNone().Match(
_ => View(new MessageModel {
ID = id,
Info = _,
Text = FormatMessageBody(id, _.Origin)
}),
() => ErrorMessageBox("Сообщение не найдено"));
//Тип IMessageInfo генерируется автоматически по полям запроса, поэтому
//его код смотреть не надо
G>А что же ты на ассемблере не пишешь? Ты же знаешь что компьютер должен делать, зачем извращаться через посредника?
Я не знаю какие ассемблерные команды должны быть.
SQL это высокоуровневый язык, специально разработанный под реляционную модель.
G>Если ты знаешь как sql должен выглядеть, то ты или ясновидящий, или запросы примитивные. Но скорее всего ты только думаешь что знаешь.
Скорее всего, ты только думаешь, что я не знаю.
Здравствуйте, Alexander Polyakov, Вы писали:
НС>>Перепиши с ним. AP>Печатал без компиляции и без CheckAllQueries, возможны опечатки.
Напомню что linq показывает опечатки и несоответствия типов в процессе набора.
AP>
AP> return Query<IMessageInfo>.New(new {id}, @"
AP>SELECT f.ShortName ForumShortName, m.CreatedOn, m.Subject, a.Origin
AP>FROM Message m
AP> JOIN Forum f ON f.Id = m.ForumId
AP> OUTER JOIN Account a ON a.Id = m.AccountId
AP>WHERE m.Id = @id AND f.ReadLevel <= @Account.AccessLevel
AP>").SingleOrNone().Match(
AP> _ => View(new MessageModel {
AP> ID = id,
AP> Info = _,
AP> Text = FormatMessageBody(id, _.Origin)
AP> }),
AP> () => ErrorMessageBox("Сообщение не найдено"));
AP> //Тип IMessageInfo генерируется автоматически по полям запроса, поэтому
AP> //его код смотреть не надо
AP>
G>>А что же ты на ассемблере не пишешь? Ты же знаешь что компьютер должен делать, зачем извращаться через посредника? AP>SQL это высокоуровневый язык, специально разработанный под реляционную модель.
SQL в посредниках не нуждается.
Здравствуйте, gandjustas, Вы писали:
G>При N=5 человек уже не может это делать.
Такой ты наивный... А как же раньше подобные задачи решались? )))
Точно так же генерили SQL аж бегом.
G>Мой пример собирается в студии, я только оттуда несущественные детали убрал. Ты же пропустил довольно важные части.
А толку? Если в базе появилось лишнее поле, а ты забыл добавить его в свои объекты, то тебе компилятор не поможет. Зато помогли бы тулзы построения запросов — ты бы видел, что у тебя в базе.
Более того, при ручной разработке запросов есть тенденция, что эти запросы будут оседать на стороне базы. А в твоём случае все запросы — динамические, даже когда 90% их статические или требует тривиальных аргументов. А у тебя выходит самый тормозной вариант из всех.
Здравствуйте, gandjustas, Вы писали:
НС>>Генерировать мапперы по IL можно и в компайл-тайме. То что EF этого не умеет вовсе не означает, что это вообще невозможно. G>Только сейчас это нельзя включить в библиотеку.
Можно и включить, ilmerge никто пока не отменял. Но ты не находишь, что от фатального недостатка ты перешел к мелким неудобствам?
НС>>Это никак не избавляет от того, о чем говорит IB. G>Он говорит о тормознутом мепинге
Нет, он говорит о неправильной архитектуре, требующей лишних шагов.
G>, при компиляции модели в код и генерации mapping view во время компиляции можно устранить тормоза полностью.
Только тормоза во время компиляции. Но и этого у EF все равно нет.
НС>>При чем тут SOAP? G>При то что это основа ws-* вебсервисов, на которые wcf рассчитан в первую очередь.
То что он рассчитан в первую очередь, это уже твои фантазии. Я лично знаком с некоторыми из архитекторов WCF, и многопротокольность там закладывалась с самого начала как базовое требование. Причем не только в плане message протоколов, но и протоколов сетевых. И в том числе поэтому WCF на порядок гибче и шире по функционалу WebAPI, но и, как следствие, имеет более крутую learning curve.
G>>>Я написал что они взаимоисключающие? Самая проблема что они все разные. НС>>Не вижу проблемы. G>Ну попробуй сходу написать код для хоста wcf с di в классы сервисов.
Да писал не раз. Если понимаешь как WCF устроен — особых проблем нет. Ну и DI сам по себе — далеко не серебряная пуля.
G> Что для этого нужно?
Тривиально реализовать крошечный интерфейс — IInstanceProvider. Один раз, если уж тебе так DI мил.
G> Толи factory сделать, толи service behavior поменять и это настолько разные апи, что хрен разберешься как правильно.
Ну так и проблема в том что ты не разобрался, а не в WCF.
НС>>Это одна строчка. G>Это больше, особенно когда у тебя хост не в asp.net
Нет. Ты опять не разобрался.
НС>>Есть. G>По сравнению с webapi считай что нет.
По сравнению с WebAPI она на порядок круче, потому что позволяет создавать собственные шаблоны конфигураций. Но ты, я понимаю, опять не разобрался.
НС>>Ты лучше сам сходи и прочитай официальное введение в архитектуру WCF, а не пиши здесь ерунду. G>Зачем мне официальное чтото читать?
Ну конечно, ссылки на собственный блог, особенно учитывая что ты тут про WCF пишешь, куда убедительнее.
НС>Ну, собственно, мне добавить нечего кроме того, что IMessageInfo ты забыл привести.
У меня нет схемы твоей базы, не на чем прогонять CheckAllQueries.
Укажи, пожалуйста, опечатки (сэкономь моё время). По поводу IMessageInfo я написал: “Тип IMessageInfo генерируется автоматически по полям запроса, поэтому его код смотреть не надо”.
Здравствуйте, Alexander Polyakov, Вы писали:
НС>>Ну, собственно, мне добавить нечего кроме того, что IMessageInfo ты забыл привести. AP>У меня нет схемы твоей базы, не на чем прогонять CheckAllQueries.
Схема моей базы тут не причем. Потому что id находится в одной таблице, а Origin в другой, о чем ты и сам догадался. Это означает что твой тип IMessageInfo adhoc, и нужен исключительно для этого конкретного запроса. Поэтому его нужно было привести.
AP>“Тип IMessageInfo генерируется автоматически по полям запроса, поэтому его код смотреть не надо”.
Т.е. пишем запрос, компилируем, потом его дописываем, так что ли?
НС>Потому что сам посредник. И работы над устранением sql из цепочки LINQ-SQL Server уже ведутся.
Совсем уберут SQL? SQL Server без SQL. Как ты там написал, заодно уберут лишнее количество пользователей.
Здравствуйте, Alexander Polyakov, Вы писали:
НС>>Потому что сам посредник. И работы над устранением sql из цепочки LINQ-SQL Server уже ведутся. AP>Совсем уберут SQL?
НС>Т.е. пишем запрос, компилируем, потом его дописываем, так что ли?
Пишем код с запросом, IMessageInfo оставляем пустым. Запускаем CheckAllQueries, он выдает сообщение о том, что поля типа и запроса не совпадают, и в сообщении указывается полный код для IMessageInfo, который должен быть (генерируется на основе GetSchemaTable). Копирование текста IMessageInfo в cs-исходник сейчас делаем вручную. Хорошо бы это автоматизировать, но это не очень критично. Читаемость не страдает, поскольку IMessageInfo можно положить в укромное место и не заглядывать туда. А написание кода не такая большая проблема. Есть желание и имена таких типов сделать генеренными T001...T999, т.е. такие вот анонимные типы, но без ограничение на использование только внутри метода.
Здравствуйте, Alexander Polyakov, Вы писали:
НС>>Т.е. пишем запрос, компилируем, потом его дописываем, так что ли? AP>Пишем код с запросом, IMessageInfo оставляем пустым.
Но руками объявление таки придется написать, хоть и пустое.
AP> Запускаем CheckAllQueries, он выдает сообщение о том, что поля типа и запроса не совпадают, и в сообщении указывается полный код для IMessageInfo
AP>Копирование текста IMessageInfo в cs-исходник сейчас делаем вручную.
Прелестно.
AP> Хорошо бы это автоматизировать, но это не очень критично. Читаемость не страдает, поскольку IMessageInfo можно положить в укромное место и не заглядывать туда.
Вобщем, ты все отлично продемонстрировал. Я бы только не заикался после этого насчет сложности использования ExpressionMethod в linq2db.
НС>Будут работать в режиме совместимости, пока поддержку нового протокола не добавят.
А декомпозицию экспрешеннов в продукт от Microsoft когда добавят? Подозреваю, если этим вопросом озаботится Hejlsberg, то что-нибудь более удобоваримое получится, чем *Expr методы.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>При N=5 человек уже не может это делать.
V>Такой ты наивный... А как же раньше подобные задачи решались? )))
Также как и сейчас «решают», делают малое количество запросов\процедур, покрывающих сценарии. Запросы не эффективны, тормозят, пинают их хинтами, чтобы работало приемлемо.
V>Точно так же генерили SQL аж бегом.
Это только примитивные запросы, максимум джоины и простые предикаты, никаких группировок и подзапросов.
G>>Мой пример собирается в студии, я только оттуда несущественные детали убрал. Ты же пропустил довольно важные части.
V>А толку? Если в базе появилось лишнее поле, а ты забыл добавить его в свои объекты, то тебе компилятор не поможет. Зато помогли бы тулзы построения запросов — ты бы видел, что у тебя в базе.
Добавляй сразу в классы, ef добавит его в базу.
V>Более того, при ручной разработке запросов есть тенденция, что эти запросы будут оседать на стороне базы. А в твоём случае все запросы — динамические, даже когда 90% их статические или требует тривиальных аргументов. А у тебя выходит самый тормозной вариант из всех.
А с чего ты взял что динамические запросы — самый тормозной вариант? На практике как раз универсальный в среднем работает хуже, ибо кэширование планов и parameter sniffing problem, особенно когда запрос динамически строится внутри процедуры.
НС>... нового протокола не добавят.
В принципе это любопытно, и интересно будет следить чем закончится.
Интересно насколько сильно новый протокол окажется влияние на архитектуру SQL Server-а. Может они и реляционную модель собрались менять? Добавить поддержку связей типа message.Forum в сам SQL Server?
P.S. Пока ставлю на то, что эта благая затея закончится либо ничем, либо результат будет редко используемым. Никто не даст ломать SQL Server.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
НС>>>Генерировать мапперы по IL можно и в компайл-тайме. То что EF этого не умеет вовсе не означает, что это вообще невозможно. G>>Только сейчас это нельзя включить в библиотеку.
НС>Можно и включить, ilmerge никто пока не отменял. Но ты не находишь, что от фатального недостатка ты перешел к мелким неудобствам?
А кто вызывать то будет? С Roslyn можно в один пакет собрать и рантайм, и расширение компилятора.
НС>>>Это никак не избавляет от того, о чем говорит IB. G>>Он говорит о тормознутом мепинге НС>Нет, он говорит о неправильной архитектуре, требующей лишних шагов.
Так шаги можно в compile time проходить.
G>>, при компиляции модели в код и генерации mapping view во время компиляции можно устранить тормоза полностью.
НС>Только тормоза во время компиляции. Но и этого у EF все равно нет.
О чем ты?
НС>>>При чем тут SOAP? G>>При то что это основа ws-* вебсервисов, на которые wcf рассчитан в первую очередь.
НС>То что он рассчитан в первую очередь, это уже твои фантазии. Я лично знаком с некоторыми из архитекторов WCF, и многопротокольность там закладывалась с самого начала как базовое требование. Причем не только в плане message протоколов, но и протоколов сетевых.
Наверное именно поэтому в wcf шандарахнутое управление соединением и такой же api для коллбеков. Такое ощущение что эти функции прикрутили сверху к api для обычных ws-* вебсервисов.
НС> И в том числе поэтому WCF на порядок гибче и шире по функционалу WebAPI, но и, как следствие, имеет более крутую learning curve.
Это все слова ни о чем. Без тулинга wcf вообще невозможно пользоваться, примерно также, как ef первой версии. Только ef прокачали, а wcf так и остался.
G>>>>Я написал что они взаимоисключающие? Самая проблема что они все разные. НС>>>Не вижу проблемы. G>>Ну попробуй сходу написать код для хоста wcf с di в классы сервисов.
НС>Да писал не раз. Если понимаешь как WCF устроен — особых проблем нет. Ну и DI сам по себе — далеко не серебряная пуля. G>> Что для этого нужно?
НС>Тривиально реализовать крошечный интерфейс — IInstanceProvider. Один раз, если уж тебе так DI мил.
Реализовать где? Там же еще behavior надо реализовать, а потом еще атрибут или трахаться с конфигом.
G>> Толи factory сделать, толи service behavior поменять и это настолько разные апи, что хрен разберешься как правильно. НС>Ну так и проблема в том что ты не разобрался, а не в WCF.
Я то разобрался, но дофига народу не могут. Причем в webapi проблем с этим нет. Там одна задача — один класс, в wcf надо 100500 классов.
НС>>>Это одна строчка. G>>Это больше, особенно когда у тебя хост не в asp.net
НС>Нет. Ты опять не разобрался.
Пример?
НС>>>Есть. G>>По сравнению с webapi считай что нет. НС>По сравнению с WebAPI она на порядок круче, потому что позволяет создавать собственные шаблоны конфигураций. Но ты, я понимаю, опять не разобрался.
Ага, но это еще 100500 классов.
G>Добавляй сразу в классы, ef добавит его в базу.
А можно мы будем разрабатывать БД сами отдельно. Дельта скрипты для новых версий схемы БД будем писать тоже сами. Пусть EF не беспокоится об этом.
Приложение шлет запросы к базе данных. Вот пусть ORM помогает только на уровне приложения. Проврка запросов на этапе компиляции -- замечательно. Например, поменяли схему БД и EF должна нам сказать, где в исходном коде приложения нужно внести изменения?
Если не сложно опиши, как в таком режиме работать с EF?
НС>Это означает что твой тип IMessageInfo adhoc, и нужен исключительно для этого конкретного запроса.
Не только для запроса. Ты, наверное, не обратил внимания, что свойства ForumShortName, CreatedOn, Subject у тебя находятся в MessageModel, а у меня их там нет, они в IMessageInfo. Т.е. IMessageInfo используется не только для запроса, а и для переноса данных наружу метода.
Замечу, что у тебя слова CreatedOn, Subject пришлось написать по два раза, у меня они пишутся по одному разу. Поэтому с IMessageInfo даже меньше писать пришлось, а, соответственно, и читается лучше.
НС>Вобщем, ты все отлично продемонстрировал. Я бы только не заикался после этого насчет сложности использования ExpressionMethod в linq2db.
что я продемонстрировал? ты, наверное, не обратил внимание, что поля переехали из MessageModel в IMessageInfo. Ты в ручную пишешь поля в MessageModel, у меня они автоматически генерируются в IMessageInfo.
AP>Вот пусть ORM помогает только на уровне приложения. Проврка запросов на этапе компиляции -- замечательно. Например, поменяли схему БД и EF должна нам сказать, где в исходном коде приложения нужно внести изменения?
Можно даже термин такой ввести "ненавязчивый ORM" (unobtrusive).
Здравствуйте, gandjustas, Вы писали:
НС>>Можно и включить, ilmerge никто пока не отменял. Но ты не находишь, что от фатального недостатка ты перешел к мелким неудобствам? G>А кто вызывать то будет?
В смысле? Прописываешь таску в файл проекта, при компиляции msbuild позовет.
НС>>Нет, он говорит о неправильной архитектуре, требующей лишних шагов. G>Так шаги можно в compile time проходить.
Я бы не был так в этом уверен.
НС>>Только тормоза во время компиляции. Но и этого у EF все равно нет. G>О чем ты?
О том что EF не умеет прекомпиляцию.
НС>>То что он рассчитан в первую очередь, это уже твои фантазии. Я лично знаком с некоторыми из архитекторов WCF, и многопротокольность там закладывалась с самого начала как базовое требование. Причем не только в плане message протоколов, но и протоколов сетевых. G>Наверное именно поэтому в wcf шандарахнутое управление соединением
В чем оно шандарахнутое?
G>Такое ощущение что эти функции прикрутили сверху к api для обычных ws-* вебсервисов.
Это только ощущение.
G>Это все слова ни о чем.
Это не слова, это факты — функционал у WCF шире.
G> Без тулинга wcf вообще невозможно пользоваться
Не знаю о каком тулинге речь, но я в свое время пользовался.
НС>>Тривиально реализовать крошечный интерфейс — IInstanceProvider. Один раз, если уж тебе так DI мил. G>Реализовать где?
В своем проекте или в библиотеке DI.
G> Там же еще behavior надо реализовать,
Не надо.
G> а потом еще атрибут
Там всего строчек 5. Можно скопировать из примеров не включая моск. И, повторяю, сделать это надо ровно один раз. Проблема не стоит и выеденного яйца, не в пример старому ASP.NET, спроектированному через жопу.
НС>>Ну так и проблема в том что ты не разобрался, а не в WCF. G>Я то разобрался, но дофига народу не могут.
Кому надо, те могут.
G> Причем в webapi проблем с этим нет.
Зато там с другим проблемы есть.
G> Там одна задача — один класс, в wcf надо 100500 классов.
Не надо.
НС>>>>Это одна строчка. G>>>Это больше, особенно когда у тебя хост не в asp.net НС>>Нет. Ты опять не разобрался. G>Пример?
У меня совсем умолчальных примеров под рукой нет. Есть с некоторым конфигурированием из собственного конфига.
using (var host = new ServiceHost(info.Type, svcUris))
{
for (var i = 0; i < svcUris.Length; i++)
host.AddServiceEndpoint(
info.ContractType,
_commHelper.CreateBinding(_endpointConfigs[i].Transport),
svcUris[i]);
host.Open();
}
Конфигурирование WebAPI без IIS требует примерно сопоставимого объема кода.
НС>>По сравнению с WebAPI она на порядок круче, потому что позволяет создавать собственные шаблоны конфигураций. Но ты, я понимаю, опять не разобрался. G>Ага, но это еще 100500 классов.
В WebAPI тебе и 100500 классов не поможет. У каждого инструмента свои особенности.
Здравствуйте, Alexander Polyakov, Вы писали:
НС>>Вобщем, ты все отлично продемонстрировал. Я бы только не заикался после этого насчет сложности использования ExpressionMethod в linq2db. AP>что я продемонстрировал?
Кучу гемороя и раздутый плохочитаемый код на ровном месте вместо изящного и лаконичного решения на LINQ.
AP> ты, наверное, не обратил внимание, что поля переехали из MessageModel в IMessageInfo
MessageModel это вообще из другой области, это модель MVC вьюхи, и в ней есть данные, которые не из этого запроса берутся. Так что твои типы не спасут.
НС>Кучу гемороя и раздутый плохочитаемый код на ровном месте вместо изящного и лаконичного решения на LINQ.
Напиши какие элементы в моем коде раздули его, т.е. какие лишние элементы?
Какой геморой?
На EF6 у меня вот такой код падает в рантайме
List<int> list = entities.Message.Select(_ => _.Account.Field1).ToList();
с сообщением
Additional information: The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
В моем подходе такое отловится на этапе CheckAllQueries. Т.е. геморрой получили на LINQ EF6.
AP>> ты, наверное, не обратил внимание, что поля переехали из MessageModel в IMessageInfo НС>MessageModel это вообще из другой области, это модель MVC вьюхи, и в ней есть данные, которые не из этого запроса берутся. Так что твои типы не спасут.
В общем случае ты прав. А практически три из четырех полей все равно нужны в MessageModel, т.е. три поля, скорее всего, будут и в других запросах, заполняющих MessageModel. Оставшееся поле Text, да, может заполнятся не как функция от Origin. Но в реальности это не так часто. И для этих частых случаев сделать почти автогенеренный тип не проблема.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Добавляй сразу в классы, ef добавит его в базу. AP>А можно мы будем разрабатывать БД сами отдельно. Дельта скрипты для новых версий схемы БД будем писать тоже сами. Пусть EF не беспокоится об этом. AP>Приложение шлет запросы к базе данных. Вот пусть ORM помогает только на уровне приложения. Проврка запросов на этапе компиляции -- замечательно. Например, поменяли схему БД и EF должна нам сказать, где в исходном коде приложения нужно внести изменения? AP>Если не сложно опиши, как в таком режиме работать с EF?
Как хочешь, хоть руками пиши, хоть генерируй. Проблема все равно переходит на этап развертывания, ибо синхронизировать базу и код в разных средах становится проблемой.
Вариант получше — используй миграции с помощью тех же скриптов, только не автоматически, а по запросу. Тогда код и база будут синхронизированы или приложение упадет.
G>Как хочешь, хоть руками пиши, хоть генерируй. Проблема все равно переходит на этап развертывания, ибо синхронизировать базу и код в разных средах становится проблемой. G>Вариант получше — используй миграции с помощью тех же скриптов, только не автоматически, а по запросу. Тогда код и база будут синхронизированы или приложение упадет.
Какой сейчас рекомендованный вариант для получения классов из схемы БД? Т.е. я добавил колонку в БД, какую кнопку нажиматься, чтобы поле в классе появилось?
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Напиши какие элементы в моем коде раздули его, т.е. какие лишние элементы? AP>Какой геморой?
AP>На EF6 у меня вот такой код падает в рантайме AP>
AP>List<int> list = entities.Message.Select(_ => _.Account.Field1).ToList();
AP>
Это личные проблемы EF6. А точнее кривой модели, в которой для nullable поля должно быть int?.
НС>>MessageModel это вообще из другой области, это модель MVC вьюхи, и в ней есть данные, которые не из этого запроса берутся. Так что твои типы не спасут. AP>В общем случае ты прав.
НС>Это личные проблемы EF6. А точнее кривой модели, в которой для nullable поля должно быть int?.
Ты, наверное, не понял. В базе Field1 NOT NULL. Null получается за счет LEFT JOIN-а. Это протечка linq абстракций.
Здравствуйте, Alexander Polyakov, Вы писали:
НС>>Кучу гемороя и раздутый плохочитаемый код на ровном месте вместо изящного и лаконичного решения на LINQ. AP>Напиши какие элементы в моем коде раздули его, т.е. какие лишние элементы? AP>Какой геморой?
AP>На EF6 у меня вот такой код падает в рантайме AP>
AP>List<int> list = entities.Message.Select(_ => _.Account.Field1).ToList();
AP>
AP>с сообщением AP>
AP>Additional information: The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
AP>В моем подходе такое отловится на этапе CheckAllQueries. Т.е. геморрой получили на LINQ EF6.
Каким образом? Нельзя замапить nullable поле запроса, на non-nullable поле объекта? Но ведь мотом можно написать присвоение в select и получить ту же ошибку.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Как хочешь, хоть руками пиши, хоть генерируй. Проблема все равно переходит на этап развертывания, ибо синхронизировать базу и код в разных средах становится проблемой. G>>Вариант получше — используй миграции с помощью тех же скриптов, только не автоматически, а по запросу. Тогда код и база будут синхронизированы или приложение упадет. AP>Какой сейчас рекомендованный вариант для получения классов из схемы БД? Т.е. я добавил колонку в БД, какую кнопку нажиматься, чтобы поле в классе появилось?
Update model from database. Доступно еще с ef4.
G>Update model from database. Доступно еще с ef4.
Ну, т.е. это правильный способ? А то я волнуюсь вдруг эту ветку они закроют, ты вон агрессивно проповедуешь code first.
G>Каким образом? Нельзя замапить nullable поле запроса, на non-nullable поле объекта? Но ведь мотом можно написать присвоение в select и получить ту же ошибку.
У меня в аналогичном запросе проблем нет:
var list = Query<int>.New(new {threshold = 10m}, @"
SELECT Field1
FROM Message
LEFT JOIN Account ON Account.Id = Message.AccountId
").List();
CheckAllQueries указывает, что int надо заменить на "int?". Никаких протекших абстракций нет.
AP>>Напиши какие элементы в моем коде раздули его, т.е. какие лишние элементы? AP>>Какой геморой? НС>
Только эмоции? Указать нечего?
AP>>На EF6 у меня вот такой код падает в рантайме AP>>
AP>>List<int> list = entities.Message.Select(_ => _.Account.Field1).ToList();
AP>>
С linq2db еще хлеще: выдает неверные данные!!! Код:
Console.WriteLine(db.Messages.Select(_ => _.Account.Field1).ToList().Count(i => i == 0));
Console.WriteLine(db.Messages.Select(_ => _.Account.Field1).Count(i => i == 0));
AP>>На EF6 у меня вот такой код падает в рантайме AP>>
AP>>List<int> list = entities.Message.Select(_ => _.Account.Field1).ToList();
AP>>
НС>Это личные проблемы EF6. А точнее кривой модели, в которой для nullable поля должно быть int?.
Так и вижу вопрос на собеседовании. В таблицах Message и Account по 10 записей. Код
Console.WriteLine(db.Messages.Select(_ => _.Account.Field1).Count(i => i == 0));
печатает 1.
Вопрос, что напечатает код:
Console.WriteLine(db.Messages.Select(_ => _.Account.Field1).ToList().Count(i => i == 0));
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Каким образом? Нельзя замапить nullable поле запроса, на non-nullable поле объекта? Но ведь мотом можно написать присвоение в select и получить ту же ошибку. AP>У меня в аналогичном запросе проблем нет: AP>
AP> var list = Query<int>.New(new {threshold = 10m}, @"
AP>SELECT Field1
AP>FROM Message
AP> LEFT JOIN Account ON Account.Id = Message.AccountId
AP>").List();
AP>
AP>CheckAllQueries указывает, что int надо заменить на "int?". Никаких протекших абстракций нет.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Update model from database. Доступно еще с ef4. AP>Ну, т.е. это правильный способ? А то я волнуюсь вдруг эту ветку они закроют, ты вон агрессивно проповедуешь code first.
Не волнуйся, не закроют. Тем не менее code first для разработчика удобнее.
V>>Такой ты наивный... А как же раньше подобные задачи решались? ))) G>Также как и сейчас «решают», делают малое количество запросов\процедур, покрывающих сценарии.
"Мало" это сколько? Вот предположи, сколько суммарно на стороне базы сохраненных запросов и хранимок в средненькой системе, когда базу разрабатывают именно как базу, а не как "тупое хранилище объектов", где все запросы идут на LINQ? Почитав твои ответы ниже, я уверен, что ответ тебя удивит.
G>Запросы не эффективны, тормозят, пинают их хинтами, чтобы работало приемлемо.
Это LINQ генерит жутко неэффективные запросы.
А хинты нужны малость для другого, тут исходный способ генерирования запроса не при чем от слова вообще. Но они, действительно, часто нужны. Только не понятно, как ими пользоваться из LINQ? ))
V>>Точно так же генерили SQL аж бегом. G>Это только примитивные запросы, максимум джоины и простые предикаты, никаких группировок и подзапросов.
Я вижу, ты страшно далек от понимания того, как подобные задачи решали и решают без LINQ. Обычно в тиме работает человек, специализирующийся на базах и запросах, он умеет SQL намного лучше, чем ты свой C# когда-либо умел или сумеешь. Ну и понимание происходящего в базе на порядки лучше твоего. Так бывает, когда человек многие годы на чём-то специализируется. )) Поэтому, твоя наивность опять зашкаливает. Если чего-то не знаешь — лучше спросить, ИМХО.
G>>>Мой пример собирается в студии, я только оттуда несущественные детали убрал. Ты же пропустил довольно важные части.
V>>А толку? Если в базе появилось лишнее поле, а ты забыл добавить его в свои объекты, то тебе компилятор не поможет. Зато помогли бы тулзы построения запросов — ты бы видел, что у тебя в базе. G>Добавляй сразу в классы, ef добавит его в базу.
Не со всеми нужными св-вами. Не со всеми связями, ограничениями, триггерами и т.д. до бесконечности. Как-то ты примитивно рассматриваешь базу, однако.
V>>Более того, при ручной разработке запросов есть тенденция, что эти запросы будут оседать на стороне базы. А в твоём случае все запросы — динамические, даже когда 90% их статические или требует тривиальных аргументов. А у тебя выходит самый тормозной вариант из всех. G>А с чего ты взял что динамические запросы — самый тормозной вариант? На практике как раз универсальный в среднем работает хуже, ибо кэширование планов и parameter sniffing problem, особенно когда запрос динамически строится внутри процедуры.
Согласен только насчет последнего, но это извращение, а не аргумент в споре. Динамические, как раз, можно построить "извне" базы и так часто и делают. Но я утверждаю, что таких запросов (динамических по своей структуре, а не по простым параметрам) менее 10% от обслуживаемых средней базой в течении суток, скажем. А то и менее 1%, положа руку на. Это обычно только какие-нить специфические отчеты, редко потребляемая аналитика или что-то в этом роде. Я не спорю, что таких запросов может быть абсолютное большинство, если считать запросы не в кол-ве реальных употреблений, а в штуках наличия самих запросов. Но это маргинальный, по-сути, сценарий, на который, как раз LINQ прекрасно ложится. Т.е. LINQ хорош в процессе построения нетривиальных, динамических запросов, угу. Но это же development time для 90-99% реальных случаев. Зачем же снова и снова строить одни и те же запросы в рантайм? )))
Здравствуйте, fddima, Вы писали:
F> Да. Поборники достойности — мой десктоп способен обслужить 7K+ запросов весьма нифика не простых запросов. И это всё через LINQ. RAW — будет быстрее. Но — ещё быстрее — будет без SQL вообще. Так что заранее прошу — глупости тут не городить. Да. Без сиквела — 20K+.
AP>> Хорошо бы это автоматизировать, но это не очень критично. Читаемость не страдает, поскольку IMessageInfo можно положить в укромное место и не заглядывать туда. НС>Вобщем, ты все отлично продемонстрировал. Я бы только не заикался после этого насчет сложности использования ExpressionMethod в linq2db.
Давай сравним. Какие проблемы вызывает ExpressionMethod? Если разработчик не пометит метод атрибутом, приложение упадет в рантайме. Если разработчик ошибется в атрибуте в имени *Expr метода, приложение упадет в рантайме. Если в *Expr будет неверная сигнатура (количество и типы параметров), приложение упадет в рантайме. Я правильно помню, linq вводили, чтобы ошибки отлавливать в компайл тайме, а не в рантайме?
Теперь давай посмотрим, что я этим в моем подходе? В настоящий рантайм ничего такого не просачивается, всё отлавливается на этапе CheckAllQueries. Читаемость кода не страдает, поскольку код IMessageInfo читать не надо. Есть слегка неудобный момент при написании кода. Даже вручную прописать проперти в IMessageInfo и то не проблема, это будет проверено машиной. Поэтому я имею полное право заикаться о ExpressionMethod, который генерирует дополнительные ошибки в рантайме.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>P.S. Пока ставлю на то, что эта благая затея закончится либо ничем, либо результат будет редко используемым. Никто не даст ломать SQL Server.
Не знаю как в последних версиях, но раньше была библиотека доступа к данным MS SQL-сервака без SQL.
И вообще, в протоколе SQL-сервака много повторяющейся информации. Например, даже если мы возвращаем всего одну строчку на один и тот же запрос, то каждый раз идёт метаинформация о столбцах, объем которой может значительно превышать объем полезных данных. Соответственно, каждый раз на стороне клиента тоже происходит куча тупой, ненужной работы — динамическое построение парсера потока данных SQL. При обмене типизированными запросами и использовании запросов как удалённых объектов, можно было бы избежать кучу дублированных данных и ненужной работы, можно было бы делать парсеры статически-компилированными (парсить данные прямо в поля объектов, как при маршалинге и десериализации), а не динамическими или работающими по мета-информации.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Такой ты наивный... А как же раньше подобные задачи решались? ))) G>>Также как и сейчас «решают», делают малое количество запросов\процедур, покрывающих сценарии.
V>"Мало" это сколько? Вот предположи, сколько суммарно на стороне базы сохраненных запросов и хранимок в средненькой системе, когда базу разрабатывают именно как базу, а не как "тупое хранилище объектов", где все запросы идут на LINQ? Почитав твои ответы ниже, я уверен, что ответ тебя удивит.
Я мигрировал небольшой проект на Linq, было 3-5 хранимок на таблицу для выборок, для таблиц с кучей колонок было побольше. После переписывания на Linq стало около 20 запросов на таблицу. Точной статистики, увы, не осталось.
G>>Запросы не эффективны, тормозят, пинают их хинтами, чтобы работало приемлемо. V>Это LINQ генерит жутко неэффективные запросы.
Люди генерят неэффективные запросы, а Linq может косячить только в очень сложных случаях, которые вообще бессмысленно на Linq писать.
Вот мой личный хит-парад причин неэффективных запросов:
1) Отсутствие проекций. Люди не пишут select, это приводит к тому что тянется слишком много данных (особенно проблема для длинных строк и блобов) и не получается построить покрывающий индекс.
2) Люди пишут Linq запросы не понимая что происходит в базе. Особенно часто встречается FirstOrDefault, который в SQL работает очень медленно, или банально вызывают функции в предикатах.
3) Люди пытаются на Linq написать то, что в базе уже есть, но нет в Linq. Видел такие рукопашные реализации FTS и оператора Merge.
V>А хинты нужны малость для другого, тут исходный способ генерирования запроса не при чем от слова вообще. Но они, действительно, часто нужны.
Я не знаю для чего по твоему нужны хинты, я видел как их применяют при использовании хранимок для Data Access.
V>Только не понятно, как ими пользоваться из LINQ? ))
Это показывает твой уровень знания SQL
plan guide вообще-то есть.
V>>>Точно так же генерили SQL аж бегом. G>>Это только примитивные запросы, максимум джоины и простые предикаты, никаких группировок и подзапросов.
V>Я вижу, ты страшно далек от понимания того, как подобные задачи решали и решают без LINQ. Обычно в тиме работает человек, специализирующийся на базах и запросах, он умеет SQL намного лучше, чем ты свой C# когда-либо умел или сумеешь. Ну и понимание происходящего в базе на порядки лучше твоего. Так бывает, когда человек многие годы на чём-то специализируется. )) Поэтому, твоя наивность опять зашкаливает. Если чего-то не знаешь — лучше спросить, ИМХО.
Я вообще-то занимаюсь обучением таких DBA и прекрасно осведомлен об их способностях.
Если есть отдельный DBA, который не лезет в код, и программисты, которые не лезут в базу, то получается impendance mismatch между людьми.
Если DBA "главнее" программистов, то он рисует базу, небольшой набор хранимок (большой поддерживать влом), запинывает их хинтами и грозится оторвать руки тем, кто фигачит Adhoc запросы в базу. При этом хранимок мало, они не отражают реальные потребности приложения и отдают зачастую слишком много данных, а программисты на стороне приложения сами разбираются.
Если же программисты "главнее" DBA, то программисты юзают базу как тупое хранилище объектов, а DBA только пишет batch processing для самых тормозящих сценариев.
Лет 7-8 назад такое было повсеместно, потом появился Linq и больше C# программистов стало понимать что происходит в базе и как сделать оптимальной работу с СУБД.
Но тебя это, видимо не коснулось. Не беспокойся, еще не поздно изучить.
G>>>>Мой пример собирается в студии, я только оттуда несущественные детали убрал. Ты же пропустил довольно важные части.
V>>>А толку? Если в базе появилось лишнее поле, а ты забыл добавить его в свои объекты, то тебе компилятор не поможет. Зато помогли бы тулзы построения запросов — ты бы видел, что у тебя в базе. G>>Добавляй сразу в классы, ef добавит его в базу.
V>Не со всеми нужными св-вами. Не со всеми связями, ограничениями, триггерами и т.д. до бесконечности. Как-то ты примитивно рассматриваешь базу, однако.
Так добавь что нужно, тебя никто не ограничивает.
V>>>Более того, при ручной разработке запросов есть тенденция, что эти запросы будут оседать на стороне базы. А в твоём случае все запросы — динамические, даже когда 90% их статические или требует тривиальных аргументов. А у тебя выходит самый тормозной вариант из всех. G>>А с чего ты взял что динамические запросы — самый тормозной вариант? На практике как раз универсальный в среднем работает хуже, ибо кэширование планов и parameter sniffing problem, особенно когда запрос динамически строится внутри процедуры.
V>Согласен только насчет последнего, но это извращение, а не аргумент в споре. Динамические, как раз, можно построить "извне" базы и так часто и делают. Но я утверждаю, что таких запросов (динамических по своей структуре, а не по простым параметрам) менее 10% от обслуживаемых средней базой в течении суток, скажем. А то и менее 1%, положа руку на.
Не пойму что ты сказать хочешь. Количество запросов, генерируемых программой — конечно (без учета параметров), кеш планов SQL Server на этот факт и рассчитан.
Например у тебя в программе есть Grid, который позволяет фильтровать и сортировать по любой колонке (как excel). Количество разных (без учета параметризации) запросов будет очень большим (порядка 2n*2^n!, где n — кол-во колонок), но конечным. При этом если грид на главной странице приложения, то на эти динамические запросы будет приходится большая часть запросов. Или это по твоему не динамические запросы?
Что ты имеешь ввиду под динамическими запросами?
V>Это обычно только какие-нить специфические отчеты, редко потребляемая аналитика или что-то в этом роде. Я не спорю, что таких запросов может быть абсолютное большинство, если считать запросы не в кол-ве реальных употреблений, а в штуках наличия самих запросов.
Как раз для отчетов запросы статичны, то есть они один раз задаются и много раз вызываются.
V>Но это маргинальный, по-сути, сценарий, на который, как раз LINQ прекрасно ложится. Т.е. LINQ хорош в процессе построения нетривиальных, динамических запросов, угу. Но это же development time для 90-99% реальных случаев. Зачем же снова и снова строить одни и те же запросы в рантайм? )))
У тебя каша в голове.
Давай по порядку: что ты называешь динамическими запросами?
Я грешным делом подумал что называешь динамическими запросы, которые клеятся по кускам, но прочитав твой ответ я понял, что не понял что ты называешь динамическими запросами.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>А где select? AP>Ты о чем? Написано же "SELECT Field1".
Не этот селект, а вот такой:
return Query<IMessageInfo>.New(new {id}, @"
SELECT f.ShortName ForumShortName, m.CreatedOn, m.Subject, a.Origin
FROM Message m
JOIN Forum f ON f.Id = m.ForumId
OUTER JOIN Account a ON a.Id = m.AccountId
WHERE m.Id = @id AND f.ReadLevel <= @Account.AccessLevel
").Select(_ => new MessageModel {
Origin = _.Origin
}));
Предположим что поле Account.Origin это int.
Вот ты говорил что IMessageInfo у тебя генерируется автоматом (интересно в какой момент, но это отдельный вопрос). В нем Origin будет иметь тип (int?).
А вот совершенно случайно MessageModel.Origin имеет тип int.
Это кейс эквивалентный тому, что ты написал с помощью Linq.
Кстати пока писал понял одну вешь ты передаешь new {id} параметром, то есть первый агрумент у тебя имеет тип object. Таким образом ты не можешь формировать объект-параметр вне функции, где вызвается New. Ну и стандартная проблема с передачей в SQL значений null.
Здравствуйте, Alexander Polyakov, Вы писали:
НС>>Т.е. пишем запрос, компилируем, потом его дописываем, так что ли? AP>Пишем код с запросом, IMessageInfo оставляем пустым. Запускаем CheckAllQueries, он выдает сообщение о том, что поля типа и запроса не совпадают, и в сообщении указывается полный код для IMessageInfo, который должен быть (генерируется на основе GetSchemaTable). Копирование текста IMessageInfo в cs-исходник сейчас делаем вручную. Хорошо бы это автоматизировать, но это не очень критично. Читаемость не страдает, поскольку IMessageInfo можно положить в укромное место и не заглядывать туда. А написание кода не такая большая проблема. Есть желание и имена таких типов сделать генеренными T001...T999, т.е. такие вот анонимные типы, но без ограничение на использование только внутри метода.
Выделенное повеселило. После этого ты еще ругаешь Linq... Лучше не продолжай.
Здравствуйте, gandjustas, Вы писали:
G>Тем не менее твоя вера расходится с фактами. Как бы тебе не верилось обратное.
Факты очень просты — EF настолько крив, что его решили выкинуть и переписать с нуля. Моя вера находится в полном согласии с этим фактом.
Так что будь мужиком, смирись уже =)
G>Ты же ни одного факта не привел, а религиозный бред уже фильтрую не задумываясь.
Ты фильтруешь не задумываясь все, что противоречит твоим убеждениям, в том числе и факты.
G>Или ты оцениваешь технологии исключительно о пресс-релизам? Это верх профессионализма сейчас?
Если в пресс-релизе написано, что технология оказалась говном и мы начинаем переписывать заново, то я совершенно справедливо решаю, что больше в эту технологию лезть не стоит.
А верх профессионализма заключается в том, что довольно подробно протестировав каждый из релизов, включая самые последние, я последние пять лет говорил о том, что в этом пресс-релизе и сказано — технология говно и имеет врожденные проблемы. И настоял на том, чтобы эта технология у нас не использовалась ни в каком виде.
Как видишь — был прав.
G>Опять идеологическая чушь. Почему-то при кривой идеологии чуваки смогли прикрутить к ef кучу фич, тип асинхронности, code-first, миграций, повысили быстродействие на порядки, создали community с кучей расширений и провайдеров. Несмешименя ))
Чуваки налабали кучу никому не нужного кода и сами признали что код говно и никому не нужен. Изначально написали так криво, что смогли серьезно ускорить, но так и не научились генерить нормальный SQL, где и случаются основные потери. Вбухали столько сил и ресурсов, что можно было бы с десяток ORM-ов написать и наконец-таки признали, что это проще выкинуть чем довести до ума.
И причины этого — совершенно верно, в изначально ущербной идее.
G>Дай бог каждому такие «кривые» идеи придумывать.
Вот не дай бог — эту еще не до конца похоронили ))
G>То есть roslyn == похоронили c#, asp.net vnext == похоронили asp.net, любой мажорный релиз продукта == похоронили продукт?
Мажорный релиз продукта не заключается в полном выкидывании всего кода и переписывании с нуля. Они не зря говорят о продолжении ветки EF 6.1, 6.1.1 для тех нещчастных, кто не сможет быстро с него слезть.
G>Я уже понял что ты технологии по пресс-релизам оцениваешь.
Это не я по пресс-релизам оцениваю, а ты лучше разработчиков знаешь что из себя их продукт представляет =)
V>И вообще, в протоколе SQL-сервака много повторяющейся информации. Например, даже если мы возвращаем всего одну строчку на один и тот же запрос, то каждый раз идёт метаинформация о столбцах, объем которой может значительно превышать объем полезных данных. Соответственно, каждый раз на стороне клиента тоже происходит куча тупой, ненужной работы — динамическое построение парсера потока данных SQL. При обмене типизированными запросами и использовании запросов как удалённых объектов, можно было бы избежать кучу дублированных данных и ненужной работы, можно было бы делать парсеры статически-компилированными (парсить данные прямо в поля объектов, как при маршалинге и десериализации), а не динамическими или работающими по мета-информации.
При использовании SqlCommand.Prepare между клиентом и сервером ходит только интовый идентификатор запроса и параметры. Это под SQL профайлером видно.
В SQL Server-е запрос всё равно лежит в кеше планов. По запросу надо как-то вычислять его ключ в кеше. Если такое вычисление выполнять и на клиенте, то при обмене между клиентом и сервером можно гонять только ключ. А на клиенте кешировать методанные по этому же ключу.
Т.е. оптимизацию можно сделать и без статически типизированных запросов.
AP>>Пишем код с запросом, IMessageInfo оставляем пустым. Запускаем CheckAllQueries, он выдает сообщение о том, что поля типа и запроса не совпадают, и в сообщении указывается полный код для IMessageInfo, который должен быть (генерируется на основе GetSchemaTable). Копирование текста IMessageInfo в cs-исходник сейчас делаем вручную. Хорошо бы это автоматизировать, но это не очень критично. Читаемость не страдает, поскольку IMessageInfo можно положить в укромное место и не заглядывать туда. А написание кода не такая большая проблема. Есть желание и имена таких типов сделать генеренными T001...T999, т.е. такие вот анонимные типы, но без ограничение на использование только внутри метода. G>Выделенное повеселило. После этого ты еще ругаешь Linq... Лучше не продолжай.
Вот уже ответил http://rsdn.ru/forum/flame.comp/5666409
Здравствуйте, IT, Вы писали:
IT>Что же они так? Спросили бы меня как надо было делать EF с самого начала. Я бы им ещё лет 5 назад рассказал. Стоило выпускать 6 релизов, чтобы понять, что 7-й нужно переписывать с нуля.
Да я им сам рассказывал — не слушали ((
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>Тем не менее твоя вера расходится с фактами. Как бы тебе не верилось обратное. IB>Факты очень просты — EF настолько крив, что его решили выкинуть и переписать с нуля. Моя вера находится в полном согласии с этим фактом. IB>Так что будь мужиком, смирись уже =)
Переписывают не потому что "он крив", а потому что текущая архитектура не позволяет достичь целей. Самая важная цель кстати чтобы работало в KRuntime и WinRT.
Раньше позволяла — прикрутили и codefirst, и миграции и производительность поправили.
Вообще у тебя проблема с причинно следственными связями. Если нечто криво, то его надо переписать. С этим я согласен. Но обратное в общем случае неверно. Если что-то надо переписать, то это не значит что оно кривое. Даже если ты в это веришь.
G>>Ты же ни одного факта не привел, а религиозный бред уже фильтрую не задумываясь. IB>Ты фильтруешь не задумываясь все, что противоречит твоим убеждениям, в том числе и факты.
Ну приведи факты — конкретно примеры кода, которые твои слова подтверждают.
G>>Или ты оцениваешь технологии исключительно о пресс-релизам? Это верх профессионализма сейчас? IB>Если в пресс-релизе написано, что технология оказалась говном и мы начинаем переписывать заново, то я совершенно справедливо решаю, что больше в эту технологию лезть не стоит.
Молодец. Очень профессиональный подход.
IB>А верх профессионализма заключается в том, что довольно подробно протестировав каждый из релизов, включая самые последние
Ну хватит врать уже. Ты даже ни одного примера привести не можешь, ты и тестировал по пресс-релизам.
G>>То есть roslyn == похоронили c#, asp.net vnext == похоронили asp.net, любой мажорный релиз продукта == похоронили продукт? IB>Мажорный релиз продукта не заключается в полном выкидывании всего кода и переписывании с нуля. Они не зря говорят о продолжении ветки EF 6.1, 6.1.1 для тех нещчастных, кто не сможет быстро с него слезть.
А кто говорит о полном переписывании ef? Глянь в репозитарии, притащили немало кода.
G>>Я уже понял что ты технологии по пресс-релизам оцениваешь. IB>Это не я по пресс-релизам оцениваю, а ты лучше разработчиков знаешь что из себя их продукт представляет =)
Я не знаю, я проверяю.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>>>Пишем код с запросом, IMessageInfo оставляем пустым. Запускаем CheckAllQueries, он выдает сообщение о том, что поля типа и запроса не совпадают, и в сообщении указывается полный код для IMessageInfo, который должен быть (генерируется на основе GetSchemaTable). Копирование текста IMessageInfo в cs-исходник сейчас делаем вручную. Хорошо бы это автоматизировать, но это не очень критично. Читаемость не страдает, поскольку IMessageInfo можно положить в укромное место и не заглядывать туда. А написание кода не такая большая проблема. Есть желание и имена таких типов сделать генеренными T001...T999, т.е. такие вот анонимные типы, но без ограничение на использование только внутри метода. G>>Выделенное повеселило. После этого ты еще ругаешь Linq... Лучше не продолжай. AP>Вот уже ответил http://rsdn.ru/forum/flame.comp/5666409
AP>У вас нет обоснованных претензий, только эмоции.
Любая ручная операция — повышение вероятности ошибки. Я та понял что у тебя руками запускается и CheckAllQueries, и копируется IMessageInfo руками. То есть на каждое изменение запроса нужно два ручных действия. Такого убожества нигде нет. Даже не представляю что надо делать, чтобы это было оправдано. Кстати как вы боретесь с коллизиями имен при генерации проекций?
Здравствуйте, vdimas, Вы писали:
V>когда базу разрабатывают именно как базу, а не как "тупое хранилище объектов", где все запросы идут на LINQ
Запросы на LINQ вовсе не означают использование БД как тупого хранилища объектов. Скорее наоборот, в случае такого использования толку от LINQ немного.
G>>Запросы не эффективны, тормозят, пинают их хинтами, чтобы работало приемлемо. V>Это LINQ генерит жутко неэффективные запросы.
Во-первых сам по себе LINQ ничего не генерит, генерит конкретный провайдер. А во-вторых неплохо бы обосновать.
V>Но они, действительно, часто нужны.
Зависит от конкретного SQL сервера и конкретной задачи.
V> Только не понятно, как ими пользоваться из LINQ? ))
Да ничего неожиданного. Можно, к примеру, так:
db
.Messages
.WithIndex(Message.IDIndex)
.Select(m => m.ID)
.Option(SqlOption.HashGroup)
.Option(SqlOption.Fast, 10);
Хинты и LINQ, в общем случае, перпендикулярны.
V>Я вижу, ты страшно далек от понимания того, как подобные задачи решали и решают без LINQ. Обычно в тиме работает человек, специализирующийся на базах и запросах, он умеет SQL намного лучше, чем ты свой C# когда-либо умел или сумеешь.
Ага, а потом я в таких проектах переписываю хранимки на linq2db и получаю ускорение в 2-3 раза.
V>Зачем же снова и снова строить одни и те же запросы в рантайм? )))
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Давай сравним. Какие проблемы вызывает ExpressionMethod? Если разработчик не пометит метод атрибутом, приложение упадет в рантайме. Если разработчик ошибется в атрибуте в имени *Expr метода, приложение упадет в рантайме. Если в *Expr будет неверная сигнатура (количество и типы параметров), приложение упадет в рантайме. Я правильно помню, linq вводили, чтобы ошибки отлавливать в компайл тайме, а не в рантайме?
Это библиотечные вещи, на которые один раз пишется тест, отлавливающий все проблемы. Ну и nameof уже на горизонте, так что часть проблем будет скоро устранена.
AP>Теперь давай посмотрим, что я этим в моем подходе?
Давай. На каждый запрос куча танцев с бубном — предварительный вариант, компиляция, заведение новых интерфейсов, переделка исходного запроса.
AP>В настоящий рантайм ничего такого не просачивается, всё отлавливается на этапе CheckAllQueries.
Статический верификатор можно и к LINQ приделать, так что это не повод от него отказываться.
AP> Читаемость кода не страдает, поскольку код IMessageInfo читать не надо.
Зато надо вгрызаться в строковый литерал, в котором ни подсветки синтаксиса, ни навигации, ни тултипов, ни интеллисенса.
AP> Есть слегка неудобный момент при написании кода.
Здравствуйте, gandjustas, Вы писали:
G>Выделенное повеселило. После этого ты еще ругаешь Linq... Лучше не продолжай.
Бесполезно. Понимаешь, когда он эту ерунду писал 3 года назад — ну что, бывает, многие пытаются трехколесные велосипеды изобретать. Но когда он тоже самое пишет сейчас — это уже о многом говорит.
G>>А вот совершенно случайно MessageModel.Origin имеет тип int.
Не скомпилруется. В чем вопрос?
G>>Это кейс эквивалентный тому, что ты написал с помощью Linq.
Нет! Не эквивалентен! В моём подходе такого бреда никогда не будет: ставим в середину цепочки .ToList() и получаем другой результат.
Вот так помаленьку вы и обкрадываете заказчика: бизнес логика почти не менялась, потребовалось только материализовать промежуточный результат. И вы нарвались на геморрой с выяснений косяков "особенностей" конкретной ORM. А геморрой в чем? Либо надо тщательное тестирование с данными, либо это выстрелит на продакшене. С ходу в чем проблема не поймешь, придется бросить все дела и начать копать эту проблему. Это не сравнимо с тем, чтобы перенести текст из одного окна в другой на этапе написании кода, делается на автомате без включения мозга.
G>>Кстати пока писал понял одну вешь ты передаешь new {id} параметром, то есть первый агрумент у тебя имеет тип object. Таким образом ты не можешь формировать объект-параметр вне функции, где вызвается New.
Это и не нужно.
Для точности, параметр имеет тип T.
G>>Ну и стандартная проблема с передачей в SQL значений null.
Решена естественным образом через Option<T>.
G>Любая ручная операция — повышение вероятности ошибки. Я та понял что у тебя руками запускается и CheckAllQueries, и копируется IMessageInfo руками. То есть на каждое изменение запроса нужно два ручных действия. Такого убожества нигде нет. Даже не представляю что надо делать, чтобы это было оправдано. Кстати как вы боретесь с коллизиями имен при генерации проекций?
CheckAllQueries запускается также на тестовой среде автоматом. Ну вы как маленькие, у вас что тестов нету?
Ручные операции не проблема, если дальше идет машинная проверка. Опять как маленькие, выступаете за компайл проверки, а сути ее не чувствуете.
НС>Это библиотечные вещи, на которые один раз пишется тест, отлавливающий все проблемы. Ну и nameof уже на горизонте, так что часть проблем будет скоро устранена.
Это универсально? Если, да, то это уже выложили на github вместе c linq2db? Или вы уже перешли к обсуждению несуществующего решения?
НС>Давай. На каждый запрос куча танцев с бубном — предварительный вариант, компиляция, заведение новых интерфейсов, переделка исходного запроса.
Прошу быть более конкретным и конструктивным. Какую переделку запроса вы имеете ввиду? Я ничего такого не писал.
AP>>В настоящий рантайм ничего такого не просачивается, всё отлавливается на этапе CheckAllQueries. НС>Статический верификатор можно и к LINQ приделать, так что это не повод от него отказываться.
Если скопировать ваше поведение, то мне надо тут поставить ваш любимый смайл
НС>Зато надо вгрызаться в строковый литерал, в котором ни подсветки синтаксиса, ни навигации, ни тултипов, ни интеллисенса.
Для VS2012 был экстеншен для подсветки SQL синтаксиса в строковых литералах. Для VS2013 пока не вышла. Да, с этим проблемы есть, но опять скопирую вас: это не повод отказываться от этого подхода. Даже Dapper получил широкое распространение, а там автоматической проверки запросов нет.
НС>Слегка?
Эмоции зашкаливают?
Здравствуйте, Alexander Polyakov, Вы писали:
G>>>А вот совершенно случайно MessageModel.Origin имеет тип int. AP>Не скомпилруется. В чем вопрос?
Ну да, тут компилятор выругается.
G>>>Это кейс эквивалентный тому, что ты написал с помощью Linq. AP>Нет! Не эквивалентен! В моём подходе такого бреда никогда не будет: ставим в середину цепочки .ToList() и получаем другой результат.
Ну так ты и в Linq ставишь ToList и получаешь другой результат...
А вообще с ToList ты дважды создешь объекты, что удваивает нагрузку на GC и снижает производительность. Идеальный вариант когда материализутся объекты, которые сразу отдаются в генерацию страниц.
AP>Вот так помаленьку вы и обкрадываете заказчика: бизнес логика почти не менялась, потребовалось только материализовать промежуточный результат. И вы нарвались на геморрой с выяснений косяков "особенностей" конкретной ORM. А геморрой в чем? Либо надо тщательное тестирование с данными, либо это выстрелит на продакшене. С ходу в чем проблема не поймешь, придется бросить все дела и начать копать эту проблему. Это не сравнимо с тем, чтобы перенести текст из одного окна в другой на этапе написании кода, делается на автомате без включения мозга.
Не понял, зачем материализовывать промежуточный результат? Это затратно и непонятно зачем, никакого value не несет. А потом еще и чето надо запускать и руками копировать, что обязательно забудут.
И почему с ходу не поймешь проблему что из базы вернулся null, а ты его мапишь на не-null? Это же случается только для чисел и дат, почему вообще в класс view model попадет свойство с типом int, если оно может отсутствовать?
G>>>Ну и стандартная проблема с передачей в SQL значений null. AP>Решена естественным образом через Option<T>.
Покажи пример кода.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Любая ручная операция — повышение вероятности ошибки. Я та понял что у тебя руками запускается и CheckAllQueries, и копируется IMessageInfo руками. То есть на каждое изменение запроса нужно два ручных действия. Такого убожества нигде нет. Даже не представляю что надо делать, чтобы это было оправдано. Кстати как вы боретесь с коллизиями имен при генерации проекций? AP>CheckAllQueries запускается также на тестовой среде автоматом. Ну вы как маленькие, у вас что тестов нету?
Тесты есть, но Linq таки ловит опечатки в процессе написания. На тесте я могу и реальные запросы прогнать. Заем тогда CheckAllQueries и писать текст.
AP>Ручные операции не проблема, если дальше идет машинная проверка. Опять как маленькие, выступаете за компайл проверки, а сути ее не чувствуете.
Проблема, еще какая, ибо тратится время. Компайл-тайм проверки хороши если работают автоматически. Но с твоей штукой требуется вручную что-то копировать, поэтому и проверку надо вручную запускать.
Здравствуйте, gandjustas, Вы писали:
G>Переписывают не потому что "он крив", а потому что текущая архитектура не позволяет достичь целей.
То есть кривая. Что и требовалось доказать.
G>Раньше позволяла — прикрутили и codefirst, и миграции и производительность поправили.
Да-да, и в итоге получили "... many seldom used features and capabilities in the code base that hamper performance and complicate development" (с)
G>Вообще у тебя проблема с причинно следственными связями. Если нечто криво, то его надо переписать. С этим я согласен. Но обратное в общем случае неверно. Если что-то надо переписать, то это не значит что оно кривое.
Прекрасно! может быть это значит что оно просто не очень прямое? =)))
G>Молодец. Очень профессиональный подход.
Всяко профессиональнее чем в отходах копаться и убеждать всех, что они прекрасны =)
G>Ну хватит врать уже.
Не нарывайся.
G>А кто говорит о полном переписывании ef?
Разработчики и говорят, но ты же идеологию не читаешь. =)
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>Переписывают не потому что "он крив", а потому что текущая архитектура не позволяет достичь целей. IB>То есть кривая. Что и требовалось доказать.
Странная логика, любая архитектура — набор ограничений. Заранее ты не знаешь какие цели будут поставлены. То есть в принципе любая архитектура кривая.
G>>Раньше позволяла — прикрутили и codefirst, и миграции и производительность поправили. IB>Да-да, и в итоге получили "... many seldom used features and capabilities in the code base that hamper performance and complicate development" (с)
Это слова, всего лишь чье-то мнение, а ты примеры покажи. По факту для типовых применений orm сегодня ef работает отлично, как бы тебе не верилось в обратное. Команда ef поставила очень амбициозную цель — сделать ef единственным средством data access на всех платформах, поэтому у них есть претензии. У тебя и близко таких проблем нет и не будет никогда. Цитирование пресс-релизов никак не ситуацию не исправит.
G>>Вообще у тебя проблема с причинно следственными связями. Если нечто криво, то его надо переписать. С этим я согласен. Но обратное в общем случае неверно. Если что-то надо переписать, то это не значит что оно кривое. IB>Прекрасно! может быть это значит что оно просто не очень прямое? =)))
По твоей логике значит. А вообще не значит.
G>>Молодец. Очень профессиональный подход. IB>Всяко профессиональнее чем в отходах копаться и убеждать всех, что они прекрасны =)
У тебя хоть когда-нибудь факты появятся?
G>>Ну хватит врать уже. IB>Не нарывайся.
Так приводи факты, а не мнение. Твое мнение совершенно ничего не стоит, ты это уже доказал.
G>>А кто говорит о полном переписывании ef? IB>Разработчики и говорят, но ты же идеологию не читаешь. =)
Угу, я исходники читаю. Тебе тоже советую. Пока что все переписывание свелось к копированию code-first почти полностью и выкидыванию objectcontext и связанных классов.
Тебе тоже советую почитать.
Здравствуйте, gandjustas, Вы писали:
G>Странная логика, любая архитектура — набор ограничений. Заранее ты не знаешь какие цели будут поставлены. То есть в принципе любая архитектура кривая.
Ты вообще не понимаешь, похоже, что тебе пишут. Проблема не в том что архитектура кривая, а в том что изначальные цели и требования были сформулированы неверно. А кривая архитектура — лишь следствие.
Ты внимательно почитай что авторы пишут: "there are many seldom used features and capabilities in the code base". Умные люди еще с ранних бета-версий EF говорили именно об этом (посмотри на LINQ часть BLT или linq2db, там почему то этих мегафич нет). Но понадобилось куча времени и релизов, чтобы до разработчиков EF наконец дошло.
Здравствуйте, gandjustas, Вы писали:
IT>>EF — это всё же отдельно от всего лежащий кусок кала. G>Года два назад отдали в ASP.NET
Т.е. его пилят уже не те индусы, которые завалили WinFS?
IT>>Ваня правильнос сказал, что практикующим девелоперам ещё лет 10 назад стало понятно каким должно быть средство работы с БД. Но команда EF шла на пролом своим путём. G>Если всем понятно, то почему никто не сделал?
Во-первых, написание полноценного Linq-провайдера — это не тривиальная задача типа unit testing framework. Лет пять назад в MS эту задачу оценивали в пару лямов. Во-вторых, большинство попыток следуют текущей конъюнктуре и в конце концов сваливаются к созданию heavy-ORM. В-третьих, сделали. linq2db не страдает ORM-ностью и представляет собой скорее типизированный SQL.
IT>>Новый компилятор позволяет переписать устаревший код и сделать его лучше. Но новый компилятор не поможет сделать лучше новую архитектуру. G>Да ладно? Например с помощью compiler as service можно сделать compile time генерация маппинга DataReader на объекты как минимум или запросто компилировать в реальный IL edmx-модель, убрав весь оверхед, или делать compile-time проверяемые текстовые запросы с декомпозицией (как мечтает Поляков).
Убрать весь оверхед не получится. То, о чём ты говоришь — это лишь несколько процентов сценариев использования. Но даже маппинг одного и того же объекта может отличаться. Например:
from t in Table select t;
from t in Table select new { t.Filed1.Length, t };
Во втором случае индексы для маппинга t съедут на 1 и придётся наворачивать весь оверхед обратно. К тому же это всё не является серьёзной проблемой. linq2db строит expression tree для каждого запроса со всеми необходимыми маппингами без всякого оверхеда в run-time, потом компилирует его и кеширует. Эффективность такого решения примерно как у параноидального ручного маппинга с индексами вместо имён полей.
IT>>После прочтения их пресс-релиза у меня уже возникают какие-то смутные сомнения. Особенно по поводу "EF7 is Lightweight and Extensible". G>Ты тоже оцениваешь технологии по пресс-релизам? Лучше посмотри исходники на гитхабе.
Меня очень сильно напрягает слово "extensible". Это плохое слово, если его использовать в самом общем смысле без конкретных пояснений. Обычно решения, в которые пытаются запихнуть расширяемость везде где только можно заканчиваются тем, что приложение всё что может — так это только расширяться и ничего более из полезного.
G>Возвращаясь к теме EF — начиная с версии 5 активно внедряется такой же сервисный подход. Тоже есть встроенный IoC, тоже куча подменяемых сервисов и соглашения (положительное влияние asp.net). Но под капотом там еще остался старый EF, построенный на принципах ООП, который и хотят в версии 7 выкорчевать из EF.
Честно говоря, мне не очень понятно, что там нужно такого расширяемого в linq-провайдере
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Мне искренне жаль тех, кто слепо верит в то, что, закрывая SQL linq-ом получается якобы улучшение:
Тебе знаком такой термин — рефакторинг базы данных? Нет? И понятно почему. Рефакторинг БД становится доступен только после использования решений основанных на подобных linq технологиях, т.к. они предоставляют 100%-ный контроль над кодом, работающим с БД.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Честно говоря, мне не очень понятно, что там нужно такого расширяемого в linq-провайдере
Things that are specific to particular types of data stores will be available as extensions that are included as part of the provider. For example, the concept of a model builder that allows you to configure your model will be part of the core framework. However, the ability to configure things such as cascade delete on a foreign key constraint will be included as extensions in the relational database provider.
...
You’ll see the same DbContext/DbSet based API but it will be built over building block components that are easy to replace or extend as needed – the same pattern we’ve used for some of the isolated components we’ve added in recent EF releases.
Здравствуйте, IT, Вы писали:
IT>А в чём тут проблема?
Проблема тут, имхо, в том что психологически человеку некомфортно от того что он не пишет sql руками. А все остальное это попытка обосновать попытку всенепременнейше писать его руками, не смотря на то что это приводит к куче проблем.
IT>Тебе знаком такой термин — рефакторинг базы данных? Нет?
Рефакторинг БД приходилось делать.
IT>... предоставляют 100%-ный контроль над кодом, работающим с БД.
Именно для этих целей и были сделаны методы CheckAllQueries и FindUsages(tableName, columnName=null). CheckAllQueries автоматически генерирует тесты для всех вариантов всех запросов (запуская их в режиме SchemaOnly). Подобные тесты раньше писались вручную для DAL-а. Мне удалось автоматизировать рутинную работу по написанию тестов на DAL.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>CheckAllQueries автоматически генерирует тесты для всех вариантов всех запросов
Тесты это хорошо, но руками править кучу текстовых запросов вместо решарпера при простейшем переименовании поля или таблицы — это надо быть очень убежденным в своей правоте.
Здравствуйте, vdimas, Вы писали:
V>Я вижу, ты страшно далек от понимания того, как подобные задачи решали и решают без LINQ. Обычно в тиме работает человек, специализирующийся на базах и запросах,
Т.е. начинаю я работать над какой-нибудь формой и мне нужно заполнить её данными, пока двумя полями. Я зову Васю-Специалиста-На-Базах-И-Запросах и он пишет мне в моём коде SQL, который читает эти два поля для меня из базы. Через 10 минут мне надо подчитать третье поле, я опять зову Васю-Специалиста-На-Базах-И-Запросах и он мне дописывает SQL по требованию. Потом мне нужно будет добавить четвёртое поле, сделать группировку, чего-нибудь отфильтровать и каждый раз мне нужно будет звать Васю-Специалиста-На-Базах-И-Запросах. Тебе самому не смешно?
V>он умеет SQL намного лучше, чем ты свой C# когда-либо умел или сумеешь.
Хорошее знание SQL — это обязательный скил для разработчика среднего уровня.
V>Ну и понимание происходящего в базе на порядки лучше твоего. Так бывает, когда человек многие годы на чём-то специализируется. )) Поэтому, твоя наивность опять зашкаливает. Если чего-то не знаешь — лучше спросить, ИМХО.
Глубокая специализация имеет две стороны. Положительную — хорошее знание в специализирующейся области. Отрицательную — костность мышления и неприятие любых других технологий.
Худшие архитектурные решение, которые мне доводилось видеть в своей жизни были сделаны людьми, специализирующимися на базах и запросах. Т.к. кроме этого они толком ничего не умееют и не хотят уметь. База данных, это важная, но всё же часть любого приложения, а для них она почему-то всегда не просто часть, а единственная часть приложения. В результате всё остальное приносится в жертву и получается очередное гипертрофированное в сторону БД уродство.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, gandjustas, Вы писали:
G>2) Люди пишут Linq запросы не понимая что происходит в базе. Особенно часто встречается FirstOrDefault, который в SQL работает очень медленно, или банально вызывают функции в предикатах.
Что за проблема с FirstOrDefault?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Alexander Polyakov, Вы писали:
IT>>Тебе знаком такой термин — рефакторинг базы данных? Нет? AP>Рефакторинг БД приходилось делать.
И как ощущения? Для меня сегодня рефакторинг БД ничем не отличается от обычного рефакторинга кода. Т.е. вообще ничем. Когда же я писал SQL руками, то это был невероятный геморой.
IT>>... предоставляют 100%-ный контроль над кодом, работающим с БД. AP>Именно для этих целей и были сделаны методы CheckAllQueries и FindUsages(tableName, columnName=null). CheckAllQueries автоматически генерирует тесты для всех вариантов всех запросов (запуская их в режиме SchemaOnly). Подобные тесты раньше писались вручную для DAL-а. Мне удалось автоматизировать рутинную работу по написанию тестов на DAL.
Это ты всего лишь автоматизировал поиск костылей. Linq устраняет сами костыли. Если они у тебя где-то остались, то ты просто не сможешь скомпилировать приложение.
Если нам не помогут, то мы тоже никого не пощадим.
AP>>CheckAllQueries автоматически генерирует тесты для всех вариантов всех запросов НС>Тесты это хорошо, но руками править кучу текстовых запросов вместо решарпера при простейшем переименовании поля или таблицы — это надо быть очень убежденным в своей правоте.
Не забываем, что еще есть FindUsages. FindUsages выдаст список [File, Line]. [File, Line] указывает на начало метода с запросом, а там Ctrl-F. А CheckAllQueries это всё проконтролирует. Поэтому не так всё страшно. Используя Roslyn, можно точно позиционироваться на колонку/таблицу (пока не реализовано).
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
G>>2) Люди пишут Linq запросы не понимая что происходит в базе. Особенно часто встречается FirstOrDefault, который в SQL работает очень медленно, или банально вызывают функции в предикатах.
IT>Что за проблема с FirstOrDefault?
Потому что внутри запроса он преобразуется в select top 1 from (select rownumber() over (...) from t) при некоторых условиях (группировка и еще что-то).
AP>>Если не сложно опиши, как в таком режиме работать с EF? IT>А в чём тут проблема?
Проблем нет. Просто хотел уточнить свое понимание. Тексты классов являются перегенерируемыми, т.е. около полей ничего не пишем руками? (иначе всё снесется) В одном из туториалов видел как вручную навешивались ASP MVC атрибуты, значит, это был неправильный туториал.
IT>И как ощущения? Для меня сегодня рефакторинг БД ничем не отличается от обычного рефакторинга кода. Т.е. вообще ничем. Когда же я писал SQL руками, то это был невероятный геморой.
В связи с этим можно у тебя поинтересоваться, на чём у вас UI? Я очень интересуюсь полным пакетом технологий, где статическая типизация везде: на БД уровне, на серверном и на UI. У вас десктоп или web? Если веб, то html формируете на сервере? или на клиента только данные в виде json уходят? Если второе какой-нибудь клиентский фреймворк используете AngularJS, Ember.js и т.д.? TypeScript используете?
Вроде после появления TypeScript моя мечта о полной статической типизации приложения забрезжила на горизонте. Видимо, какой-то Remote Facade должен быть между клиентским TS и серверным C#. Есть уже что-то готовое для этого?
Здравствуйте, gandjustas, Вы писали:
IT>>Что за проблема с FirstOrDefault? G>Потому что внутри запроса он преобразуется в select top 1 from (select rownumber() over (...) from t) при некоторых условиях (группировка и еще что-то).
Это такое EF генерит? Жуть.
Если нам не помогут, то мы тоже никого не пощадим.
IT>И как ощущения? Для меня сегодня рефакторинг БД ничем не отличается от обычного рефакторинга кода. Т.е. вообще ничем. Когда же я писал SQL руками, то это был невероятный геморой.
Рефакторинг же не конечная цель. Конечная цель это постепенно строить и развивать приложение. И рассматривать отвлеченные переименование таблицы/колонки не интересно.
Если доступ к базе не покрыт ни тестами, ни статической типизацией, то, да, вносить изменения очень боязно, поэтому это сильно тормозит развитие, а разработчики начинают серьезно играть в игру угадай будущее. Что несомненно плохо. А вот разница между случаем, когда есть тесты, и случаем, когда есть статическая типизация, эта разница уже не такая существенная. Разработчики без проблем вносят изменения в базу, поскольку есть уверенность, что их ошибки отловятся и они не отдадут поломанное приложение в продакшен.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
IT>>>EF — это всё же отдельно от всего лежащий кусок кала. G>>Года два назад отдали в ASP.NET IT>Т.е. его пилят уже не те индусы, которые завалили WinFS?
В МС результат мало зависит от индусов, они обычно пилят то, что скажут. Результат зависит от менеджеров прогдакт-группы. Сейчас у asp.net похоже самые толковые менеджеры.
IT>>>Ваня правильнос сказал, что практикующим девелоперам ещё лет 10 назад стало понятно каким должно быть средство работы с БД. Но команда EF шла на пролом своим путём. G>>Если всем понятно, то почему никто не сделал?
IT>Во-первых, написание полноценного Linq-провайдера — это не тривиальная задача типа unit testing framework. Лет пять назад в MS эту задачу оценивали в пару лямов.
Слабая отмазка, в Open Source уже немерено этих провайдеров, а IQToolkit появился вместе с .NET 3.5. Если бы новый провайер мог решить реальные проблемы, а не сущетвующие только в голове отдельных личностей, то уже давно бы это сделали.
IT>Во-вторых, большинство попыток следуют текущей конъюнктуре и в конце концов сваливаются к созданию heavy-ORM.
Какой такой конъюнктуре?
IT>В-третьих, сделали. linq2db не страдает ORM-ностью и представляет собой скорее типизированный SQL.
И что? Проблемы решились? Где толпы восторженных пользователей? Гуглг по linq2db находит репы, NuGet пакеты и целое одно сообщение на rsdn давностью больше полугода.
IT>>>Новый компилятор позволяет переписать устаревший код и сделать его лучше. Но новый компилятор не поможет сделать лучше новую архитектуру. G>>Да ладно? Например с помощью compiler as service можно сделать compile time генерация маппинга DataReader на объекты как минимум или запросто компилировать в реальный IL edmx-модель, убрав весь оверхед, или делать compile-time проверяемые текстовые запросы с декомпозицией (как мечтает Поляков).
IT>Убрать весь оверхед не получится. То, о чём ты говоришь — это лишь несколько процентов сценариев использования. Но даже маппинг одного и того же объекта может отличаться. Например:
IT>
IT>from t in Table select t;
IT>from t in Table select new { t.Filed1.Length, t };
IT>
IT>Во втором случае индексы для маппинга t съедут на 1 и придётся наворачивать весь оверхед обратно. К тому же это всё не является серьёзной проблемой. linq2db строит expression tree для каждого запроса со всеми необходимыми маппингами без всякого оверхеда в run-time, потом компилирует его и кеширует. Эффективность такого решения примерно как у параноидального ручного маппинга с индексами вместо имён полей.
Верю. И что? Для меня вообще скорость маппинга не была никогда проблемой. При тех нагрузках, где скорость мапинга хоть что-то решает я использую кеширование и на скорость мапинга становится пофиг. Это IB беспокоит скорость мепинга, а по моим замерам ef тратит на мепинг одного объекта на 0,2 мкс (две десятых миросекунды, 2*10^-7 секунд) больше, чем при ручном мепинге (проверял на резалтсете из 5000к элементов). Кстати это составляет примено тысячную часть часть от времени запроса, без чтения с диска.
Я вот даже не могу представить причину по которой меня (или кого либо) должны такие "тормоза" беспокоить.
G>>Возвращаясь к теме EF — начиная с версии 5 активно внедряется такой же сервисный подход. Тоже есть встроенный IoC, тоже куча подменяемых сервисов и соглашения (положительное влияние asp.net). Но под капотом там еще остался старый EF, построенный на принципах ООП, который и хотят в версии 7 выкорчевать из EF. IT>Честно говоря, мне не очень понятно, что там нужно такого расширяемого в linq-провайдере
Скорее всего в самом Linq провайдере и не будет особой расширяемости по сравнению с предыдущей версией.
Кстати для замеров добавил linq2db в тестовый проект, оказалось что TT генератор хреново работает с базами, у которых точки в имени, а также напрягло что завязано на .config файл. В KRuntime хотят отказаться от идеи обязательного конфига, да и сейчас много сред, где конфиг недоступен.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
G>>Странная логика, любая архитектура — набор ограничений. Заранее ты не знаешь какие цели будут поставлены. То есть в принципе любая архитектура кривая.
НС>Ты вообще не понимаешь, похоже, что тебе пишут. Проблема не в том что архитектура кривая, а в том что изначальные цели и требования были сформулированы неверно. А кривая архитектура — лишь следствие. НС>Ты внимательно почитай что авторы пишут: "there are many seldom used features and capabilities in the code base". Умные люди еще с ранних бета-версий EF говорили именно об этом (посмотри на LINQ часть BLT или linq2db, там почему то этих мегафич нет). Но понадобилось куча времени и релизов, чтобы до разработчиков EF наконец дошло.
По прядку.
1) "Дошло" до команды EF только тогда, когда понадобилось портировать EF на WinRT (читай "телефоны"). Когда создавался EF никто и представить не мог, что вообще будет WinRT. По большому счету сейчас ни один ORM в телефоне не заработает, так же как EF. Будем считать что у всех архитектура кривая.
2) Куча редкоиспользуемых фич никого не беспокоит (кроме тех, кто активно цитирует пресс-релиз в этой теме).
3) Мега-тормоза, о которых также любят писать некоторые люди в этой теме, тоже мало кто видел. Лично я сталкивался с тормозами EF и решал эту проблему парой строк кода, в текущей версии все эти решения автоматизированы.
Я прекрасно понимаю что тут пишут, и прекрасно понимаю, что это совершенно не проблемы для подавляющего большинства программистов.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
IT>>>Что за проблема с FirstOrDefault? G>>Потому что внутри запроса он преобразуется в select top 1 from (select rownumber() over (...) from t) при некоторых условиях (группировка и еще что-то).
IT>Это такое EF генерит? Жуть.
Помоему это было в Linq2SQL, не помню уже. Там был кейс, что такой SQL, единственный, который давал результат, аналогичный результату на списке объектов. Причем, по странному стечению обстоятельств, таких запросов в коде было дофига.
НС>Тесты это хорошо, но руками править кучу текстовых запросов вместо решарпера при простейшем переименовании поля или таблицы — это надо быть очень убежденным в своей правоте.
Всякие Фаулеры, проповедующие аджайл, на тесты и уповают, у них и языки часто динамические.
Забавно
Здравствуйте, Alexander Polyakov, Вы писали:
AP>>>Если не сложно опиши, как в таком режиме работать с EF? IT>>А в чём тут проблема? AP>Проблем нет. Просто хотел уточнить свое понимание. Тексты классов являются перегенерируемыми, т.е. около полей ничего не пишем руками? (иначе всё снесется) В одном из туториалов видел как вручную навешивались ASP MVC атрибуты, значит, это был неправильный туториал.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>В связи с этим можно у тебя поинтересоваться, на чём у вас UI?
Традиционно WPF и ASP.NET MVC. Т.е. тут даже думать не надо. MVVM и MVC требуют для себя отдельной модели, которая с DataModel пересекаться может, но редко и не долго, ровно до тех пор пока не начнётся усложнение UI. Т.е. для себя я давно решил, что модель данных приложения ака DataModel, необходима исключительно для того, чтобы работать с БД. Кстати, BLT и linq2db поддерживает параноидальный режим описания метаданных БД в виде интерфейсов, а не классов, что вообще искючает создание экземпляров объектов модели данных. Т.е. модель данных используется исключительно для запросов к БД. В целом это работает неплохо, учитывая, что большая часть запросов в реальном приложении представляют собой ad-hoc запросы и требуют перекладывания данных из БД в модель MVVM или MVC.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Alexander Polyakov, Вы писали:
AP> Если доступ к базе не покрыт ни тестами, ни статической типизацией, то, да, вносить изменения очень боязно, поэтому это сильно тормозит развитие, а разработчики начинают серьезно играть в игру угадай будущее.
Юнит тесты — это прежде всего дорого и долго. К тому же наличие статической типизации делает большинство юнит тесов, которые делалются как раз из-за её отсутствия, бессмысленными. Т.е. и здесь linq серьёзно способен удешевить разработку.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, gandjustas, Вы писали:
G>В МС результат мало зависит от индусов, они обычно пилят то, что скажут. Результат зависит от менеджеров прогдакт-группы. Сейчас у asp.net похоже самые толковые менеджеры.
Ну будем надеяться.
IT>>Во-первых, написание полноценного Linq-провайдера — это не тривиальная задача типа unit testing framework. Лет пять назад в MS эту задачу оценивали в пару лямов. G>Слабая отмазка, в Open Source уже немерено этих провайдеров, а IQToolkit появился вместе с .NET 3.5. Если бы новый провайер мог решить реальные проблемы, а не сущетвующие только в голове отдельных личностей, то уже давно бы это сделали.
Отмазка вполне серьёзная. Тот же IQToolkit более как на роль примера linq-провайдера больше ни на что не тянет. Реально его пытался использовать только автор Subsonic, который в результате на OrmMetter не был допущен к забегу в категории linq из-за фейла почти всех linq-тестов.
В общем, если бы я точно знал куда я лезу, когда начинал заниматься linq-провайдером в BLT, то точно бы не стал этого делать и сейчас, скорее всего восхвалял EF вместе с тобой и точно так же спорил бы с IB
IT>>Во-вторых, большинство попыток следуют текущей конъюнктуре и в конце концов сваливаются к созданию heavy-ORM. G>Какой такой конъюнктуре?
Все хотят построить не просто маппер, а охренительный умный всемогутер, который сам знает что нужно разработчику ещё до того как разработчик об этом подумал. Тот же Unit Of Work, на самом деле, вполне имеет право на жизнь в некоторых случаях. Но проблема в том, что конъюнктурщики начинают именно с него, а всё остальное в результате идёт по-боку, потому что на это элементарно не хватает ресурсов. Мне, кстати, тоже сильно не хватает ресурсов, в частности на тот же Unit Of Work, но зато мне их хватило на генерацию вменяемого SQL для FirstOrDefault, для поддержки более десятка БД, для генерации human friendly SQL, который не нужно переформатировать, чтобы на него посмотреть и прочих вещей, нужных не для демонстраций, а для каждодневной работы.
IT>>В-третьих, сделали. linq2db не страдает ORM-ностью и представляет собой скорее типизированный SQL. G>И что? Проблемы решились? Где толпы восторженных пользователей? Гуглг по linq2db находит репы,
Я программист, а не пиарщик. Видимо в этом проблема. К тому же см. выше про ресурсы. Кто-то их тратит на написание кода, а кто-то на толпы восторженных пользователей.
G>NuGet пакеты и
Вообще-то есть целый форум про это дело. К тому же linq2db это как раз переработка BLT в части linq и всё, что касается BLT можно отнести к linq2db.
G>Верю. И что? Для меня вообще скорость маппинга не была никогда проблемой.
Тогда зачем ты это приводил в качестве аргумента? На самом деле метапрограммирование в этом деле вовсе не бесполезно. Например, модель данных запросто можно генерировать в момент компиляции, а не с помощью T4.
G>Кстати для замеров добавил linq2db в тестовый проект, оказалось что TT генератор хреново работает с базами, у которых точки в имени,
Давай пофиксим вместо. Давай пример неработающего кода, будем фиксить.
G>а также напрягло что завязано на .config файл. В KRuntime хотят отказаться от идеи обязательного конфига, да и сейчас много сред, где конфиг недоступен.
Всё можно сконфигурировать и без конфигов. Последние пять лет у меня это вообще была единственная доступная опция.
Если нам не помогут, то мы тоже никого не пощадим.
Резултат тот же. Может у тебя не самая свежая версия. Я довно nuget не обновлял. Может в этом проблема.
AP>P.S. По хорошему, Parent свойство должно быть Option<Parent>.
Да это как бы тоже не проблема. Можно покумекать над расширением маппинга для твоего собственного Option<T>.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, gandjustas, Вы писали:
G>Помоему это было в Linq2SQL, не помню уже. Там был кейс, что такой SQL, единственный, который давал результат, аналогичный результату на списке объектов. Причем, по странному стечению обстоятельств, таких запросов в коде было дофига.
Ну незнаю, обычного TOP 1 хватает за глаза. Для Single(OrDefault) TOP 2. Но даже это всё не обязательно.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Не забываем, что еще есть FindUsages. FindUsages выдаст список [File, Line]. [File, Line] указывает на начало метода с запросом, а там Ctrl-F.
И так 50 раз. И это вместо того чтобы просто один раз нажать хоткей и ввести новое имя.
Здравствуйте, IT, Вы писали:
IT> Т.е. начинаю я работать над какой-нибудь формой и мне нужно заполнить её данными, пока двумя полями. Я зову Васю-Специалиста-На-Базах-И-Запросах и он пишет мне в моём коде SQL, который читает эти два поля для меня из базы. Через 10 минут мне надо подчитать третье поле, я опять зову Васю-Специалиста-На-Базах-И-Запросах и он мне дописывает SQL по требованию. Потом мне нужно будет добавить четвёртое поле, сделать группировку, чего-нибудь отфильтровать и каждый раз мне нужно будет звать Васю-Специалиста-На-Базах-И-Запросах. Тебе самому не смешно?
Еще смешнее становится когда грид-контрол умеет сортировки, фильтрацию и группировки.
Здравствуйте, IT, Вы писали:
IT>>>Во-первых, написание полноценного Linq-провайдера — это не тривиальная задача типа unit testing framework. Лет пять назад в MS эту задачу оценивали в пару лямов. G>>Слабая отмазка, в Open Source уже немерено этих провайдеров, а IQToolkit появился вместе с .NET 3.5. Если бы новый провайер мог решить реальные проблемы, а не сущетвующие только в голове отдельных личностей, то уже давно бы это сделали.
IT>Отмазка вполне серьёзная. Тот же IQToolkit более как на роль примера linq-провайдера больше ни на что не тянет. Реально его пытался использовать только автор Subsonic, который в результате на OrmMetter не был допущен к забегу в категории linq из-за фейла почти всех linq-тестов. IT>В общем, если бы я точно знал куда я лезу, когда начинал заниматься linq-провайдером в BLT, то точно бы не стал этого делать и сейчас, скорее всего восхвалял EF вместе с тобой и точно так же спорил бы с IB
А почему? Решение проблем не стоит затраченных усилий? Тогда за что EF ругают?
IT>>>В-третьих, сделали. linq2db не страдает ORM-ностью и представляет собой скорее типизированный SQL. G>>И что? Проблемы решились? Где толпы восторженных пользователей? Гуглг по linq2db находит репы, IT>Я программист, а не пиарщик. Видимо в этом проблема. К тому же см. выше про ресурсы. Кто-то их тратит на написание кода, а кто-то на толпы восторженных пользователей.
Без реального фидбека хороший продукт не получится. А фидбек получить без контента не получится.
G>>целое одно сообщение на rsdn давностью больше полугода. IT>Вообще-то есть целый форум про это дело. К тому же linq2db это как раз переработка BLT в части linq и всё, что касается BLT можно отнести к linq2db.
Я не про форум, а про гугл. Главное правило интернета — если тебя не находит гугл, значит тебя не существует.
G>>Верю. И что? Для меня вообще скорость маппинга не была никогда проблемой. IT>Тогда зачем ты это приводил в качестве аргумента? На самом деле метапрограммирование в этом деле вовсе не бесполезно. Например, модель данных запросто можно генерировать в момент компиляции, а не с помощью T4.
Потому что для многих в этой теме это проблема (по неясным для меня причинам).
G>>Кстати для замеров добавил linq2db в тестовый проект, оказалось что TT генератор хреново работает с базами, у которых точки в имени, IT>Давай пофиксим вместо. Давай пример неработающего кода, будем фиксить.
Генерит имя класса DataBaseName.WithDot, что вызывает ошибку компиляции.
Скорее всего с именами полей та же проблема будет.
G>>а также напрягло что завязано на .config файл. В KRuntime хотят отказаться от идеи обязательного конфига, да и сейчас много сред, где конфиг недоступен.
IT>Всё можно сконфигурировать и без конфигов. Последние пять лет у меня это вообще была единственная доступная опция.
Нельзя передать в конструктор контекста строку подключения
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
G>>1) "Дошло" до команды EF только тогда, когда понадобилось портировать EF на WinRT НС>Докажи что именно это послужило причиной. Пока что твои заявления голословны.
В том же пресс-релизе написано в самом начале:
Entity Framework is a popular data access choice for traditional client and server applications that target the full .NET Framework. This includes applications built with technologies such as WPF, WinForms and ASP.NET. As we look to the future, we believe there is value in providing the same programming model for data access on the remaining platforms where .NET development is common. This includes Windows Store, Windows Phone and the Cloud Optimized .NET that was announced at TechEd. EF7 will work on all of these platforms as well as Mono, on both Mac and Linux.
G>>2) Куча редкоиспользуемых фич никого не беспокоит НС>Авторов, вишь, таки беспокоит.
А я не про авторов, а про пользователей. Авторов оно беспокоит ровно по причине поддержки и портирования.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Докажи что именно это послужило причиной. Пока что твои заявления голословны.
Бесполезно. Он давно подсел на EF, а теперь просто обидно за зря потраченные годы... =) По человечески понятно, но это путь в никуда. Если уж разработчики сами явно пишут, что фигня получилась, а он рассказывает, что они имели ввиду что-то другое, то тут логика бессильна...
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
G>>Далее смотрим в wiki: https://github.com/aspnet/EntityFramework/wiki/Getting-and-Building-the-Code G>>Выясняется что EF разрабатывается под K Runtime. который использует .NET Core Runtime (общий знаменатель для всех версий .NET)
НС>Одновременно не означает в следствие.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>Докажи что именно это послужило причиной. Пока что твои заявления голословны. IB>Бесполезно. Он давно подсел на EF, а теперь просто обидно за зря потраченные годы... =) По человечески понятно, но это путь в никуда. Если уж разработчики сами явно пишут, что фигня получилась, а он рассказывает, что они имели ввиду что-то другое, то тут логика бессильна...
Вообще-то в том же пресс-релизе написано, который ты цитируешь. Я так понял что ты даже пресс-релизы невнимательно читаешь.
Насчет "путь в никуда" — очень даже ясно куда — EF7. Читаем пресс-релиз дальше:
Upgrade from EF6 to EF7 is a key scenario for us, both in terms of existing code and existing knowledge. We’ll be keeping the same concepts and patterns wherever it makes sense. The upgrade to EF7 will require some changes to your code. Our aim is that code that uses the core functionality of the DbContext API will upgrade easily, code that makes use of the lower level APIs in EF may require more complicated changes.
Но я понимаю что все факты расходятся с твоей верой, поэтому ты ищешь проблемы в других.
Здравствуйте, gandjustas, Вы писали:
V>>>>Такой ты наивный... А как же раньше подобные задачи решались? ))) G>>>Также как и сейчас «решают», делают малое количество запросов\процедур, покрывающих сценарии.
V>>"Мало" это сколько? Вот предположи, сколько суммарно на стороне базы сохраненных запросов и хранимок в средненькой системе, когда базу разрабатывают именно как базу, а не как "тупое хранилище объектов", где все запросы идут на LINQ? Почитав твои ответы ниже, я уверен, что ответ тебя удивит. G>Я мигрировал небольшой проект на Linq, было 3-5 хранимок на таблицу для выборок, для таблиц с кучей колонок было побольше. После переписывания на Linq стало около 20 запросов на таблицу. Точной статистики, увы, не осталось.
Ну это что-то совсем простое. В тех проектах, где я участвовал и был выделенный программист БД, кол-во хранимок+сохраненных запросов было порядка 2к на примерно полторы-две сотни таблиц. И еще несколько десятков запросов составлялись динамически. Но эти "запросы" мы считали не по кол-ву результирующих сочетаний (а оно большое, ес-но, из-за комбинаторики условий), а по кол-ву таких параметризуемых "построителей". Т.е. динамических сценариев было довольно немного в общей куче.
G>>>Запросы не эффективны, тормозят, пинают их хинтами, чтобы работало приемлемо. V>>Это LINQ генерит жутко неэффективные запросы. G>Люди генерят неэффективные запросы, а Linq может косячить только в очень сложных случаях, которые вообще бессмысленно на Linq писать.
Linq использует далеко не все ср-ва языка. И речь не только о хинтах. Сам запрос в Linq формируется тупым переводом структуры исходного выражения. Поэтому, не спорь, Linq генерит заведомо плохой SQL "в лоб".
G>Вот мой личный хит-парад причин неэффективных запросов: G>1) Отсутствие проекций. Люди не пишут select, это приводит к тому что тянется слишком много данных (особенно проблема для длинных строк и блобов) и не получается построить покрывающий индекс.
Куда тянется? Если это внутренний подзапрос, то ничего никуда не тянется.
Лишние поля на клиента мы не гоняли, ес-но, т.е. select самого верхнего уровня тщательный, ес-но. Мне даже трудно вообразить, где-то может быть не так и ты даже привел ЭТО как аргумент. ))
G>2) Люди пишут Linq запросы не понимая что происходит в базе. Особенно часто встречается FirstOrDefault, который в SQL работает очень медленно, или банально вызывают функции в предикатах.
Ну, если, действительно нужен First, то быстрее ты не сделаешь. А OrDefault можно и на клиентской стороне обыграть, но это не может существенно повлиять на результат. Что-то ты не то говоришь, кароч. Я тебе говорил о самом SQL. Кароч, оч большая разница с тем, какой SQL пишет специально-обученный и уже 20 лет этим занимающийся человек и SQL после Linq "обычного программиста". Это небо и земля.
Опять же. Есть такой фактор — владение проблемой. Когда программист SQL пишет запросы, он "видит" происходящую картинку. Именно так. Нет эдакого "разрыва" кода и базы. Просто индексы, статистику, материализцию view и прочее — такие решения принимает человек, который в этом "варится". А программист C# в этом не варится нифига, что бы кто не говорил.
G>3) Люди пытаются на Linq написать то, что в базе уже есть, но нет в Linq. Видел такие рукопашные реализации FTS и оператора Merge.
V>>А хинты нужны малость для другого, тут исходный способ генерирования запроса не при чем от слова вообще. Но они, действительно, часто нужны. G>Я не знаю для чего по твоему нужны хинты, я видел как их применяют при использовании хранимок для Data Access.
Хинтами можно указать уровень блокировок. При частом обновлении это даёт прирост до нескольких раз, в особо клинических случаях — до порядка.
Ну и "длинные транзакции" всё-равно на стороне базы исполняются на многие порядки быстрее (с тащтельно подобранными уровнями блокировки), чем последовательность вызовов Linq с клиента базы в рамках одной транзакции. От этого ты вообще никак не убежишь.
Триггера те же и т.д.
Понимаешь, все эти триггера, длинные транзакции и прочее используют какую-то кодовую базу SQL, которая УЖЕ есть на стороне базы. Смысл её дублировать в Linq?
В этом смысле Linq можно рассматривать примерно как и весь дотнет — как неплохой тул для макетирования. А "взрослая" разработка все-равно перепишет львиную долю макета в "боевой" вид.
V>>Только не понятно, как ими пользоваться из LINQ? )) G>Это показывает твой уровень знания SQL
Ты не показал, как этим пользоваться из Linq.
G>plan guide вообще-то есть.
Есть мильон служебных хелперов, и? Эти хелперы связаны с состоянием базы. Ты чуть подмандил свой запрос, и твой вызванный ранее plan guide стал бесполезен. Или ты каждый раз перед целевым запросом будешь настраивать plan guide?
Кароч, этот костыль не для этого сценария.
V>>>>Точно так же генерили SQL аж бегом. G>>>Это только примитивные запросы, максимум джоины и простые предикаты, никаких группировок и подзапросов.
V>>Я вижу, ты страшно далек от понимания того, как подобные задачи решали и решают без LINQ. Обычно в тиме работает человек, специализирующийся на базах и запросах, он умеет SQL намного лучше, чем ты свой C# когда-либо умел или сумеешь. Ну и понимание происходящего в базе на порядки лучше твоего. Так бывает, когда человек многие годы на чём-то специализируется. )) Поэтому, твоя наивность опять зашкаливает. Если чего-то не знаешь — лучше спросить, ИМХО. G>Я вообще-то занимаюсь обучением таких DBA и прекрасно осведомлен об их способностях. G>Если есть отдельный DBA, который не лезет в код, и программисты, которые не лезут в базу, то получается impendance mismatch между людьми. G>Если DBA "главнее" программистов, то он рисует базу, небольшой набор хранимок (большой поддерживать влом), запинывает их хинтами и грозится оторвать руки тем, кто фигачит Adhoc запросы в базу. При этом хранимок мало, они не отражают реальные потребности приложения и отдают зачастую слишком много данных, а программисты на стороне приложения сами разбираются.
Скорее, это результат ТВОЕГО обучения. )) А есть среди них те, кто хотя бы лет 15 именно этим занимается?
Про impendance mismatch я вообще молчу. С грамотным DBA я наблюдал ровно противоположное — у всех всё выспросит, заставить оформить требования, ни байта лишнего из базы не отдаст.
Про количество хранимок и вьюшек я написал выше. Я сразу в твоих аргументах ощутил специфический опыт, когда разработка на стороне базы фактически отсутствовала. ОК! В условиях объективной невозможности вести разработку на стороне базы, Linq тебе в помощь.
Правда, и до Linq был тот же Hibernate/NHibernate со своим построителем запросов. ))
Да и у нас в одном из проектов проекте был свой объектный построитель запросов, где тоже шла комбинация условий, в т.ч. групповые операции и затем сериализация в SQL. Но я прекрасно помню, для каких именно сценариев мы такое делали — для динамики, для вычурной аналитики, вызываемой клиентами из специальных форм и отчетов. А такие сценарии — капля в море в общей "боевой" нагрузке.
G>Если же программисты "главнее" DBA, то программисты юзают базу как тупое хранилище объектов, а DBA только пишет batch processing для самых тормозящих сценариев.
И этот подход прекрасно работает, пока в таблицах сотни тыщ / единицы мильонов строк! )))
Кароч, пока SQL-сервак в состоянии держать все частоисопльзуемые индексы и даже данные в оперативной памяти, всё прекрасно работает хоть на Linq, хоть на коленке. Но для таких сценариев не всегда реляционная база — лучший вариант. Объектные или blob-базы могуть зарулить всё и вся. Когда идет обработка "просто графов объектов" в памяти, то там реляционки сливают на порядок и больше, бо они изначально нужны для медленных внешних хранилищ и ни для чего более.
G>Лет 7-8 назад такое было повсеместно, потом появился Linq и больше C# программистов стало понимать что происходит в базе и как сделать оптимальной работу с СУБД. G>Но тебя это, видимо не коснулось. Не беспокойся, еще не поздно изучить.
Что ИМЕННО надо изучить?
И КАК C#-программист начнет понимать происходящее в базе, особенно, если разные программисты разрабатывают разные абстрактные предикаты, из которых собирается целевой запрос "кем-то еще"? Даже по неизвестной заранее таблице? Как преодолеть ту пропасть между мышлением "типами" у программиста и "доменами" у DBA? )) Я вживую такое не видел и тебе не верю — бо помню тебя по прошлым обсуждениям. Слишком большая косность мышления у фанатов "dotnet only", что даже с прочтением IL-кода были неразрешимые трудности. Мышление в типах — это "плоское" 2D-мышление. Во главе угла — простота. ))) В доменах — объемное, пространственное мышление. Точнее — многомерное. Умение держать в голове слишком много сразу, чтобы уметь принимать адекватные решения. Редкие люди хорошо умеют и то и другое, тут нужна определённая гибкость ума, умение быстро перестраиваться, которое мало кто здесь демонстрирует. А если у кого настолько светлая и гибкая голова, то тратить её на тупую инженерию, типа прикладника на C# или SQL было не иначе как преступлением. Хотя, есть здесь и единицы таких. ))
G>>>Добавляй сразу в классы, ef добавит его в базу.
V>>Не со всеми нужными св-вами. Не со всеми связями, ограничениями, триггерами и т.д. до бесконечности. Как-то ты примитивно рассматриваешь базу, однако. G>Так добавь что нужно, тебя никто не ограничивает.
Добавлю, конечно. Иначе бы не приводил как аргумент того, что от независимого изменения базы ты не убежишь. Этот "автоматизм" вообще малость опасен. Возьмет какой-нить программист удалит поле, синхронизирует, потом обнаружит, что оно было нужно таки, быстро добавит обратно, опять синхронизирует. И тю-тю все прежние настройки. Если диффы по SQL-определениям таблиц не вести, то и не заметишь ничего. А их удобнее вести именно при полноценной разработки базы со стороны базы.
V>>Согласен только насчет последнего, но это извращение, а не аргумент в споре. Динамические, как раз, можно построить "извне" базы и так часто и делают. Но я утверждаю, что таких запросов (динамических по своей структуре, а не по простым параметрам) менее 10% от обслуживаемых средней базой в течении суток, скажем. А то и менее 1%, положа руку на. G>Не пойму что ты сказать хочешь. Количество запросов, генерируемых программой — конечно (без учета параметров), кеш планов SQL Server на этот факт и рассчитан. G>Например у тебя в программе есть Grid, который позволяет фильтровать и сортировать по любой колонке (как excel). Количество разных (без учета параметризации) запросов будет очень большим (порядка 2n*2^n!, где n — кол-во колонок), но конечным. При этом если грид на главной странице приложения, то на эти динамические запросы будет приходится большая часть запросов. Или это по твоему не динамические запросы?
Ох, блин. Ну ты дал!
Нет, не динамические. Подготавливается заранее view, скрывающий всю сложность низлежащего запроса, а уже на результат можно накладывать сортировку и фильтрацию. View делается DBA, конкретный тупой SQL-запрос к этому view пишет программист. Но он же тривиальный, много ума не надо, бо по специально заточенному view идёт тупой "select * from ... where ... order by ...".
G>Что ты имеешь ввиду под динамическими запросами?
С динамической структурой, затрагивающей подзапросы. Т.е. где в условиях идут еще выборки или групповые операции над ними, типа exists, any и т.д. из этой оперы. С перекрестными связями по-условию м/у подуровнями — прикольнее всего. ))
V>>Это обычно только какие-нить специфические отчеты, редко потребляемая аналитика или что-то в этом роде. Я не спорю, что таких запросов может быть абсолютное большинство, если считать запросы не в кол-ве реальных употреблений, а в штуках наличия самих запросов. G>Как раз для отчетов запросы статичны, то есть они один раз задаются и много раз вызываются.
Это список полей статичный, а запрос к базе может быть очень даже динамичным в том смысле, что я написал выше.
Простой пример — список товаров со склада, краткая форма. Вид отчета одинаков для любых выборок, но самих выборок — масса. Простая выборка, для которой цена отпуска товара отличается от средней более чем на 15% (за некий период) уже требует подзапросов. А если товары еще дополнительно делятся по "разносортице" (в стандартной 1С не поддерживается, почему до сих пор полно самописных складских программ со своими прибамбасами), то это будет запрос с 3-мя и более "уровнями", со ссылками на первый уровень из самого низа.
V>>Но это маргинальный, по-сути, сценарий, на который, как раз LINQ прекрасно ложится. Т.е. LINQ хорош в процессе построения нетривиальных, динамических запросов, угу. Но это же development time для 90-99% реальных случаев. Зачем же снова и снова строить одни и те же запросы в рантайм? ))) G>У тебя каша в голове.
А ну да. Я помню про "гибкость". ))
G>Давай по порядку: что ты называешь динамическими запросами?
Ну я заведомо исключил из них те, где меняются простые параметры, бо для ТАКИХ сценариев вообще Linq не облокотился и обсуждать сразу нечего.
Я рассматриваю те сценарии, где Linq еще хоть зачем-то нужен, например, если ты заранее не знаешь, какой будет конечный join.
G>Я грешным делом подумал что называешь динамическими запросы, которые клеятся по кускам, но прочитав твой ответ я понял, что не понял что ты называешь динамическими запросами.
Это запросы с неизвестной заранее структурой и уровнями вложенности. Например, в одной из систем был способ визуального построения иерархического фильтра и простенький DSL к нему, для пользования клиентами.
Так-то у нас "объектный" построитель запросов в похожем синтаксисе (построенный на тогдашнем BLT, кста) был еще в 2004-м, Linq не нужен?)))
V>>Я вижу, ты страшно далек от понимания того, как подобные задачи решали и решают без LINQ. Обычно в тиме работает человек, специализирующийся на базах и запросах, он умеет SQL намного лучше, чем ты свой C# когда-либо умел или сумеешь. НС>Ага, а потом я в таких проектах переписываю хранимки на linq2db и получаю ускорение в 2-3 раза.
За счет чего именно?
Чудес же не бывает, правильно?
Я бы мог ответить "это твой опыт, такой у вас был ДВА и т.д.", но вижу подобный аргумент уже не первый раз. Хочу понять, мож что-то фундаментальное там?
Тем более, что самые "тяжелые" хранимки (по моему субъективному опыту) ни на какой Linq не перенесешь, бо там несколько операций с промежуточными таблицами, обычно, т.е. "длинные транзакции", которые на стороне базы примерно на пару порядков быстрее, чем точно такая же последовательность операций в "длинной транзакции" со стороны клиента.
V>>Зачем же снова и снова строить одни и те же запросы в рантайм? ))) НС>Нормальные linq провайдеры умеют запросы кешировать.
Речь об общей кодовой базе. Повторного использования кода на стороне БД, при разработке именно со стороны БД оч много. Часто одни view строятся на основе других, точно так же sp и табличные ф-ии. Т.е. как в обычном программировании, есть "низкоуровневый" и "высокоуровневый" слой. А это уже кеширование на стороне базы, что совсем другое дело, чем кеширование текста на стороне клиента. (Я не считаю клиентские затраты на генерирование тескта SQL существенными, т.е. речь не об этом).
Здравствуйте, IT, Вы писали:
IT> Т.е. начинаю я работать над какой-нибудь формой и мне нужно заполнить её данными, пока двумя полями. Я зову Васю-Специалиста-На-Базах-И-Запросах и он пишет мне в моём коде SQL, который читает эти два поля для меня из базы. Через 10 минут мне надо подчитать третье поле,
Т.е. ты сам себе ПМ, аналитик, архитектор и тот самый Вася, если тебе через 10 мин (!!!) потребовалось третье поле. ))
Такого рода задачи у нас тоже бывали, но ничего серьезного обычно, т.е. проекты сами несерьезные, обсуждать бессмысленно. Из подобного наколенного творчества делать какие-либо выводы я бы не стал, хотя сам именно в таком режиме много чего понаделал.
IT>я опять зову Васю-Специалиста-На-Базах-И-Запросах и он мне дописывает SQL по требованию. Потом мне нужно будет добавить четвёртое поле, сделать группировку, чего-нибудь отфильтровать и каждый раз мне нужно будет звать Васю-Специалиста-На-Базах-И-Запросах. Тебе самому не смешно?
Нисколько. Я уже не первый год говорю, что дотнет и Linq являются неплохими инструментами для прототипирования. Сейчас даже архитекторы, вместо контруирования форм в "специальных" программах, накидывают их прямо в студии и общаются потом с клиентами.
Дай-ка угадаю, чтобы мы этот твой аргумент (уже не первый раз тобой приведенный за последние годы, кста), "проехали", наконец.
Ты плотно работаешь в команде не более 3-х человек?
Т.е. независимо от кол-ва людей в конторе, плотно по работе у тебя максимум пара коллег контактирует в каждом проекте. Другая организация труда тебе будет просто раздражать, ты работать по-другому не будешь и продуктивно не сможешь при всем желании.
V>>он умеет SQL намного лучше, чем ты свой C# когда-либо умел или сумеешь. IT>Хорошее знание SQL — это обязательный скил для разработчика среднего уровня.
Речь была о специфике конкретной БД. Иначе зачем нам ДБ-разраб, когда дело касалось бы "голого SQL"?
IT>Глубокая специализация имеет две стороны. Положительную — хорошее знание в специализирующейся области. Отрицательную — костность мышления и неприятие любых других технологий.
Ммм... Ты пытаешься лезть в такую область, как информационный метаболизм. А данных для столь громких выводов у тебя недостаточно.
Косность мышления — это почти врожденное кач-во человека (наполовину врожденное, если быть точным — только по координате сенсорик/интуит), от глубины специализации сие никак не зависит. Обычно к косности склонны сенсорики-интроверты (дотошность, конкретное мышление), на другом полюсе находятся интуиты-экстраверты (экспериментаторы и аналитики по-натуре, склонные к абстрактному мышлению). Кароч, речь идет о т.н. "гибкости ума". Гибкость ума ну никак не может мешать глубокой специализации в чем-либо, хотя да, вторая упомянутая группа склонна к поверхностности... но тут дело сугубо специфичное у каждого человка. Мы же говорим о спецах, так? Так вот, ровно наоборот, без достаточной гибкости ума сию глубину-то и не достигнешь, бо на каждом уровне понимания области собственной деятельности часто открываются совсем разные по характеру задачи и ньюансы. Поэтому даже во второй группе технических спецов (именно глубоких спецов своего дела) встречается намного больше, чем в первой. Из первой прут руководители, филологи, историки и т.д., из второй — ученые и артисты. ))
IT>Худшие архитектурные решение, которые мне доводилось видеть в своей жизни были сделаны людьми, специализирующимися на базах и запросах. Т.к. кроме этого они толком ничего не умееют и не хотят уметь. База данных, это важная, но всё же часть любого приложения, а для них она почему-то всегда не просто часть, а единственная часть приложения. В результате всё остальное приносится в жертву и получается очередное гипертрофированное в сторону БД уродство.
А я видел худшие архитектурные решения от "программистов от сохи", и?
Худшие архитектурные решения получаются у людей, чей кредит доверия превышает их профессиональные навыки, а всё остальное — лирика и субъективизм. Я наблюдал, что тот же самый человек, но уже с адекватным кредитом доверия, порождает потом неплохие в итоге решения, потому что из работы выключен банальный личный снобизм. Человек был ВЫНУЖДЕН быть открытым и любопытным. Что дало требуемые плоды. Всё-таки все плохие решения идут обычно от недостатка информации и ни от чего более. (Малый опыт я не рассматриваю, бо бесполезно в этом споре)
Здравствуйте, vdimas, Вы писали:
НС>>Хинты и LINQ, в общем случае, перпендикулярны. V>А в синтаксисе именно LINQ?
Сто такое "синтаксис LINQ"? Если ты про query comprehension, то это не обязательная и даже не основная его часть. Я, к примеру, ей вообще не пользуюсь.
V>Так-то у нас "объектный" построитель запросов в похожем синтаксисе
Похожесть тебе только показалась. Ключевой момент здесь — наличие expression tree, которого в 2004 не было. А QC это так, мелочевка.
НС>>Ага, а потом я в таких проектах переписываю хранимки на linq2db и получаю ускорение в 2-3 раза. V>За счет чего именно?
За счет того что выкидывается куча странного кода внутри хранимок. Особо весело выходит, когда одна хранимка вызывает другую, та третью и т.д.
V>Я бы мог ответить "это твой опыт, такой у вас был ДВА и т.д."
Проблема только в том, что я в куче проектов такое видел. А, судя по общению с коллегами, не только я.
V>Тем более, что самые "тяжелые" хранимки (по моему субъективному опыту) ни на какой Linq не перенесешь, бо там несколько операций с промежуточными таблицами, обычно
Во-во, навертят бреда вокруг промежуточных таблиц на ровном месте с десятком select into, а потом оказывается что все можно переписать без них.
V>>>Зачем же снова и снова строить одни и те же запросы в рантайм? ))) НС>>Нормальные linq провайдеры умеют запросы кешировать. V>Речь об общей кодовой базе. Повторного использования кода на стороне БД, при разработке именно со стороны БД оч много.
Моя практика в рамках нескольких разнородных проектов показывает наоборот, такого кода очень мало. 90% запросов уникальны.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>>>Такой ты наивный... А как же раньше подобные задачи решались? ))) G>>>>Также как и сейчас «решают», делают малое количество запросов\процедур, покрывающих сценарии.
V>>>"Мало" это сколько? Вот предположи, сколько суммарно на стороне базы сохраненных запросов и хранимок в средненькой системе, когда базу разрабатывают именно как базу, а не как "тупое хранилище объектов", где все запросы идут на LINQ? Почитав твои ответы ниже, я уверен, что ответ тебя удивит. G>>Я мигрировал небольшой проект на Linq, было 3-5 хранимок на таблицу для выборок, для таблиц с кучей колонок было побольше. После переписывания на Linq стало около 20 запросов на таблицу. Точной статистики, увы, не осталось.
V>Ну это что-то совсем простое. В тех проектах, где я участвовал и был выделенный программист БД, кол-во хранимок+сохраненных запросов было порядка 2к на примерно полторы-две сотни таблиц. И еще несколько десятков запросов составлялись динамически. Но эти "запросы" мы считали не по кол-ву результирующих сочетаний (а оно большое, ес-но, из-за комбинаторики условий), а по кол-ву таких параметризуемых "построителей". Т.е. динамических сценариев было довольно немного в общей куче.
Я тоже видел такие проекты, но там по факту половина хранимок не использовалось, добавление поля это была задача примерно на месяц. Проект очень быстро загнулся.
Даже банальная математика говорит что при 2к хранимок и 200 таблиц это минимум 10 хранимок на таблицу, а скорее всего в два раза больше. Любая правка в исходной таблице — нужна синхронная правка около 20 хранимок. Команда из 3-4 программистов будет поля править раз в день, DBA от такого сдохнет.
При этом Linq позволяет генерировать больше и более специализированные запросы, чем выделенный DBA.
G>>>>Запросы не эффективны, тормозят, пинают их хинтами, чтобы работало приемлемо. V>>>Это LINQ генерит жутко неэффективные запросы. G>>Люди генерят неэффективные запросы, а Linq может косячить только в очень сложных случаях, которые вообще бессмысленно на Linq писать. V>Linq использует далеко не все ср-ва языка. И речь не только о хинтах. Сам запрос в Linq формируется тупым переводом структуры исходного выражения. Поэтому, не спорь, Linq генерит заведомо плохой SQL "в лоб".
Уж прости, но аргументация на уровне детского сада.
Linq умеет генерить:
1) все виды джоинов
2) подзапросы
3) группировки
4) предикаты
Этого хватает чтобы покрыть 99% запросов.
Linq не умеет (зависит от провайдера):
1) CTE
2) merge operator
3) ranking-функции
Сколько запросов у тебя содержат эти функции?
Что ты считаешь "плохим" SQL и почему Linq его генерит сам?
G>>Вот мой личный хит-парад причин неэффективных запросов: G>>1) Отсутствие проекций. Люди не пишут select, это приводит к тому что тянется слишком много данных (особенно проблема для длинных строк и блобов) и не получается построить покрывающий индекс.
V>Куда тянется? Если это внутренний подзапрос, то ничего никуда не тянется.
С чего ты взял? От проекции в запросе (неважно подзапрос это или нет) зависит какой план построит SQL, а это напрямую влияет на быстродействие. Конечно кроме случаев, когда ты используешь подзапрос в exists выражении.
V>Лишние поля на клиента мы не гоняли, ес-но, т.е. select самого верхнего уровня тщательный, ес-но. Мне даже трудно вообразить, где-то может быть не так и ты даже привел ЭТО как аргумент. ))
Знал бы ты сколько я таких запросов починил... Не хватит пальцев рук у всех родственников до третьего колена.
G>>2) Люди пишут Linq запросы не понимая что происходит в базе. Особенно часто встречается FirstOrDefault, который в SQL работает очень медленно, или банально вызывают функции в предикатах.
V>Ну, если, действительно нужен First, то быстрее ты не сделаешь. А OrDefault можно и на клиентской стороне обыграть, но это не может существенно повлиять на результат. Что-то ты не то говоришь, кароч. Я тебе говорил о самом SQL. Кароч, оч большая разница с тем, какой SQL пишет специально-обученный и уже 20 лет этим занимающийся человек и SQL после Linq "обычного программиста". Это небо и земля.
Разница конечно есть, но не всегда в положительную сторону. Человек может ошибаться или банально не знать о конкретных потребностях приложения, поэтому делать неоптимальные запросы.
V>Опять же. Есть такой фактор — владение проблемой. Когда программист SQL пишет запросы, он "видит" происходящую картинку. Именно так. Нет эдакого "разрыва" кода и базы. Просто индексы, статистику, материализцию view и прочее — такие решения принимает человек, который в этом "варится". А программист C# в этом не варится нифига, что бы кто не говорил.
Проблема в том, что "картинка" которую он "видит" может с реальным потребностями и проблемами расходиться. Именно так часто и получается.
G>>3) Люди пытаются на Linq написать то, что в базе уже есть, но нет в Linq. Видел такие рукопашные реализации FTS и оператора Merge.
V>>>А хинты нужны малость для другого, тут исходный способ генерирования запроса не при чем от слова вообще. Но они, действительно, часто нужны. G>>Я не знаю для чего по твоему нужны хинты, я видел как их применяют при использовании хранимок для Data Access. V>Хинтами можно указать уровень блокировок. При частом обновлении это даёт прирост до нескольких раз, в особо клинических случаях — до порядка.
Особо клинические случаи получаются как раз по причинам, описанным выше.
EF кстати генрит базы с READ_COMMITED_SNAPSHOT, так что блокировки, скорее всего, не станут проблемой.
V>Ну и "длинные транзакции" всё-равно на стороне базы исполняются на многие порядки быстрее (с тащтельно подобранными уровнями блокировки), чем последовательность вызовов Linq с клиента базы в рамках одной транзакции. От этого ты вообще никак не убежишь.
"Длинные транзакции" это что? Если у тебя один селект работает полчаса это длинная транзакция? А 1000 инсертов за секунду, отправленных одним батчем? И то и другое вполне может быть сделано как Linq, так и написано вручную.
V>Триггера те же и т.д. V>Понимаешь, все эти триггера, длинные транзакции и прочее используют какую-то кодовую базу SQL, которая УЖЕ есть на стороне базы. Смысл её дублировать в Linq?
А кто говорит что надо дублировать? Типичное распределение чтения\записи в веб-приложении — 98\2. Об оптимизации записи речи в этом плане не идет.
V>В этом смысле Linq можно рассматривать примерно как и весь дотнет — как неплохой тул для макетирования. А "взрослая" разработка все-равно перепишет львиную долю макета в "боевой" вид.
Ну вот сайт сочи 2014 собрали макет и он удачно проработал...
V>>>Только не понятно, как ими пользоваться из LINQ? )) G>>Это показывает твой уровень знания SQL V>Ты не показал, как этим пользоваться из Linq.
Хинты в частности и любая оптимизация вообще должна выполняться как раз знающим человеком, поэтому допускать писать хинты в Linq категорически нельзя, ибо программисты хинтами зафиксируют план, потому что им покажется что "так лучше" и оптимизировать станет возможно только путем изменения кода. Поэтому хинты только через план-гайды.
G>>plan guide вообще-то есть. V>Есть мильон служебных хелперов, и? Эти хелперы связаны с состоянием базы. Ты чуть подмандил свой запрос, и твой вызванный ранее plan guide стал бесполезен. Или ты каждый раз перед целевым запросом будешь настраивать plan guide?
План-гайд или хинты для каждого запроса — индикатор неграмотного DBA. В базе много средств построения оптимальных планов без хинтов. Увы не все это знают. linq в этом плане помогает, ибо не дает писать хинты.
G>>Я вообще-то занимаюсь обучением таких DBA и прекрасно осведомлен об их способностях. G>>Если есть отдельный DBA, который не лезет в код, и программисты, которые не лезут в базу, то получается impendance mismatch между людьми. G>>Если DBA "главнее" программистов, то он рисует базу, небольшой набор хранимок (большой поддерживать влом), запинывает их хинтами и грозится оторвать руки тем, кто фигачит Adhoc запросы в базу. При этом хранимок мало, они не отражают реальные потребности приложения и отдают зачастую слишком много данных, а программисты на стороне приложения сами разбираются.
V>Скорее, это результат ТВОЕГО обучения. )) А есть среди них те, кто хотя бы лет 15 именно этим занимается?
нет, это состояние ДО обучения. Был один раз DBA с огромным опытом, чуть ли не 20 лет, имел должность "главного архитектора". С удивлением узнал про read_commited_snapshot и не очень понимал как работает статистика.
V>Про impendance mismatch я вообще молчу. С грамотным DBA я наблюдал ровно противоположное — у всех всё выспросит, заставить оформить требования, ни байта лишнего из базы не отдаст.
Теоретически такое может быть, но сильно удлиняет цикл разработки и повышает нагрузку на этого самого DBA.
V>Про количество хранимок и вьюшек я написал выше. Я сразу в твоих аргументах ощутил специфический опыт, когда разработка на стороне базы фактически отсутствовала. ОК! В условиях объективной невозможности вести разработку на стороне базы, Linq тебе в помощь.
С чего ты взял что отсутствовала? Я говорил именно про запросы, которые идут от приложения в базу. То что происходит внутри базы не является предметом разговора.
V>Правда, и до Linq был тот же Hibernate/NHibernate со своим построителем запросов. ))
там постритель запросов с трудом осиливает джоины и предикаты. Подзапросы и проекции — жопа.
G>>Если же программисты "главнее" DBA, то программисты юзают базу как тупое хранилище объектов, а DBA только пишет batch processing для самых тормозящих сценариев. V>И этот подход прекрасно работает, пока в таблицах сотни тыщ / единицы мильонов строк! )))
Ну это ели не сделать чтонить типа select N+1. Посадить производительность можно всегда, и даже Linq в этом не помешает.
G>>Лет 7-8 назад такое было повсеместно, потом появился Linq и больше C# программистов стало понимать что происходит в базе и как сделать оптимальной работу с СУБД. G>>Но тебя это, видимо не коснулось. Не беспокойся, еще не поздно изучить.
V>Что ИМЕННО надо изучить?
Как работает SQL.
V>И КАК C#-программист начнет понимать происходящее в базе, особенно, если разные программисты разрабатывают разные абстрактные предикаты, из которых собирается целевой запрос "кем-то еще"? Даже по неизвестной заранее таблице? Как преодолеть ту пропасть между мышлением "типами" у программиста и "доменами" у DBA? ))
Изучать и SQL, и C#.
G>>>>Добавляй сразу в классы, ef добавит его в базу.
V>>>Не со всеми нужными св-вами. Не со всеми связями, ограничениями, триггерами и т.д. до бесконечности. Как-то ты примитивно рассматриваешь базу, однако. G>>Так добавь что нужно, тебя никто не ограничивает.
V>Добавлю, конечно. Иначе бы не приводил как аргумент того, что от независимого изменения базы ты не убежишь. Этот "автоматизм" вообще малость опасен. Возьмет какой-нить программист удалит поле, синхронизирует, потом обнаружит, что оно было нужно таки, быстро добавит обратно, опять синхронизирует. И тю-тю все прежние настройки. Если диффы по SQL-определениям таблиц не вести, то и не заметишь ничего. А их удобнее вести именно при полноценной разработки базы со стороны базы.
Так для этого и созданы миграции. База данных и код синхронизированы. Разработчик работает на локальной базе, фиксирует изменения. При деплое новой версии в общую тестовую среду, изменения базы деплоятся пачкой все сразу.
Так что рассинхрона или таких выкрутасов, как ты описываешь, достигнуть сложно.
V>Нет, не динамические. Подготавливается заранее view, скрывающий всю сложность низлежащего запроса, а уже на результат можно накладывать сортировку и фильтрацию. View делается DBA, конкретный тупой SQL-запрос к этому view пишет программист. Но он же тривиальный, много ума не надо, бо по специально заточенному view идёт тупой "select * from ... where ... order by ...".
так where и orderby каждый раз будут разными, это все равно не динамический запрос?
G>>Что ты имеешь ввиду под динамическими запросами?
V>С динамической структурой, затрагивающей подзапросы. Т.е. где в условиях идут еще выборки или групповые операции над ними, типа exists, any и т.д. из этой оперы. С перекрестными связями по-условию м/у подуровнями — прикольнее всего. ))
А чем такие запросы в принципе отличаются от "select * from .. where ..." где предикаты формируются в UI (с точки зрения SQL)?
V>>>Это обычно только какие-нить специфические отчеты, редко потребляемая аналитика или что-то в этом роде. Я не спорю, что таких запросов может быть абсолютное большинство, если считать запросы не в кол-ве реальных употреблений, а в штуках наличия самих запросов. G>>Как раз для отчетов запросы статичны, то есть они один раз задаются и много раз вызываются. V>Это список полей статичный, а запрос к базе может быть очень даже динамичным в том смысле, что я написал выше.
Увы, не могу понять твое определение динамичности. Для SQL это такой же запрос.
G>>Давай по порядку: что ты называешь динамическими запросами?
V>Ну я заведомо исключил из них те, где меняются простые параметры, бо для ТАКИХ сценариев вообще Linq не облокотился и обсуждать сразу нечего. V>Я рассматриваю те сценарии, где Linq еще хоть зачем-то нужен, например, если ты заранее не знаешь, какой будет конечный join.
Что значит "заранее не знаешь" ?
G>>Я грешным делом подумал что называешь динамическими запросы, которые клеятся по кускам, но прочитав твой ответ я понял, что не понял что ты называешь динамическими запросами. V>Это запросы с неизвестной заранее структурой и уровнями вложенности. Например, в одной из систем был способ визуального построения иерархического фильтра и простенький DSL к нему, для пользования клиентами.
И что? Он все равно давал на выходе конечное множество запросов. Чем такая штука принципиально отличается от грида с настраиваемыми сортировками? (опять же с точки зрения SQL).
Здравствуйте, vdimas, Вы писали:
V>Сам запрос в Linq формируется тупым переводом структуры исходного выражения.
Лучше не пиши того, о чем не знаешь. Даже если никаких оптимизаций не делать тупой перевод LINQ в SQL все равно невозможен, там разная структура запросов и разные языковые возможности. IT тут не зря написал, что собственный linq провайдер это очень сложно и дорого.
Вообще, читая тут твои сообщения складывается стойкое ощущение, что в твоем представлении LINQ это просто встроенный в C# SQL.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, IT, Вы писали:
IT>> Т.е. начинаю я работать над какой-нибудь формой и мне нужно заполнить её данными, пока двумя полями. Я зову Васю-Специалиста-На-Базах-И-Запросах и он пишет мне в моём коде SQL, который читает эти два поля для меня из базы. Через 10 минут мне надо подчитать третье поле,
V>Т.е. ты сам себе ПМ, аналитик, архитектор и тот самый Вася, если тебе через 10 мин (!!!) потребовалось третье поле. ))
Как это связано? Чтобы добавить поле нужен аналитик, архитектор и еще кто-то?
V>Худшие архитектурные решения получаются у людей, чей кредит доверия превышает их профессиональные навыки, а всё остальное — лирика и субъективизм.
На поле СУБД часто наблюдаются искажения. Человек знающий слово "статистика", "хинт" или "покрывающий индекс" получает практически неограниченный кредит доверия со стороны тех, кто подобных слов не знает.
Причем если бы вместо СУБД был функциональный язык, то его бы послали и запилили все на "родном" C#\Java\PHP. Но СУБД такая штука, что отказаться от неё нельзя, а вникать как она работает всем не хочется (выводит из зоны комфорта).
Вот и получается, что DBA с посредственными навыками получают слишком большой кредит доверия.
Кстати по этой же причине последние годы появилось повальное увлечение NoSQL базами. Они банально проще и работа с ними более прямолинейна.
Здравствуйте, gandjustas, Вы писали:
G>Даже банальная математика говорит что при 2к хранимок и 200 таблиц это минимум 10 хранимок на таблицу, а скорее всего в два раза больше. Любая правка в исходной таблице — нужна синхронная правка около 20 хранимок. Команда из 3-4 программистов будет поля править раз в день, DBA от такого сдохнет.
Во-во, и после этого ты еще поучаешь коллег.
Все запросы всей базы верифицируются после изменений.
G>При этом Linq позволяет генерировать больше и более специализированные запросы, чем выделенный DBA.
Ты плохо представляешь себе работу DBA. В 90% случаев от "слепит" тебе результат из уже готовых view, табличных ф-ий или уже готовых SP. У грамотного разработчика большое повторное использование кода. Соответственно его вариант будет намного-намного проще твоего, построенного на Linq с 0-ля.
G>>>>>Запросы не эффективны, тормозят, пинают их хинтами, чтобы работало приемлемо. V>>>>Это LINQ генерит жутко неэффективные запросы. G>>>Люди генерят неэффективные запросы, а Linq может косячить только в очень сложных случаях, которые вообще бессмысленно на Linq писать. V>>Linq использует далеко не все ср-ва языка. И речь не только о хинтах. Сам запрос в Linq формируется тупым переводом структуры исходного выражения. Поэтому, не спорь, Linq генерит заведомо плохой SQL "в лоб". G>Уж прости, но аргументация на уровне детского сада.
Нормальная аргументация.
G>Linq умеет генерить: G>1) все виды джоинов G>2) подзапросы G>3) группировки G>4) предикаты G>Этого хватает чтобы покрыть 99% запросов.
Кто же спорит...
Я говорил про вид запросов. Одно и тоже сложное выражение можно вертеть многими способами. На Linq это банально неудобно, т.к. не очевидно. Например, очередность и взаимная вложенность подзапросов запросто может зависеть от конкретного провайдера, порождающего код SQL.
А рассуждения из цикла "MS SQL умный и сам составит нужный план" — и есть детсад. Это только на относительно несложных запросах. Вложи 3 раза exists/any друг в друга и получишь, что вертя внешней формой одного и того же запроса будешь менять конечный план.
G>Linq не умеет (зависит от провайдера): G>1) CTE G>2) merge operator G>3) ranking-функции G>Сколько запросов у тебя содержат эти функции?
С любыми запросами на групповое обновление — беда. А их бывает дохрена в учетных системах. Linq тебе поможет в обновлении только пообъектно, то бишь построчно. Хаха, как грится.
G>Что ты считаешь "плохим" SQL и почему Linq его генерит сам?
Потому что программист борется за лучшую читабельность, вестимо. Это же на уровне мозжечка, на то он и программист. А по закону подлости, наилучшим образом читаемый Linq-запрос не всегда самый лучший.
V>>Куда тянется? Если это внутренний подзапрос, то ничего никуда не тянется. G>С чего ты взял? От проекции в запросе (неважно подзапрос это или нет) зависит какой план построит SQL, а это напрямую влияет на быстродействие. Конечно кроме случаев, когда ты используешь подзапрос в exists выражении.
Да любой подзапрос, если его поля используются только для построения условий на других уровнях — там вовсе не надо указывать никакие проекции, "унутре" всегда читается строка в ОП целиком (кроме тех самых блобов и text), бо MS SQL хранит построчно.
V>>Лишние поля на клиента мы не гоняли, ес-но, т.е. select самого верхнего уровня тщательный, ес-но. Мне даже трудно вообразить, где-то может быть не так и ты даже привел ЭТО как аргумент. )) G>Знал бы ты сколько я таких запросов починил... Не хватит пальцев рук у всех родственников до третьего колена.
Мде. Теперь я знаю, чем еще плох Linq. )))
Шутю. Вряд ли буду использовать сие как аргумент конкретно по Linq, т.к. не вооруженным взглядом видно, что тут речь об уровне разработчика скорее, т.е. это будет чистой воды спекуляция. Ну и ты, ес-но, такой мощный разработчик, подбираешь за другими их г-но... Если бы я всё то г-но, что подбирал за неопытными коллегами, приводил как аргумент, спорить можно было бы бесконечно и ни о чем в то же время. ))
G>>>2) Люди пишут Linq запросы не понимая что происходит в базе. Особенно часто встречается FirstOrDefault, который в SQL работает очень медленно, или банально вызывают функции в предикатах.
V>>Ну, если, действительно нужен First, то быстрее ты не сделаешь. А OrDefault можно и на клиентской стороне обыграть, но это не может существенно повлиять на результат. Что-то ты не то говоришь, кароч. Я тебе говорил о самом SQL. Кароч, оч большая разница с тем, какой SQL пишет специально-обученный и уже 20 лет этим занимающийся человек и SQL после Linq "обычного программиста". Это небо и земля.
G>Разница конечно есть, но не всегда в положительную сторону. Человек может ошибаться или банально не знать о конкретных потребностях приложения, поэтому делать неоптимальные запросы.
Да ХЗ.
Я привел такой аргумент как "вариться" во всём этом. Пытаться его раскрыть можно долго и нудно, но мне банально облом. Когда ты "варишься" в чем-то, то у тебя совсем другие навыки, чем у того, который делает это лишь "мимоходом". Другие сценарии, ты в другие места смотришь, когда видишь результат и т.д. DBA следит не за приложением, в отличие от программиста, а за данными. И эти данные на одном и том же приложении могут быть разные у разных влиентов. Поэтому и индексы и прикручиваемые хинты могут быть разные.
Да. Серьезные приложухи на стороне базы — это ад для современных программистов. Это и так известно. Но выхода не было, по тем ресурсам аппаратуры, что были еще до времен MS SQL 2005. Сейчас то же самое с той лишь разницей, что эта граница отодвинулась примерно в 5 раз. Но она не исчезла. Просто да, многие нагрузочные раньше приложения стали простыми с т.з. требуемой мощности. Но далеко не все. Серьезные по размерам базы всё так же обслуживаются DBA по-старинке, я знаю это их первых рук, как грится.
А простые сценарии обсуждать облом. Я уже высказывался про то, что когда вся база влезает в оперативку сервака, то реляционка является заведомо худшим выбором.
V>>Опять же. Есть такой фактор — владение проблемой. Когда программист SQL пишет запросы, он "видит" происходящую картинку. Именно так. Нет эдакого "разрыва" кода и базы. Просто индексы, статистику, материализцию view и прочее — такие решения принимает человек, который в этом "варится". А программист C# в этом не варится нифига, что бы кто не говорил. G>Проблема в том, что "картинка" которую он "видит" может с реальным потребностями и проблемами расходиться. Именно так часто и получается.
Бла-бла-бла. Реальную картинку даешь не ты, мега-программист, а характер самих данных и конечно статистика. Но её тоже надо уметь читать и понимать.
V>>Хинтами можно указать уровень блокировок. При частом обновлении это даёт прирост до нескольких раз, в особо клинических случаях — до порядка. G>Особо клинические случаи получаются как раз по причинам, описанным выше.
Конкретно к хинтам ни одной причины не увидел.
Клинические они по самому сценарию. Вот тебе идёт обновление одной и той же немалой таблицы тысячи раз в секунду и десятки тысяч раз — запросы из неё. Хоть ужом извернись, но без ручного ковыряния хинтами ты нормально ничего не сделаешь. Часто таблицу разбивают на 2, а то и 3: актуальные (наиболее меняющиеся) данные, реже меняющиеся, исторические. Иногда делят домены на поддомены и т.д. и т.п.. И периодически перемещают данные м/у таблицами. И для разных операций разные уровни блокировки.
G>EF кстати генрит базы с READ_COMMITED_SNAPSHOT, так что блокировки, скорее всего, не станут проблемой.
Для батча с построчным изменением нескольких объектов? Ню-ню...
Ты хоть знаешь, что еще лет 10 назад за подобное любой вменяемый DBA тебя просто расстрелял бы? ))
При небольшом кол-ве построчных изменений, всё можно вложить в один запрос обновления, а не в батч, где каждый раз идет скан по таблице. Один скан на 3 ключа дешевле, чем три скана на один ключ. Хотя итоговая "математическая" сложность эквивалентна. Но вот подиж ты.
V>>Ну и "длинные транзакции" всё-равно на стороне базы исполняются на многие порядки быстрее (с тащтельно подобранными уровнями блокировки), чем последовательность вызовов Linq с клиента базы в рамках одной транзакции. От этого ты вообще никак не убежишь. G>"Длинные транзакции" это что?
Это начало транзакции, более одной операции, конец транзакции.
G>Если у тебя один селект работает полчаса это длинная транзакция?
Это идиотизм даже по меркам 10-тилетней давности. А уж на нынешних мощщах за это кастрировать надо. Чтобы не портить общечеловеческий генофонд. Я тут ему про актуальные/исторические данные распинаюсь, про поддомены, а он мне селект на пол-часа.
G>А 1000 инсертов за секунду, отправленных одним батчем? И то и другое вполне может быть сделано как Linq, так и написано вручную.
Тупые 1000 инсертов за секунду позволял сервак на Pentium-III в своё время.
V>>Триггера те же и т.д. V>>Понимаешь, все эти триггера, длинные транзакции и прочее используют какую-то кодовую базу SQL, которая УЖЕ есть на стороне базы. Смысл её дублировать в Linq? G>А кто говорит что надо дублировать? Типичное распределение чтения\записи в веб-приложении — 98\2. Об оптимизации записи речи в этом плане не идет.
V>>В этом смысле Linq можно рассматривать примерно как и весь дотнет — как неплохой тул для макетирования. А "взрослая" разработка все-равно перепишет львиную долю макета в "боевой" вид. G>Ну вот сайт сочи 2014 собрали макет и он удачно проработал...
Новостной сайт базу не нагружает от слова вообще. Эти сайты по большей части пишутся на конструкторах сайтов, где самый популярный конструктор написан на... ууупссс!... VB.Net, и весь мир прекрасно на этом работает.
Писать сегодня новостной сайт на коленке + Linq — это разновидность попила.
V>>Ты не показал, как этим пользоваться из Linq. G>Хинты в частности и любая оптимизация вообще должна выполняться как раз знающим человеком, поэтому допускать писать хинты в Linq категорически нельзя, ибо программисты хинтами зафиксируют план, потому что им покажется что "так лучше" и оптимизировать станет возможно только путем изменения кода. Поэтому хинты только через план-гайды.
Я уже отвечал на это. Мимо.
V>>Есть мильон служебных хелперов, и? Эти хелперы связаны с состоянием базы. Ты чуть подмандил свой запрос, и твой вызванный ранее plan guide стал бесполезен. Или ты каждый раз перед целевым запросом будешь настраивать plan guide? G>План-гайд или хинты для каждого запроса — индикатор неграмотного DBA. В базе много средств построения оптимальных планов без хинтов. Увы не все это знают. linq в этом плане помогает, ибо не дает писать хинты.
Ясно. Этот вопрос ты решил тщательно замылить.
Ты мне конкретный сценарий дай. Вот у меня идёт постоянная и одновременно частое обновление на таблице — регистре остатков. Частоту я тебе уже приводил. Без хинтов блокировок там ловить нечего. Просто поверь. Не работает.
V>>Скорее, это результат ТВОЕГО обучения. )) А есть среди них те, кто хотя бы лет 15 именно этим занимается? G>нет, это состояние ДО обучения. Был один раз DBA с огромным опытом, чуть ли не 20 лет, имел должность "главного архитектора". С удивлением узнал про read_commited_snapshot и не очень понимал как работает статистика.
Ну тогда мне всё ясно. Прими мои соболезнования.
Я одно не понимаю! Какое нафиг отношение к нашему обсуждению имеют ГЛОБАЛЬНЫЕ настройки базы (типа твоего read_commited_snapshot), когда речь о тюнинге конкретных запросов? Этих глобальных настроек многие десятки и что с того?
Я не увидел удобного сценария, как тюнить хинтами запросы в Linq, кароч.
V>>Про impendance mismatch я вообще молчу. С грамотным DBA я наблюдал ровно противоположное — у всех всё выспросит, заставить оформить требования, ни байта лишнего из базы не отдаст. G>Теоретически такое может быть, но сильно удлиняет цикл разработки и повышает нагрузку на этого самого DBA.
Дык, у него ЗП не меньше, чем у программиста. Каждый пусть занимается своим делом.
V>>Про количество хранимок и вьюшек я написал выше. Я сразу в твоих аргументах ощутил специфический опыт, когда разработка на стороне базы фактически отсутствовала. ОК! В условиях объективной невозможности вести разработку на стороне базы, Linq тебе в помощь. G>С чего ты взял что отсутствовала?
Ну или опыт был печален. Блин, с вами линоководами смешные разговоры выходят. Как послушаешь вас, так до Linq ни одного приложения на БД толком не взлетело и это идёт как основной аргумент. Ребят, это у ВАС не взлетело. А весь мир давно успешно пользуется базами без Linq. Например, ни в один банк ты со своим Linq не сунешься, кроме как для маргинальной неспешной аналитики под прихоть и ответственность какого-нить старшего менеджера. В рабочий процесс ЭТО не пустят на сегодня. Таковы реалии.
V>>Правда, и до Linq был тот же Hibernate/NHibernate со своим построителем запросов. )) G>там постритель запросов с трудом осиливает джоины и предикаты. Подзапросы и проекции — жопа.
Нормально он осиливает. Если пользоваться в синтаксисе "объектного построителя" как мне тут рядом давали для демонстрации прикрепления хинтов, то точно так же всё.
G>>>Если же программисты "главнее" DBA, то программисты юзают базу как тупое хранилище объектов, а DBA только пишет batch processing для самых тормозящих сценариев. V>>И этот подход прекрасно работает, пока в таблицах сотни тыщ / единицы мильонов строк! ))) G>Ну это ели не сделать чтонить типа select N+1. Посадить производительность можно всегда, и даже Linq в этом не помешает.
Да не в этом дело. А в том, что когда вся база легко садится в ОП сервака, то наш разговор теряет смысл сам собой. И вообще становится дичью, бо надобность реляционки в таком сценарии сильно под вопросом.
G>>>Лет 7-8 назад такое было повсеместно, потом появился Linq и больше C# программистов стало понимать что происходит в базе и как сделать оптимальной работу с СУБД. G>>>Но тебя это, видимо не коснулось. Не беспокойся, еще не поздно изучить.
V>>Что ИМЕННО надо изучить? G>Как работает SQL.
Давай конкретней. Особенно про момент, когда программист Linq волшебным образом начинает БОЛЬШЕ ПОНИМАТЬ, что происходит в базе.
V>>И КАК C#-программист начнет понимать происходящее в базе, особенно, если разные программисты разрабатывают разные абстрактные предикаты, из которых собирается целевой запрос "кем-то еще"? Даже по неизвестной заранее таблице? Как преодолеть ту пропасть между мышлением "типами" у программиста и "доменами" у DBA? )) G>Изучать и SQL, и C#.
Это не ответ на выделенное. Ты хоть вопрос понял?
V>>Нет, не динамические. Подготавливается заранее view, скрывающий всю сложность низлежащего запроса, а уже на результат можно накладывать сортировку и фильтрацию. View делается DBA, конкретный тупой SQL-запрос к этому view пишет программист. Но он же тривиальный, много ума не надо, бо по специально заточенному view идёт тупой "select * from ... where ... order by ...".
G>так where и orderby каждый раз будут разными, это все равно не динамический запрос?
ОК, динамический. Но недостойный ни внимания, ни обсуждения.
Просто, действительно динамически в моей практике строили запросы только с изменяемой структурой. А описанный сценарий требует лишь однажды написанной вьюшки на стороне базы. Пусть эту вьюшка будет унутре сколь угодно сложной, но прилепить условия и сортировку к ней можно задешево без всяких Linq.
G>>>Что ты имеешь ввиду под динамическими запросами?
V>>С динамической структурой, затрагивающей подзапросы. Т.е. где в условиях идут еще выборки или групповые операции над ними, типа exists, any и т.д. из этой оперы. С перекрестными связями по-условию м/у подуровнями — прикольнее всего. )) G>А чем такие запросы в принципе отличаются от "select * from .. where ..." где предикаты формируются в UI (с точки зрения SQL)?
Чем сложнее тело вьюшки, тем более больше отличий, вестимо.
Ты всерьез спрашиваешь или как? ))
V>>Это список полей статичный, а запрос к базе может быть очень даже динамичным в том смысле, что я написал выше. G>Увы, не могу понять твое определение динамичности. Для SQL это такой же запрос.
G>>>Давай по порядку: что ты называешь динамическими запросами?
V>>Ну я заведомо исключил из них те, где меняются простые параметры, бо для ТАКИХ сценариев вообще Linq не облокотился и обсуждать сразу нечего. V>>Я рассматриваю те сценарии, где Linq еще хоть зачем-то нужен, например, если ты заранее не знаешь, какой будет конечный join. G>Что значит "заранее не знаешь" ?
Ну вот так. Добавил сравнение со статистикой — вот тебе лишняя операция реляционной алгебры (всё-равно все подзапросы, а так же exists/any/all/some и т.д. идут унутре через разновидности джоинов). Добавил сравнение в другим элементом, встречающимся в другом поддомене — вот тебе дополнительный джоин на другую таблицу.
G>>>Я грешным делом подумал что называешь динамическими запросы, которые клеятся по кускам, но прочитав твой ответ я понял, что не понял что ты называешь динамическими запросами. V>>Это запросы с неизвестной заранее структурой и уровнями вложенности. Например, в одной из систем был способ визуального построения иерархического фильтра и простенький DSL к нему, для пользования клиентами. G>И что? Он все равно давал на выходе конечное множество запросов.
На выходе ващет бесконечное мн-во запросов.
G>Чем такая штука принципиально отличается от грида с настраиваемыми сортировками? (опять же с точки зрения SQL).
Тем, что для грида можно написать низлежащую вьюшку лишь однажды.
Здравствуйте, Ночной Смотрящий, Вы писали:
V>>Сам запрос в Linq формируется тупым переводом структуры исходного выражения.
НС>Лучше не пиши того, о чем не знаешь. Даже если никаких оптимизаций не делать тупой перевод LINQ в SQL все равно невозможен, там разная структура запросов и разные языковые возможности. IT тут не зря написал, что собственный linq провайдер это очень сложно и дорого. НС>Вообще, читая тут твои сообщения складывается стойкое ощущение, что в твоем представлении LINQ это просто встроенный в C# SQL.
Я очень внимательно слежу за разработками коллеги IT c 2003-го года, если что... И не раз его либы использовал во всех их 3-х основных этапах жизни. ))
Много чего дорабатывал под свои нужды (маппинг на массив объектов, описанных как value-type, например). Скажу больше, если бы разрешили, еще бы в 2006-м добавили свою визуальную дизайн-тайм приблуду над его ORM. У нас было оч удобно.
"Тупой" подразумевал без оптимизации, то бишь без "понимания" самого запроса. Это на клиентской стороне практически всегда и невозможно. Почему — отдельная тема. Правда, неинтересная, бо прошли её еще лет 10 назад, всё и так ясно.
НС>>>Хинты и LINQ, в общем случае, перпендикулярны. V>>А в синтаксисе именно LINQ?
НС>Сто такое "синтаксис LINQ"? Если ты про query comprehension, то это не обязательная и даже не основная его часть. Я, к примеру, ей вообще не пользуюсь.
Э нет! Когда приводят примеры именно крутости Linq в том плане, что он позволил построить сложный запрос, в котором на SQL сам чёрт ногу сломит, то приводят именно встроенный синтаксис. И я даже иногда бываю согласен.
А в приведенном тобой виде, повторюсь, мы могли это еще в 2004-м. ))
V>>Так-то у нас "объектный" построитель запросов в похожем синтаксисе
НС>Похожесть тебе только показалась. Ключевой момент здесь — наличие expression tree, которого в 2004 не было. А QC это так, мелочевка.
Это у вас не было. А у нас — практически все используемые по-факту операции в выражениях T-SQL. И переопределение операторов, ес-но, для вменяемого синтаксиса.
НС>>>Ага, а потом я в таких проектах переписываю хранимки на linq2db и получаю ускорение в 2-3 раза. V>>За счет чего именно?
НС>За счет того что выкидывается куча странного кода внутри хранимок. Особо весело выходит, когда одна хранимка вызывает другую, та третью и т.д.
Так это специально так делается. Хранимки и надо декомпозировать, если есть некие условия "верхнего" уровня.
Внутри одной хранимки может быть криво закеширован план, увы. MS SQK этим страдал. Не знаю как сейчас.
V>>Я бы мог ответить "это твой опыт, такой у вас был ДВА и т.д." НС>Проблема только в том, что я в куче проектов такое видел. А, судя по общению с коллегами, не только я.
V>>Тем более, что самые "тяжелые" хранимки (по моему субъективному опыту) ни на какой Linq не перенесешь, бо там несколько операций с промежуточными таблицами, обычно
НС>Во-во, навертят бреда вокруг промежуточных таблиц на ровном месте с десятком select into, а потом оказывается что все можно переписать без них.
До снятия ограничений с табличных ф-ий на рекурсию и до введения рекурсивных возможностей в SQL — нифига не всё.
Да и сейчас тоже.
Опять же. В любом случае, в процессе таких же точно вычислений точно так же создаются промежуточные результаты во временных таблицах, просто неявно. Вряд ли ты покажешь существенный прирост скорости, бо происходит одно и то же. А код с промежуточными результатами зачастую намного проще и, опять же, замечательно поддаётся декомпозиции и повторному использованию.
V>>>>Зачем же снова и снова строить одни и те же запросы в рантайм? ))) НС>>>Нормальные linq провайдеры умеют запросы кешировать. V>>Речь об общей кодовой базе. Повторного использования кода на стороне БД, при разработке именно со стороны БД оч много.
НС>Моя практика в рамках нескольких разнородных проектов показывает наоборот, такого кода очень мало. 90% запросов уникальны.
Ну а по моей практике, уникальны 90% простых вьюшек и табличных ф-ий, составляющих "низкоуровневый" слой. А что-то более-менее сложное делается уже на основе имеющихся простых вьюшек и тех же табличных ф-ий. А какой смысл многократно расписывать одни и те же комбинации джоинов?
G>Покажи пример где EF последней версии генерит неэффективный запрос.
Order[] orders = context.Set<Order>().Include( o => o.Products).ToArray();
Генерится SQL, который в два раза менее эффективен, чем генерил в свое время linq2SQL. И это один из наиболее частых сценариев, то есть это приговор инструменту...
А знаешь почему запрос такой тормозной и они так и не поправили его за пять лет? Потому что для корректной работы маппинга EF через внутреннюю модель, нужно сгенерить дополнительный столбец, по которому не построишь индекс, а потом еще и отсортировать по этому столбцу.
То есть нельзя просто взять и поправить генерацию запросов для сценария потомок-родитель — нужно переделывать всю архитектуру генерации запросов. А эта архитектура, в свою очередь, явилась следствием дурацкой идеологии.
Как видишь, иногда полезно все-таки понимать изначальную идею решения и оценивать ее адекватность, а не бросаться сразу осваивать все что предложили.
Э да!
V> Когда приводят примеры именно крутости Linq в том плане, что он позволил построить сложный запрос, в котором на SQL сам чёрт ногу сломит, то приводят именно встроенный синтаксис
Это личные примеры того кто приводит. Я здесь приводил примеры без этого. И вообще, кто и что приводит к обсуждению отношения не имеет.
V>А в приведенном тобой виде, повторюсь, мы могли это еще в 2004-м. ))
Подобные утверждения выдают твое полное непонимание того, что такое LINQ. Без expression tree LINQ невозможен в принципе.
НС>>Похожесть тебе только показалась. Ключевой момент здесь — наличие expression tree, которого в 2004 не было. А QC это так, мелочевка. V>Это у вас не было.
Это в C# не было.
V> А у нас — практически все используемые по-факту операции в выражениях T-SQL. И переопределение операторов, ес-но, для вменяемого синтаксиса.
Ты не понимаешь что такое expression tree.
НС>>За счет того что выкидывается куча странного кода внутри хранимок. Особо весело выходит, когда одна хранимка вызывает другую, та третью и т.д. V>Так это специально так делается.
О да, и специально от этого тормозит как не в себя. Потому что вызов хранимки в интерпретаторе SQL это дорого, и потому что средства декомпозии у SQL до жути убоги (из нормального в mssql, по сути, только inline functions).
НС>>Во-во, навертят бреда вокруг промежуточных таблиц на ровном месте с десятком select into, а потом оказывается что все можно переписать без них. V>До снятия ограничений с табличных ф-ий на рекурсию и до введения рекурсивных возможностей в SQL — нифига не всё.
Описываемые мной проблемы присутствовали без какой либо рекурсии.
V>Опять же. В любом случае, в процессе таких же точно вычислений точно так же создаются промежуточные результаты во временных таблицах, просто неявно.
Вот только перформанс с их выкидыванием, напоминаю, улучшался в разы.
V>А код с промежуточными результатами зачастую намного проще и, опять же, замечательно поддаётся декомпозиции и повторному использованию.
Код LINQ запросов неизмеримо лучше поддается декомпозиции, чем императивный код на T-SQL.
V>А какой смысл многократно расписывать одни и те же комбинации джоинов?
А не надо, внезапно, в LINQ расписывать руками джойны, представляешь?
Здравствуйте, Ночной Смотрящий, Вы писали:
V>>"Тупой" подразумевал без оптимизации НС>В BLT определенные оптимизации делаются.
В рамках логических/арифметических выражений?
V>>, то бишь без "понимания" самого запроса НС>Что такое "понимание запроса"?
Логически дублированные/эквивалентные части вычленять, например. Это без переводя на язык реляционной алгебры и невозможно толком. А если используется view в запросе вместе в дублированием части её тела, то на клиенте тем более невозможно.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>Покажи пример где EF последней версии генерит неэффективный запрос.
IB>
IB> Order[] orders = context.Set<Order>().Include( o => o.Products).ToArray();
IB>
IB>Генерится SQL, который в два раза менее эффективен, чем генерил в свое время linq2SQL. И это один из наиболее частых сценариев, то есть это приговор инструменту...
IB>А знаешь почему запрос такой тормозной и они так и не поправили его за пять лет? Потому что для корректной работы маппинга EF через внутреннюю модель, нужно сгенерить дополнительный столбец, по которому не построишь индекс, а потом еще и отсортировать по этому столбцу. IB>То есть нельзя просто взять и поправить генерацию запросов для сценария потомок-родитель — нужно переделывать всю архитектуру генерации запросов. А эта архитектура, в свою очередь, явилась следствием дурацкой идеологии. IB>Как видишь, иногда полезно все-таки понимать изначальную идею решения и оценивать ее адекватность, а не бросаться сразу осваивать все что предложили.
Вы имеете в виду наследование и столбец-дискриминатор? Если да, то по примеру у вас этого вообще не видно.
Напишите что за схема используется и какой SQL получается в обоих случаях.
PS. Не сравнивал эффективность, но способность EF6.1 загружать несколько связанных коллекций (OtM, MtM) одним запросом меня порадовала. Hibernate насколько я знаю до сих пор это не осилил и плюётся исключением.
Здравствуйте, gandjustas, Вы писали:
IT>>В общем, если бы я точно знал куда я лезу, когда начинал заниматься linq-провайдером в BLT, то точно бы не стал этого делать и сейчас, скорее всего восхвалял EF вместе с тобой и точно так же спорил бы с IB G>А почему? Решение проблем не стоит затраченных усилий?
Потому что я недооценил сложность задачи. Причём недооценил не просто скажем в пару раз, а как оказалось в пару десятков раз. Планировалось всё закончить за пару тройку месяцев, в результате где-то только через пол года наступило понимание происходящего. Естественно, речь идёт не о full-time работае за деньги, а об open-source проекте в свободное время, но даже работая full-time такая задача не поднимается за несколько месяцев.
G>Тогда за что EF ругают?
За громоздкую и никому не нужную архитектуру. За тормоза. За кривой SQL. За кривой маппинг, вспомним маппинг энумераторов. За бестолковые решения, делающие некоторые фичи совершенно бесполезными. Самое интересное, что на уровне архитектуры решаемая задача на самом деле проста как угол дома. Если рисовать квадратики подсистем, то их можно будет пересчитать на пальцах одной руки. Всё, что нужно было сделать команде EF — это посмотреть по сторонам и проанализировать существующие решения на предмет наличия решений и их полезности. Тем более, что у них уже был собственный неудачный опыт ObjectSpaces и ошибочный на уровне архитектуры, но качественный в реализации Linq2SQL. Главной ошибкой было, конечно же, создание архитектуры на базе никому не нужных сервисов тяжёлой ORM.
IT>>Я программист, а не пиарщик. Видимо в этом проблема. К тому же см. выше про ресурсы. Кто-то их тратит на написание кода, а кто-то на толпы восторженных пользователей. G>Без реального фидбека хороший продукт не получится. А фидбек получить без контента не получится.
Фидбека хватает. linq2db не делался на голом месте. Можно сказать, что это глубокая переработка BLToolkit в части работы с БД, в которой учтены недостатки и переписаны проблемные места последней. К тому же, в отличии от команды EF, которая пишет продукт для кого-то, linq2db делается в том числе и для себя. У MS (и не только) традиционно хорошо получаются лишь те продукты, которыми они пользуются сами. Возьмём тут же студию или WPF, которым стало можно пользоваться лишь после того, как его стали применять в студии.
G>Я не про форум, а про гугл. Главное правило интернета — если тебя не находит гугл, значит тебя не существует.
Как договориться с гуглом я не знаю Видимо на это надо убить всё свободное время, но тогда кто будет заниматься библиотекой?
G>Генерит имя класса DataBaseName.WithDot, что вызывает ошибку компиляции.
Поправлю. Хотя это всё можно настроить в самом шаблоне, но исправить надо.
IT>>Всё можно сконфигурировать и без конфигов. Последние пять лет у меня это вообще была единственная доступная опция. G>Нельзя передать в конструктор контекста строку подключения
public DataConnection(IDataProvider dataProvider, string connectionString)
Здравствуйте, Ночной Смотрящий, Вы писали:
V>> Когда приводят примеры именно крутости Linq в том плане, что он позволил построить сложный запрос, в котором на SQL сам чёрт ногу сломит, то приводят именно встроенный синтаксис НС>Это личные примеры того кто приводит. Я здесь приводил примеры без этого. И вообще, кто и что приводит к обсуждению отношения не имеет.
Некий AVK приводил.
Не знакомы?
V>>А в приведенном тобой виде, повторюсь, мы могли это еще в 2004-м. )) НС>Подобные утверждения выдают твое полное непонимание того, что такое LINQ. Без expression tree LINQ невозможен в принципе.
Пффф...
НС>>>Похожесть тебе только показалась. Ключевой момент здесь — наличие expression tree, которого в 2004 не было. А QC это так, мелочевка. V>>Это у вас не было. НС>Это в C# не было.
Это было у нас.
V>> А у нас — практически все используемые по-факту операции в выражениях T-SQL. И переопределение операторов, ес-но, для вменяемого синтаксиса. НС>Ты не понимаешь что такое expression tree.
У нас называлось SqlOrOp, SqlAddOp, SqlJoinOp. И переопределение операторов в рамках C# отчасти выручало.
НС>>>За счет того что выкидывается куча странного кода внутри хранимок. Особо весело выходит, когда одна хранимка вызывает другую, та третью и т.д. V>>Так это специально так делается.
НС>О да, и специально от этого тормозит как не в себя. Потому что вызов хранимки в интерпретаторе SQL это дорого, и потому что средства декомпозии у SQL до жути убоги (из нормального в mssql, по сути, только inline functions).
Временная таблица уровня транзакции тебе в помощь для декомпозиции.
НС>>>Во-во, навертят бреда вокруг промежуточных таблиц на ровном месте с десятком select into, а потом оказывается что все можно переписать без них. V>>До снятия ограничений с табличных ф-ий на рекурсию и до введения рекурсивных возможностей в SQL — нифига не всё.
НС>Описываемые мной проблемы присутствовали без какой либо рекурсии.
Без рекурсии не нужны были временные таблицы.
V>>Опять же. В любом случае, в процессе таких же точно вычислений точно так же создаются промежуточные результаты во временных таблицах, просто неявно. НС>Вот только перформанс с их выкидыванием, напоминаю, улучшался в разы.
Тут бы хотелось взглянуть на до и после. Бо эксперименты с рекурсивными возможностями показали, что особой разницы с аналогичным кодом на курсорах нет.
V>>А код с промежуточными результатами зачастую намного проще и, опять же, замечательно поддаётся декомпозиции и повторному использованию. НС>Код LINQ запросов неизмеримо лучше поддается декомпозиции, чем императивный код на T-SQL.
На стороне клиента. База его компилит каждый раз.
V>>А какой смысл многократно расписывать одни и те же комбинации джоинов? НС>А не надо, внезапно, в LINQ расписывать руками джойны, представляешь?
Компилятору запроса на стороне базе надо. Тут речь идет о сравнительной стоимости стадий собсно подготовки запроса и его исполнения. Для частых однострочных обновлений прямой вызов sp в синтаксисе {proc params..} заруливал всё и вся. Стадия компиляции запроса отсутствует.
Здравствуйте, gandjustas, Вы писали:
V>>Т.е. ты сам себе ПМ, аналитик, архитектор и тот самый Вася, если тебе через 10 мин (!!!) потребовалось третье поле. )) G>Как это связано? Чтобы добавить поле нужен аналитик, архитектор и еще кто-то?
Ха-ха три раза.
Сначала код, так?
Например, для среднеразмерной складской программы?
V>>Худшие архитектурные решения получаются у людей, чей кредит доверия превышает их профессиональные навыки, а всё остальное — лирика и субъективизм.
G>На поле СУБД часто наблюдаются искажения. Человек знающий слово "статистика", "хинт" или "покрывающий индекс" получает практически неограниченный кредит доверия со стороны тех, кто подобных слов не знает.
Какое-то зазеркалье.
G>Причем если бы вместо СУБД был функциональный язык, то его бы послали и запилили все на "родном" C#\Java\PHP. Но СУБД такая штука, что отказаться от неё нельзя, а вникать как она работает всем не хочется (выводит из зоны комфорта).
Зона комфорта, говоришь? ))
Вас ведь именно за лень ума и ругают (если посмотреть на все эти споры с высоты птичьего полёта), а ты так подставляешься.
G>Вот и получается, что DBA с посредственными навыками получают слишком большой кредит доверия. G>Кстати по этой же причине последние годы появилось повальное увлечение NoSQL базами. Они банально проще и работа с ними более прямолинейна.
И кто тут косностью страдает?
NoSql хорош не по этому, а потому что аппаратура позволяет отказаться от реляционки. В т.ч. быстродействующие внешние носители, а не только размер ОП. Сдаётся мне, ты фундаментально не понимаешь происходящих процессов.
Реляционка с построчным хранением — самая неподходящая структура для навигации в случае наличия данных в ОП. Хуже — не придумать. И самая лучшая для МЕДЛЕННЫХ внешних носителей из всех имеющихся на сегодня конкурирующих парадигм. Поэтому и сложность алгоритмов в реляционках до сих пор считают в попугаях, то бишь, в кол-ве "страниц", необходимых для сканирования. В обычных объектах для этого же существуют "жесткие" ссылки, завязанные на физическое представление данных в памяти, где операция перехода по ссылке сравнима с разыменованием указателя... что на 4-8 порядков быстрее, чем поиск по ключу в реляционке.
Здравствуйте, vdimas, Вы писали:
V>Т.е. ты сам себе ПМ, аналитик, архитектор и тот самый Вася, если тебе через 10 мин (!!!) потребовалось третье поле. ))
Как это всё связано вместе?
V>Такого рода задачи у нас тоже бывали, но ничего серьезного обычно, т.е. проекты сами несерьезные, обсуждать бессмысленно. Из подобного наколенного творчества делать какие-либо выводы я бы не стал, хотя сам именно в таком режиме много чего понаделал.
Не совсем понял понял как добавление третьего поля в форму связано с серьёзностью проекта, ну да фиг с ним.
V>Дай-ка угадаю, чтобы мы этот твой аргумент (уже не первый раз тобой приведенный за последние годы, кста), "проехали", наконец. V>Ты плотно работаешь в команде не более 3-х человек?
И в таких командах мне доводилось работать тоже. Если эти 3 человека "Чаки Норисы" и смогли между собой договориться, то по эффективности такая команда может легко порвать на тряпки два десятка обычных девелоперов. Но, к сожалению, такие команды сегодня большая редкость прежде всего по причине неумения менеджментом их создавать и ими управлять. Проще нанять двадцать человек, всё по максимуму зарегулировать и после этого обозвать проект "серьёзным".
В такой команде (из 3-х человек) я работал до текущего проекта. Сейчас у меня в команде 7 или 8 (не знаю точно сколько в Индии) дотнетчиков, 5 мейнфремщиков, 5 аналитиков, пара DBA. Эффективность работы весьма низкая. Уровень дизайна и архитектуры плачевный. Сейчас мы эту ситуацию выправляем. Мне за пол года удалось отогнать от базы всех DBA и фактически узурпировать дизайн БД, полностью отказаться от спроков и прямого SQL и перевести .NET разработку полностью на linq. Сразу стало легче дышать всем. А уж как народ удивляется вдруг возросшей производительности!
V>Т.е. независимо от кол-ва людей в конторе, плотно по работе у тебя максимум пара коллег контактирует в каждом проекте. Другая организация труда тебе будет просто раздражать, ты работать по-другому не будешь и продуктивно не сможешь при всем желании.
Это не так. Мне в мою бытность контрактником доводилось работать на разных проектах. В том числе, где количество девелоперов было около 60-70-ти человек. Это был по всей видимости твой любимый тип проекта. Куча BA, архитекторов и ПМ-ов. Супердорогой проект для заказчика. Но я понимаю почему. IBM в обмен на собственный бренд и гарантии успеха раздевал заказчика практически до трусов. Это мне понятно. Но зачем раздевать до трусов самого себя я не понимаю. Поэтому, стараюсь избегать подобных проектов. Хотя похоже всё-таки опять вляпался.
V>Речь была о специфике конкретной БД. Иначе зачем нам ДБ-разраб, когда дело касалось бы "голого SQL"?
Как раз с помощью linq можно очень неплохо учитывать специфику конкретной БД. Гораздо лучше чем это делают DB-guys.
V>Косность мышления — это почти врожденное кач-во человека
Это не так. Врожденные качества человека — это максимум треть. Ещё треть — это воспитание (образование). Оставшаяся часть — окружение, в котором человек пребывал/пребывает.
У DBA очень специфическое и весьма консервативное окружение. При всей их экстравертности это окружение лекго её компенсирует и в конце концов подавляет. Ещё раз повторюсь. Худших архитекторов, чем выросших из DBA я в своей жизни не видел. При этом, подозреваю, что это как раз та лучшая часть, которая смогла в определённой степени преодолеть свою костность. На самом деле это всё легко объясняется без всякого выпендрёжа. SQL весьма специфичный и главное консервативный инструмент. А тот же C# как язык программирования общего назначения даёт программисту в руки на порядок более широкий спектр парадигм, паттернов и прочих инструментов. В результате и C# девелоперы обзаводятся более широким кругозором, разнообразными знаниями, умением видеть проблему под разными углами.
V>А я видел худшие архитектурные решения от "программистов от сохи", и?
Не спорю, криворучки везде встречаются. Но хороший дизайн от бывшего DBA — это редкое в природе и можно сказать аномальное явление, которое мне пока не посчастливилось видеть ни разу.
V>Худшие архитектурные решения получаются у людей, чей кредит доверия превышает их профессиональные навыки, а всё остальное — лирика и субъективизм. Я наблюдал, что тот же самый человек, но уже с адекватным кредитом доверия, порождает потом неплохие в итоге решения, потому что из работы выключен банальный личный снобизм. Человек был ВЫНУЖДЕН быть открытым и любопытным. Что дало требуемые плоды. Всё-таки все плохие решения идут обычно от недостатка информации и ни от чего более. (Малый опыт я не рассматриваю, бо бесполезно в этом споре)
Ты как раз зря не рассматриваешь опыт. У того же DBA опыт прежде всего однобокий, другими словами малый во многих областях. В рузультате и получаются однобокие решения.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, vdimas, Вы писали:
НС>>В BLT определенные оптимизации делаются. V>В рамках логических/арифметических выражений?
Почему такое условие? И о каких конкретно выражениях речь (в сиквеле, в отличие от универсальных языков, 3 типа выражений, а не один)?
V>>>, то бишь без "понимания" самого запроса НС>>Что такое "понимание запроса"? V>Логически дублированные/эквивалентные части вычленять, например.
Это без проблем с expression tree делается. Есть ли в конкретном провайдере такая оптимизация и насколько она вообще нужна — этот вопрос надо изучать отдельно.
V>А если используется view в запросе
Ну вот и не надо использовать view, если не нужны индексы по нему. А если индексы нужны, то и сиквел у себя уже ничего заинлайнить не сможет.
Здравствуйте, vdimas, Вы писали:
НС>>Это в C# не было. V>Это было у нас.
Пффф (С)
НС>>Ты не понимаешь что такое expression tree. V>У нас называлось SqlOrOp, SqlAddOp, SqlJoinOp. И переопределение операторов в рамках C# отчасти выручало.
Ты не понимаешь что такое expression tree. Это не просто способ конструирования дерева (тем более что дерево там совсем не 1 в 1 срезультирующим сиквелом), это еще и полная проверка компилятором, и полноценная работа всех средств анализа, рефакторинга и навигации.
V>Временная таблица уровня транзакции тебе в помощь для декомпозиции.
Во-во, вот после таких декомпозиций и начинаются жуткие тормоза. Иногда отдельные DBA так надекомпозируют, что выборка пары десятков строк занимает минуту.
НС>>Описываемые мной проблемы присутствовали без какой либо рекурсии. V>Без рекурсии не нужны были временные таблицы.
Вот я и говорю что не нужны. А были. В количестве. DBA блин, ему ж все заинкапсулячить надо в хранимки, даже то что следует делать на клиенте.
НС>>Вот только перформанс с их выкидыванием, напоминаю, улучшался в разы. V>Тут бы хотелось взглянуть на до и после.
NDA.
V> Бо эксперименты с рекурсивными возможностями показали, что особой разницы с аналогичным кодом на курсорах нет.
Нет там рекурсии. От слова "совсем".
НС>>Код LINQ запросов неизмеримо лучше поддается декомпозиции, чем императивный код на T-SQL. V>На стороне клиента. База его компилит каждый раз.
Нет, не каждый раз. Сиквел прекрасно умеет кешировать скомпилированные запросы. Причем уже давно. Это ж, блин, азы.
Здравствуйте, vdimas, Вы писали:
V>И кто тут косностью страдает? V>NoSql хорош не по этому, а потому что аппаратура позволяет отказаться от реляционки. В т.ч. быстродействующие внешние носители
Ха-ха три раза (С). Основной сценарий NoSql это кластеры, соединенные обычным ethernet и общающиеся по обычному TCP.
НС>Сто такое "синтаксис LINQ"? Если ты про query comprehension, то это не обязательная и даже не основная его часть. Я, к примеру, ей вообще не пользуюсь.
Т.е. ты не пишешь больше 3-х join-ов? Посмотри во что query comprehension разворачивается при большом количестве join-ов. Писать такое без query comprehension практически нереально.
После этого заявления возникает вопрос, у кого запросы сложные, а у кого простые...
И не надо говорить, что ассоциации решают, join-ы не только по ассоциациям бывают.
IT>Кстати, BLT и linq2db поддерживает параноидальный режим описания метаданных БД в виде интерфейсов, а не классов, что вообще искючает создание экземпляров объектов модели данных. Т.е. модель данных используется исключительно для запросов к БД.
Как в этом режиме выглядят insert и update?
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Т.е. ты не пишешь больше 3-х join-ов?
Явных? Очень редко.
AP> Посмотри во что query comprehension разворачивается при большом количестве join-ов. Писать такое без query comprehension практически нереально.
Все реально.
AP>После этого заявления возникает вопрос, у кого запросы сложные, а у кого простые...
У меня длиннее, не переживай.
AP>И не надо говорить, что ассоциации решают, join-ы не только по ассоциациям бывают.
Не только. Но так чтобы не по ассоциациям, да еще больше трех штук в одном запросе — редко.
IT>https://github.com/linq2db/linq2db/commit/c2e3e660c3ffaa7f932772c41088644060b1d6ef IT>Резултат тот же. Может у тебя не самая свежая версия. Я довно nuget не обновлял. Может в этом проблема.
Ну так разберись, где там у тебя старая версия или еще какие косяки. Я вчера сделал всё как указано на сайте проекта. Воспроизведи багу (тебе всё дали для этого) и напиши точную причину, а не гадай на кофейной гуще.
Здравствуйте, Ночной Смотрящий, Вы писали:
V>>И кто тут косностью страдает? V>>NoSql хорош не по этому, а потому что аппаратура позволяет отказаться от реляционки. В т.ч. быстродействующие внешние носители
НС>Ха-ха три раза (С). Основной сценарий NoSql это кластеры, соединенные обычным ethernet и общающиеся по обычному TCP.
Ну продолжай. В кластерах же бывают разные принципы разделения данных.
Здравствуйте, vdimas, Вы писали:
V>В тех проектах, где я участвовал и был выделенный программист БД, кол-во хранимок+сохраненных запросов было порядка 2к на примерно полторы-две сотни таблиц.
Поражаюсь твоему умению представлять худшие из преданных анафеме практик в полубожественном свете
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>>Ты не понимаешь что такое expression tree. V>>У нас называлось SqlOrOp, SqlAddOp, SqlJoinOp. И переопределение операторов в рамках C# отчасти выручало.
НС>Ты не понимаешь что такое expression tree. Это не просто способ конструирования дерева (тем более что дерево там совсем не 1 в 1 срезультирующим сиквелом), это еще и полная проверка компилятором, и полноценная работа всех средств анализа, рефакторинга и навигации.
Ага, пошли ходить зигзагами. ))
Рефакторинг работал. Параметры мы описывали как типизированные структуры/объекты, под них — ф-ии контекста. Приходилось. Собсно, сейчас описание табличных ф-ий или хранимок в дата-контексте происходит аналогично. Классика жанра, не Linq это придумал, ес-но.
Всей разницы, что мы объекты проекций описывали явно, вместо автогенерирования компилятором анонимных типов.
Собсно, и там и там основное преобразование AST->SQL. Твоё "не понимаешь, что без expression tree" и далее по тексту, показало лишь отсутствие воображения. А как вообще порождать SQL из объектной модели запроса? )) Конечно, наколотили свой аналог expression tree над выражениями SQL. Поддержали в синтаксисе как смогли через переопределенные операторы. Примерно в том виде, как ты написал, и было. Только вместо встроенных в провайдер "типизированных хинтов" была возможность приписать к каждой таблице и каждому запросу текстовые опции.
.From(db.Products + "with some option")
V>>Временная таблица уровня транзакции тебе в помощь для декомпозиции. НС>Во-во, вот после таких декомпозиций и начинаются жуткие тормоза. Иногда отдельные DBA так надекомпозируют, что выборка пары десятков строк занимает минуту.
Я такого не помню даже на Celeron-300 ))
Просто временные таблицы уровня транзакции, действительно, неплохо выручали именно для целей декомпозиции. Это же просто представления в памяти.
НС>>>Описываемые мной проблемы присутствовали без какой либо рекурсии. V>>Без рекурсии не нужны были временные таблицы. НС>Вот я и говорю что не нужны. А были. В количестве. DBA блин, ему ж все заинкапсулячить надо в хранимки, даже то что следует делать на клиенте.
Слушай, ну я такого от C# разработчиков насмотрелся за эти 10 лет, бо "порог вхождения низок", что... Ну офигенный аргумент, однако, стоит только начать обобщать среднего разработчика на сам инструмент.
НС>>>Вот только перформанс с их выкидыванием, напоминаю, улучшался в разы. V>>Тут бы хотелось взглянуть на до и после.
НС>NDA.
Та ладно... Прям маленький кусочек нельзя показать?
Объясню. С временными таблицами работали много и плотно еще во времена вторых пней. Никаких ужасов не было замечено даже на приличных выборках и алгоритмах. А уж на нынешней технике ты вообще бы разницу не заметил, по сравнению с современной формой запросов, поддерживающих рекурсию, где надобность в явно-задаваемых промежуточных данных сейчас отсутствует. Там твой сложный запрос будет компилироваться и по нему строится план дольше. Поэтому и спрашиваю.
V>> Бо эксперименты с рекурсивными возможностями показали, что особой разницы с аналогичным кодом на курсорах нет. НС>Нет там рекурсии. От слова "совсем".
Ну тогда пример нерелевантный, бо ты как аргумент решил привести чьи-то кривые руки. Нафига там были временные таблицы, тогда? А какой был уровень видимости у этих таблиц? — базы, соединения или транзакции? Тоже сильно влияет на издержки, из-за принципиально разной модели блокировок (или полного её отсутствия в последнем случае). А то мож все дело в этом, что ты банально избавился от блокировок? Чудес ведь не бывает, всему должна быть причина. Никакая пошаговая интерпретация никакой хранимой процедуры не даст тебе минуту.
НС>>>Код LINQ запросов неизмеримо лучше поддается декомпозиции, чем императивный код на T-SQL. V>>На стороне клиента. База его компилит каждый раз. НС>Нет, не каждый раз. Сиквел прекрасно умеет кешировать скомпилированные запросы. Причем уже давно. Это ж, блин, азы.
Так если он каждый раз разный у вас? В вашем контроле-гриде? ))
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Теперь введем естественное усложнение тестовой задачи:
Эксепшен тоже предполагается в SQL генерить?
myEnum == case MyEnum.Item1
? x > c1 && x < c2
: myEnum == case MyEnum.Item2
? x > c1 && x < c2*c1
: myEnum == case MyEnum.Item3
? x > c1 && x < c2%c1*17
: ???
AP>P.S. в моем подходе это реализуется естественным образом
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>>В BLT определенные оптимизации делаются. V>>В рамках логических/арифметических выражений?
НС>Почему такое условие? И о каких конкретно выражениях речь (в сиквеле, в отличие от универсальных языков, 3 типа выражений, а не один)?
О логических/арифметических, допустимых как предикат или вычислимое поле.
И хоть сколько типов выражений — это рояли не играет. Как-то с Синклером подробно уже обсуждали эту тему. В целевой РА всё-равно два типа.
V>>>>, то бишь без "понимания" самого запроса НС>>>Что такое "понимание запроса"? V>>Логически дублированные/эквивалентные части вычленять, например.
НС>Это без проблем с expression tree делается. Есть ли в конкретном провайдере такая оптимизация и насколько она вообще нужна — этот вопрос надо изучать отдельно.
Я не говорю, что expression tree тут помеха. Я говорю об эквивалентных преобразованиях выражений exists/any/some/join/select_from_subquery_with_cross_level_conditions.
V>>А если используется view в запросе НС>Ну вот и не надо использовать view, если не нужны индексы по нему. А если индексы нужны, то и сиквел у себя уже ничего заинлайнить не сможет.
Для сиквела вьюха "прозрачна", как шаблон С++ для компилятора. Т.е. он может выбрать использовать уже скомпилённый её вариант, либо просто использовать её тело как источник текстового выражения для подстановки (грубо говоря). Т.е. использование вьюхи никак не гарантирует (или ограничивает) порядок просмотра индексов и таблиц. Даже её материализация — это лишь разновидность "хинта" для построителя плана запроса, эдакий еще один индекс среди прочих в запросе.
И как, можно было решарпером переименовать поле в БД?
V>Всей разницы, что мы объекты проекций описывали явно, вместо автогенерирования компилятором анонимных типов.
При чем тут анонимные типы и проекции? Банальное выражение фильтра foo.Bar > 4 ты как записывал?
V>Конечно, наколотили свой аналог expression tree над выражениями SQL
Да я уже давно все понял про твой трехколесный велосипед. И все проблемы этого велосипеда тоже прекрасно знаю.
НС>>Вот я и говорю что не нужны. А были. В количестве. DBA блин, ему ж все заинкапсулячить надо в хранимки, даже то что следует делать на клиенте. V>Слушай, ну я такого от C# разработчиков насмотрелся за эти 10 лет, бо "порог вхождения низок", что... Ну офигенный аргумент, однако, стоит только начать обобщать среднего разработчика на сам инструмент.
А нафига мне твои теоретические идеальные DBA, если и я и IT в реальных ситуациях видим совсем другое?
НС>>NDA. V>Та ладно... Прям маленький кусочек нельзя показать?
Там немаленький кусочек.
НС>>Нет там рекурсии. От слова "совсем". V>Ну тогда пример нерелевантный, бо ты как аргумент решил привести чьи-то кривые руки. Нафига там были временные таблицы, тогда?
Так проще писать. Сложные запросы на много страниц на SQL плохо читаемы, со средствами декомпозиции бедулька, CTE больше засирает чем упрощает порой. Поэтому берут выборку, кладут во временную таблицу, и потом последовательно в несколько шагов ее ковыряют. А если там еще и пейджинг, да total к нему нужен ... Это ж до последней версии такого уродца надо было сочинять. А тут наклал все во времянку, а потом из нее нужную страничку и total выдернул.
НС>>Нет, не каждый раз. Сиквел прекрасно умеет кешировать скомпилированные запросы. Причем уже давно. Это ж, блин, азы. V>Так если он каждый раз разный у вас? В вашем контроле-гриде? ))
Разный, да не совсем. Количество вариантов в реальности сильно ограничено. А если кто сочинил что то новое — ну будет при первом запросе компиляция, не смертельно.
Здравствуйте, vdimas, Вы писали:
НС>>Почему такое условие? И о каких конкретно выражениях речь (в сиквеле, в отличие от универсальных языков, 3 типа выражений, а не один)? V>О логических/арифметических, допустимых как предикат или вычислимое поле.
Предикат и вычислимое поле — это разные типы, которые не во всех диалектах даже совместимы. И да, по предикатам оптимизации кое какие точно делаются.
НС>>Это без проблем с expression tree делается. Есть ли в конкретном провайдере такая оптимизация и насколько она вообще нужна — этот вопрос надо изучать отдельно. V>Я не говорю, что expression tree тут помеха. Я говорю об эквивалентных преобразованиях выражений exists/any/some/join/select_from_subquery_with_cross_level_conditions.
Ну и в чем, по твоему, проблема?
НС>>Ну вот и не надо использовать view, если не нужны индексы по нему. А если индексы нужны, то и сиквел у себя уже ничего заинлайнить не сможет. V>Для сиквела вьюха "прозрачна", как шаблон С++ для компилятора.
Ну так и для линка метод, возвыращающий IQueryable, тоже прозрачен, представляешь?
V> Т.е. он может выбрать использовать уже скомпилённый её вариант
Вот ты привязался к компиляции. Для современного железа, даже если закрыть глаза на кеширование, компиляция запросов особой нагрузки не создает. А с кешированием на это смело можно забить, о чем, кстати, прямо говорится в рекомендациях МС.
Здравствуйте, IT, Вы писали:
V>>В тех проектах, где я участвовал и был выделенный программист БД, кол-во хранимок+сохраненных запросов было порядка 2к на примерно полторы-две сотни таблиц. IT>Поражаюсь твоему умению представлять худшие из преданных анафеме практик в полубожественном свете
А ну да, ну да. Я ж опять забыл, куда я влез, со своим немытым...
Странно только, что все банки и все биржи именно так и работают до сих пор, и никакого линка там быть не может в принципе. А уж банков и бирж сейчас — как собак не резанных.
"Полубожественный" доставило. Но это следовало понимать не как божественный, а как "бинго!" для оппонента, от которого за версту несет "поколением next". У меня возникла догадка, она подтвердилась. Всего-то и делов. Другой мир, прям. Других слов нет.
НС>myEnum == case MyEnum.Item1
НС> ? x > c1 && x < c2
НС> : myEnum == case MyEnum.Item2
НС> ? x > c1 && x < c2*c1
НС> : myEnum == case MyEnum.Item3
НС> ? x > c1 && x < c2%c1*17
НС> : ???
НС>
О чем я и писал два дня назад, средства декомпозиции не развитые, а довольно скудные. Они приводят к неестественным извращениям над кодом. Человек воспринимает код через текст. Поэтому естественным способом декомпозиции является декомпозиция близкая к нарезке фрагментов текста. Фрагмент текста можно окружить условным оператором, выделить в метод и т.д. Это естественная нарезка текста, и именно такое предлагают большинство языков при работе с обычным кодом. В примере это продемонстрировано на IEnumerable<T>. Такое свойство хочется иметь и в коде по работе с БД. Текстовые запросы дают такое свойство. А проблемы, связанные с текстовыми запросами, оказалось можно решить без потери этого фундаментального свойства.
НС>Эксепшен тоже предполагается в SQL генерить?
Не в том направлении мыслишь, условия для генерации эксепшена не зависят от серверных данных, поэтому эти условия можно вычислять на клиенте. В этом направлении и надо было ресёчить команде, которая делала LINQ к БД. Компилятор должен специальным образом обрабатывать смесь кода, часть которого выполняется на клиенте, а часть на сервере. Довольно интересно насколько далеко можно продвинуться в этом направлении. Но они почему-то остановились в самом начале пути. И оставили нас с куцыми экспрешенами.
НС>Зато теряется в нем намного намного больше.
Ты сильно переоценивает реальные потери.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>>Почему такое условие? И о каких конкретно выражениях речь (в сиквеле, в отличие от универсальных языков, 3 типа выражений, а не один)? V>>О логических/арифметических, допустимых как предикат или вычислимое поле.
НС>Предикат и вычислимое поле — это разные типы, которые не во всех диалектах даже совместимы. И да, по предикатам оптимизации кое какие точно делаются.
Nullable булевское поле имеет тот же тип, что и предикат. И вообще, я плохо понимаю причины твоих уточнений именно этого момента.
Предикат может выглядеть как (арифметическое_выражение > @X). Левая часть пригодна для упрощений. Тот же самый механизм пойдет и на вычислимое поле, по которому идет join, например.
V>>Я не говорю, что expression tree тут помеха. Я говорю об эквивалентных преобразованиях выражений exists/any/some/join/select_from_subquery_with_cross_level_conditions.
НС>Ну и в чем, по твоему, проблема?
Я пока всё еще уточнял вопрос. Такие оптимизации делаются?
Тем более, что ты заговорил о диалектах, то бишь о ситуациях, когда не поддерживаемые в целевом диалекте SQL конструкции надо выражать через другие, так?
Просто в сиквеле-сервере дублирующие подзапросы могут схлопываться аж бегом, если эквивалентное выражено разными с-вами языка. А в движке Access или каком еще — дудки.
НС>>>Ну вот и не надо использовать view, если не нужны индексы по нему. А если индексы нужны, то и сиквел у себя уже ничего заинлайнить не сможет. V>>Для сиквела вьюха "прозрачна", как шаблон С++ для компилятора.
НС>Ну так и для линка метод, возвыращающий IQueryable, тоже прозрачен, представляешь?
Нет, не прозрачен, если содержит маппинг на вьюху. Тело этой вьюхи не прозрачно для клиентской стороны и оптимизациям не подлежит. См исходный умозрительный пример.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>Покажи пример где EF последней версии генерит неэффективный запрос.
IB>
IB> Order[] orders = context.Set<Order>().Include( o => o.Products).ToArray();
IB>
IB>Генерится SQL, который в два раза менее эффективен, чем генерил в свое время linq2SQL. И это один из наиболее частых сценариев, то есть это приговор инструменту...
А ты что с чем сравниваешь? Мапить many-to-many никто кроме ef не умеет, поэтому даже сравнить не с чем...
Перепиши с промежуточной таблицей\классом проблем не будет, делает красивые inner join.
IB>А знаешь почему запрос такой тормозной и они так и не поправили его за пять лет? Потому что для корректной работы маппинга EF через внутреннюю модель, нужно сгенерить дополнительный столбец, по которому не построишь индекс, а потом еще и отсортировать по этому столбцу. IB>То есть нельзя просто взять и поправить генерацию запросов для сценария потомок-родитель — нужно переделывать всю архитектуру генерации запросов. А эта архитектура, в свою очередь, явилась следствием дурацкой идеологии. IB>Как видишь, иногда полезно все-таки понимать изначальную идею решения и оценивать ее адекватность, а не бросаться сразу осваивать все что предложили.
По странному стечению обстоятельств именно эта кривая архитектура\идеология позволяет мапить many-to-many
Здравствуйте, vdimas, Вы писали:
V>>>В тех проектах, где я участвовал и был выделенный программист БД, кол-во хранимок+сохраненных запросов было порядка 2к на примерно полторы-две сотни таблиц. IT>>Поражаюсь твоему умению представлять худшие из преданных анафеме практик в полубожественном свете
V>А ну да, ну да. Я ж опять забыл, куда я влез, со своим немытым...
Ну так помой. А то нимб с немытым не очень сочетается
V>Странно только, что все банки и все биржи именно так и работают до сих пор, и никакого линка там быть не может в принципе. А уж банков и бирж сейчас — как собак не резанных.
Это не делает чести ни банкам, ни биржам. Местами они так, конечно, работают, но видно невооруженным взглядом, что очень плохо работают, медленно и неэффективно. По мере сил мы эту ситуацию меняем и надо признать не без успеха.
V>"Полубожественный" доставило. Но это следовало понимать не как божественный, а как "бинго!" для оппонента, от которого за версту несет "поколением next". У меня возникла догадка, она подтвердилась. Всего-то и делов. Другой мир, прям. Других слов нет.
Ты считаешь, что лучше, когда от тебя за версту несёт нафталином и гниловатым запахом разлагающихся технологий? Прямо некрофилизм какой-то. Фу. Ужас.
Если нам не помогут, то мы тоже никого не пощадим.
D>Я, увы, не настолько хорошо знаю C# и совсем не знаю EF/NHibernate, чтобы понять, что делает этот код.
Делает он то же самое, что вот этот old-school вариант:
var messageInfo = Query<IMessageInfo>.New(new {id}, @"
SELECT f.ShortName ForumShortName, m.CreatedOn, m.Subject, a.Origin
FROM Message m
JOIN Forum f ON f.Id = m.ForumId
OUTER JOIN Account a ON a.Id = m.AccountId
WHERE m.Id = @id AND f.ReadLevel <= @Account.AccessLevel
").SingleOrDefault();
return messageInfo == null
? ErrorMessageBox("Сообщение не найдено")
: View(new MessageModel(id, messageInfo, FormatMessageBody(id, messageInfo.Origin)));
Здравствуйте, vdimas, Вы писали:
V>Nullable булевское поле имеет тот же тип, что и предикат.
Нет. "WHERE tbl.BoolField" в большинстве диалектов написать нельзя, только "WHERE tbl.BoolField = 1".
V> И вообще, я плохо понимаю причины твоих уточнений именно этого момента.
Потому что обрабатываются разные типы обычно существенно по разному.
V>>>Я не говорю, что expression tree тут помеха. Я говорю об эквивалентных преобразованиях выражений exists/any/some/join/select_from_subquery_with_cross_level_conditions. НС>>Ну и в чем, по твоему, проблема? V>Я пока всё еще уточнял вопрос. Такие оптимизации делаются?
Я же ответил — не знаю, надо специально уточнять для конкретных провайдеров. Принципиальных проблем нет.
НС>>Ну так и для линка метод, возвыращающий IQueryable, тоже прозрачен, представляешь? V>Нет, не прозрачен, если содержит маппинг на вьюху.
Цитирую сам себя: "Ну вот и не надо использовать view".
Здравствуйте, Alexander Polyakov, Вы писали:
AP>О чем я и писал два дня назад, средства декомпозиции не развитые, а довольно скудные.
По сравнению с SQL на три головы выше.
AP> Они приводят к неестественным извращениям над кодом.
Что в приведенном мной коде неестественного?
AP>Поэтому естественным способом декомпозиции является декомпозиция близкая к нарезке фрагментов текста.
Ложное утверждение. Особенно когда куски приходится параметризовать. И в случае таких нарезок твой статический чекер идет лесом, так как запрос собирается динамически.
AP> Фрагмент текста можно окружить условным оператором, выделить в метод и т.д. Это естественная нарезка текста
Текста — может быть. А декомпозированный SQL запрос, на практике, в 99% случаев собирается склеиваиванием датасетов и дописыванием в предикаты по AND. Для всего этого возможностей выражений в C# за глаза.
Ты же пытаешься вытащить какие то экзотические случаи, которые не в кажом проекте вообще бывают, и на основании этого заявить, что это все хуже чем фатальнейший прощелк с девэкспириенсом в твоей библиотечке, вылазящий строго на каждом запросе строго при каждой его модификации.
А обоснование я увидел ровно одно — личне тебе некомфортно не видеть SQL. Браво, чо.
НС>>Эксепшен тоже предполагается в SQL генерить? AP>Не в том направлении мыслишь
AP>, условия для генерации эксепшена не зависят от серверных данных, поэтому эти условия можно вычислять на клиенте.
А это неважно. Наложение эксепшена на ленивое функциональное выражение — жестяная жесть. Такой код должен приводить только к ошибке при компиляции запроса.
НС>>Зато теряется в нем намного намного больше. AP>Ты сильно переоценивает реальные потери.
Или ты их недооцениваешь. Хотя фик тебя знает, может у тебя в качестве IDE какой нибудь Far или древняя студия без решарпера. Тогда тебя можно понять.
Здравствуйте, Dair, Вы писали:
D>Я, увы, не настолько хорошо знаю C# и совсем не знаю EF/NHibernate, чтобы понять, что делает этот код.
SQL, надеюсь, понимаешь?
SELECT TOP 1
f.ForumShortName, m.CreatedOn, m.Subject, a.Origin, mt.Text
FROM Messages m
JOIN Forums f ON f.ID = m.ForumID
OUTER JOIN Accounts a ON a.ID = m.AccountID
JOIN MessageTexts mt ON mt.ID = m.ID
WHERE m.ID = @id AND f.ReadLevel <= @accessLevel
Приведенный код открывает коннект к БД, выполняет этот sql с передачей значений двух параметров, читает результат. Если записей нет — возвращает null, если есть — создает и заполняет данными экземпляр класса MessageModel (при этом вызывается функция FormatMessageBody с частью полей результата) и возвращает этот экземпляр. При этом все типы в запросе, его параметрах и результате контролируются комспилятором.
Теперь понятно?
AP>> Они приводят к неестественным извращениям над кодом. НС>Что в приведенном мной коде неестественного?
Запись switch через оператор '?'. Зачем придумали switch он не нужен, ага?
AP>>Поэтому естественным способом декомпозиции является декомпозиция близкая к нарезке фрагментов текста. НС>Ложное утверждение. Особенно когда куски приходится параметризовать.
Ты прочитал невнимательно, слово "близкая" пропустил.
НС>И в случае таких нарезок твой статический чекер идет лесом, так как запрос собирается динамически.
Это ложь! Просто нет слов! После нескольких десятков постов выясняется, что ты ничего не понял. Просто ничего, ни капли. Даже не пытался понять.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>Даже банальная математика говорит что при 2к хранимок и 200 таблиц это минимум 10 хранимок на таблицу, а скорее всего в два раза больше. Любая правка в исходной таблице — нужна синхронная правка около 20 хранимок. Команда из 3-4 программистов будет поля править раз в день, DBA от такого сдохнет.
V>Во-во, и после этого ты еще поучаешь коллег.
После чего?
V>Все запросы всей базы верифицируются после изменений.
Кем? и зачем?
G>>При этом Linq позволяет генерировать больше и более специализированные запросы, чем выделенный DBA.
V>Ты плохо представляешь себе работу DBA. В 90% случаев от "слепит" тебе результат из уже готовых view, табличных ф-ий или уже готовых SP.
Это ты плохо представляешь.
Типичная проблема. Надо сделать функцию с параметром. Если параметр null, то надо вернуть все записи, у которых поле — null. Если поле не null, то нужно использовать предикат.
DBA может пойти двумя путями:
1) Сделать две функции, одну для null, другую для не-null и выбирать на строне приложения
2) Написать универсальную функцию, примерно так:
CREATE FUNCTION [dbo].[Function]
(
@shipDate datetime
)
RETURNS TABLE AS RETURN
(
SELECT * from Transactions t
where t.ShippedDate = @shipdate or (@shipDate is null and t.ShippedDate is null)
)
Использовать IF или клеить строки на стороне базы не рассматриваем, ибо контекст теряется запроса.
Естественно 99% DBA выберут второй варинат, ибо они — люди, и чем меньше им поддерживать, тем лучше.
Программисты потом напишут один вызов:
select ... from Function(@p)
План для этого запроса закешируется и дальше происходят неприятные вещи.
Оказывается что null селективность низкая и SQL использует scan. А для конкретного значения селективность высокая и стоит использовать seek. Но план запроса кешируется при первом вызове и если первый был вызов был с параметром null, то SQL всегда будет делать scan. Это называется Parameter Sniffing Problem (PSP).
Чтобы такого не было вешают хинт — OPTION(RECOMPILE) и SQL начинает перекомпилировать план на каждый запрос.
Если такой запрос выполняется часто, то SQL большую часть времени начинает компилировать запросы.
Тогда DBA делает хранимку, которая внутри делает склейку строк с учетом проекций, постраничного разбиения и подобных вещей, а потом мучительно её поддерживает, потому что нет способов валидировать динамические запросы внутри SQL.
В этом случае Linq генерит разные запросы когда параметр null и когда не-null. Это значит что PSP больше не наступает.
V>У грамотного разработчика большое повторное использование кода. Соответственно его вариант будет намного-намного проще твоего, построенного на Linq с 0-ля.
Внезапно в Linq гораздо проще делать декомпозицию. См выше.
V>Я говорил про вид запросов. Одно и тоже сложное выражение можно вертеть многими способами. На Linq это банально неудобно, т.к. не очевидно. Например, очередность и взаимная вложенность подзапросов запросто может зависеть от конкретного провайдера, порождающего код SQL.
SQL сам (пере)упорядочивает inner join и эквивалентные ему подзапросы.
В случае внешних джоинов от порядка зависит результат и все известные мне linq-провайдеры делают джоины ровно в том порядке, в котором укажешь в коде.
V>А рассуждения из цикла "MS SQL умный и сам составит нужный план" — и есть детсад. Это только на относительно несложных запросах.
Это на любых запросах. Механизм работы оптимизатора не отличается.
V>Вложи 3 раза exists/any друг в друга и получишь, что вертя внешней формой одного и того же запроса будешь менять конечный план.
Это ни о чем. Приводи запрос и план, будем смотреть.
V>С любыми запросами на групповое обновление — беда. А их бывает дохрена в учетных системах. Linq тебе поможет в обновлении только пообъектно, то бишь построчно. Хаха, как грится. https://github.com/loresoft/EntityFramework.Extended#batch-update-and-delete https://github.com/linq2db/linq2db/blob/master/Source/LinqExtensions.cs (см методы Delete и Update)
G>>Что ты считаешь "плохим" SQL и почему Linq его генерит сам? V>Потому что программист борется за лучшую читабельность, вестимо. Это же на уровне мозжечка, на то он и программист. А по закону подлости, наилучшим образом читаемый Linq-запрос не всегда самый лучший.
Еще раз: что ты считаешь плохим SQL?
V>>>Куда тянется? Если это внутренний подзапрос, то ничего никуда не тянется. G>>С чего ты взял? От проекции в запросе (неважно подзапрос это или нет) зависит какой план построит SQL, а это напрямую влияет на быстродействие. Конечно кроме случаев, когда ты используешь подзапрос в exists выражении.
V>Да любой подзапрос, если его поля используются только для построения условий на других уровнях — там вовсе не надо указывать никакие проекции, "унутре" всегда читается строка в ОП целиком (кроме тех самых блобов и text), бо MS SQL хранит построчно.
Ты про индексы в курсе? SQL может не читать данные таблицы вообще, только индекс.
А еще есть columnstore индексы...
V>Да. Серьезные приложухи на стороне базы — это ад для современных программистов. Это и так известно. Но выхода не было, по тем ресурсам аппаратуры, что были еще до времен MS SQL 2005. Сейчас то же самое с той лишь разницей, что эта граница отодвинулась примерно в 5 раз. Но она не исчезла. Просто да, многие нагрузочные раньше приложения стали простыми с т.з. требуемой мощности. Но далеко не все. Серьезные по размерам базы всё так же обслуживаются DBA по-старинке, я знаю это их первых рук, как грится.
Во первых это не значит что это хорошо. Во вторых причины скорее исторические, чем объективная необходимость.
V>>>Опять же. Есть такой фактор — владение проблемой. Когда программист SQL пишет запросы, он "видит" происходящую картинку. Именно так. Нет эдакого "разрыва" кода и базы. Просто индексы, статистику, материализцию view и прочее — такие решения принимает человек, который в этом "варится". А программист C# в этом не варится нифига, что бы кто не говорил. G>>Проблема в том, что "картинка" которую он "видит" может с реальным потребностями и проблемами расходиться. Именно так часто и получается. V>Бла-бла-бла. Реальную картинку даешь не ты, мега-программист, а характер самих данных и конечно статистика. Но её тоже надо уметь читать и понимать.
Наиболее реальной картиной обладает тот, кто делает UI или Public API системы. Если дать ему формировать запросы с помощью linq и научить как правильно это делать, то DBA много нового узнает о системе. Видел это вживую.
V>Клинические они по самому сценарию. Вот тебе идёт обновление одной и той же немалой таблицы тысячи раз в секунду и десятки тысяч раз — запросы из неё. Хоть ужом извернись, но без ручного ковыряния хинтами ты нормально ничего не сделаешь. Часто таблицу разбивают на 2, а то и 3: актуальные (наиболее меняющиеся) данные, реже меняющиеся, исторические. Иногда делят домены на поддомены и т.д. и т.п.. И периодически перемещают данные м/у таблицами. И для разных операций разные уровни блокировки.
Чушь какая-то. Если одновременно много записей и чтений нужно:
1) Сделать для чтения покрывающие индексы, чтобы весь запрос отдавался через index seek
2) Сделать stagingtable, без индексов, куда будут все писать, желательно с низким уровнем изоляции
3) Повесить на sqlagent задачу раз в интервал переносить данные stagingtable в основную таблицу одним insert select
4) Пересчитывать статистику по индексам когда нагрузка минимальная
Конечно если запросы делаются через хранимки, то так не получится.
G>>EF кстати генрит базы с READ_COMMITED_SNAPSHOT, так что блокировки, скорее всего, не станут проблемой.
V>Для батча с построчным изменением нескольких объектов? Ню-ню...
Да, для него тоже.
V>Ты хоть знаешь, что еще лет 10 назад за подобное любой вменяемый DBA тебя просто расстрелял бы? ))
10 лет назад в SQL Server не было SNAPSHOT, а в Oracle только он и есть с первых версий.
V>При небольшом кол-ве построчных изменений, всё можно вложить в один запрос обновления, а не в батч, где каждый раз идет скан по таблице. Один скан на 3 ключа дешевле, чем три скана на один ключ. Хотя итоговая "математическая" сложность эквивалентна. Но вот подиж ты.
Какой скан, ты о чем? Мы все еще о SQL Server?
Что такое скан на три ключа?
V>>>Ну и "длинные транзакции" всё-равно на стороне базы исполняются на многие порядки быстрее (с тащтельно подобранными уровнями блокировки), чем последовательность вызовов Linq с клиента базы в рамках одной транзакции. От этого ты вообще никак не убежишь. G>>"Длинные транзакции" это что? V>Это начало транзакции, более одной операции, конец транзакции.
G>>Если у тебя один селект работает полчаса это длинная транзакция? V>Это идиотизм даже по меркам 10-тилетней давности. А уж на нынешних мощщах за это кастрировать надо. Чтобы не портить общечеловеческий генофонд. Я тут ему про актуальные/исторические данные распинаюсь, про поддомены, а он мне селект на пол-часа.
так это является "длинной транзакцией"?
G>>А 1000 инсертов за секунду, отправленных одним батчем? И то и другое вполне может быть сделано как Linq, так и написано вручную. V>Тупые 1000 инсертов за секунду позволял сервак на Pentium-III в своё время.
А это является "длинной транзакцией"?
V>>>Триггера те же и т.д. V>>>Понимаешь, все эти триггера, длинные транзакции и прочее используют какую-то кодовую базу SQL, которая УЖЕ есть на стороне базы. Смысл её дублировать в Linq? G>>А кто говорит что надо дублировать? Типичное распределение чтения\записи в веб-приложении — 98\2. Об оптимизации записи речи в этом плане не идет.
V>>>Есть мильон служебных хелперов, и? Эти хелперы связаны с состоянием базы. Ты чуть подмандил свой запрос, и твой вызванный ранее plan guide стал бесполезен. Или ты каждый раз перед целевым запросом будешь настраивать plan guide? G>>План-гайд или хинты для каждого запроса — индикатор неграмотного DBA. В базе много средств построения оптимальных планов без хинтов. Увы не все это знают. linq в этом плане помогает, ибо не дает писать хинты.
V>Ясно. Этот вопрос ты решил тщательно замылить. V>Ты мне конкретный сценарий дай. Вот у меня идёт постоянная и одновременно частое обновление на таблице — регистре остатков. Частоту я тебе уже приводил. Без хинтов блокировок там ловить нечего. Просто поверь. Не работает.
1) Поставь READ_COMMITED_SNAPSHOT.
2) Сделай материализованное представление для остатков.
3) Сделай хорошие проекции.
4) сделай покрывающие индексы.
Хинты блокировок это от незнания.
V>Я одно не понимаю! Какое нафиг отношение к нашему обсуждению имеют ГЛОБАЛЬНЫЕ настройки базы (типа твоего read_commited_snapshot), когда речь о тюнинге конкретных запросов? Этих глобальных настроек многие десятки и что с того?
А ты попробуй почитать что означает read_commited_snapshot.
V>Я не увидел удобного сценария, как тюнить хинтами запросы в Linq, кароч.
План-гайды
V>>>Про impendance mismatch я вообще молчу. С грамотным DBA я наблюдал ровно противоположное — у всех всё выспросит, заставить оформить требования, ни байта лишнего из базы не отдаст. G>>Теоретически такое может быть, но сильно удлиняет цикл разработки и повышает нагрузку на этого самого DBA. V>Дык, у него ЗП не меньше, чем у программиста. Каждый пусть занимается своим делом.
А какой смысл в этом?
V>>>Про количество хранимок и вьюшек я написал выше. Я сразу в твоих аргументах ощутил специфический опыт, когда разработка на стороне базы фактически отсутствовала. ОК! В условиях объективной невозможности вести разработку на стороне базы, Linq тебе в помощь. G>>С чего ты взял что отсутствовала?
V>Ну или опыт был печален. Блин, с вами линоководами смешные разговоры выходят. Как послушаешь вас, так до Linq ни одного приложения на БД толком не взлетело и это идёт как основной аргумент. Ребят, это у ВАС не взлетело. А весь мир давно успешно пользуется базами без Linq. Например, ни в один банк ты со своим Linq не сунешься, кроме как для маргинальной неспешной аналитики под прихоть и ответственность какого-нить старшего менеджера. В рабочий процесс ЭТО не пустят на сегодня. Таковы реалии.
С чего ты взял? Взлетало и без linq, но больше времени на это уходило.
V>>>Правда, и до Linq был тот же Hibernate/NHibernate со своим построителем запросов. )) G>>там постритель запросов с трудом осиливает джоины и предикаты. Подзапросы и проекции — жопа. V>Нормально он осиливает. Если пользоваться в синтаксисе "объектного построителя" как мне тут рядом давали для демонстрации прикрепления хинтов, то точно так же всё.
Ну покажи как подзапрос сделать в CriteriaAPI.
V>Да не в этом дело. А в том, что когда вся база легко садится в ОП сервака, то наш разговор теряет смысл сам собой. И вообще становится дичью, бо надобность реляционки в таком сценарии сильно под вопросом.
Гарантировать что БД всегда влезает в память довольно сложно.
G>>>>Лет 7-8 назад такое было повсеместно, потом появился Linq и больше C# программистов стало понимать что происходит в базе и как сделать оптимальной работу с СУБД. G>>>>Но тебя это, видимо не коснулось. Не беспокойся, еще не поздно изучить.
V>>>Что ИМЕННО надо изучить? G>>Как работает SQL.
V>Давай конкретней. Особенно про момент, когда программист Linq волшебным образом начинает БОЛЬШЕ ПОНИМАТЬ, что происходит в базе.
V>>>И КАК C#-программист начнет понимать происходящее в базе, особенно, если разные программисты разрабатывают разные абстрактные предикаты, из которых собирается целевой запрос "кем-то еще"? Даже по неизвестной заранее таблице? Как преодолеть ту пропасть между мышлением "типами" у программиста и "доменами" у DBA? )) G>>Изучать и SQL, и C#. V>Это не ответ на выделенное. Ты хоть вопрос понял?
Это именно ответ на выделенный вопрос.
V>>>Нет, не динамические. Подготавливается заранее view, скрывающий всю сложность низлежащего запроса, а уже на результат можно накладывать сортировку и фильтрацию. View делается DBA, конкретный тупой SQL-запрос к этому view пишет программист. Но он же тривиальный, много ума не надо, бо по специально заточенному view идёт тупой "select * from ... where ... order by ...". G>>так where и orderby каждый раз будут разными, это все равно не динамический запрос? V>ОК, динамический. Но недостойный ни внимания, ни обсуждения.
Почему?
V>Просто, действительно динамически в моей практике строили запросы только с изменяемой структурой. А описанный сценарий требует лишь однажды написанной вьюшки на стороне базы. Пусть эту вьюшка будет унутре сколь угодно сложной, но прилепить условия и сортировку к ней можно задешево без всяких Linq.
Так что такое "динамический запрос"?
G>>>>Что ты имеешь ввиду под динамическими запросами?
V>>>С динамической структурой, затрагивающей подзапросы. Т.е. где в условиях идут еще выборки или групповые операции над ними, типа exists, any и т.д. из этой оперы. С перекрестными связями по-условию м/у подуровнями — прикольнее всего. )) G>>А чем такие запросы в принципе отличаются от "select * from .. where ..." где предикаты формируются в UI (с точки зрения SQL)? V>Чем сложнее тело вьюшки, тем более больше отличий, вестимо. V>Ты всерьез спрашиваешь или как? ))
Серьезно спрашиваю, ибо алгоритмы SQL не отличаются в этом случае.
V>>>Это список полей статичный, а запрос к базе может быть очень даже динамичным в том смысле, что я написал выше. G>>Увы, не могу понять твое определение динамичности. Для SQL это такой же запрос.
G>>>>Давай по порядку: что ты называешь динамическими запросами?
V>>>Ну я заведомо исключил из них те, где меняются простые параметры, бо для ТАКИХ сценариев вообще Linq не облокотился и обсуждать сразу нечего. V>>>Я рассматриваю те сценарии, где Linq еще хоть зачем-то нужен, например, если ты заранее не знаешь, какой будет конечный join. G>>Что значит "заранее не знаешь" ?
V>Ну вот так. Добавил сравнение со статистикой — вот тебе лишняя операция реляционной алгебры (всё-равно все подзапросы, а так же exists/any/all/some и т.д. идут унутре через разновидности джоинов). Добавил сравнение в другим элементом, встречающимся в другом поддомене — вот тебе дополнительный джоин на другую таблицу.
И что? Для SQL какая разница? Он по одному и тому же алгоритму план строит, независимо от количества джоинов.
G>>Чем такая штука принципиально отличается от грида с настраиваемыми сортировками? (опять же с точки зрения SQL). V>Тем, что для грида можно написать низлежащую вьюшку лишь однажды.
И как это отразится на работе SQL Server? Он планы по-другому делать будет?
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Т.е. ты сам себе ПМ, аналитик, архитектор и тот самый Вася, если тебе через 10 мин (!!!) потребовалось третье поле. )) G>>Как это связано? Чтобы добавить поле нужен аналитик, архитектор и еще кто-то?
V>Ха-ха три раза. V>Сначала код, так? V>Например, для среднеразмерной складской программы?
Почему бы и нет? У тебя с этим проблемы?
G>>Вот и получается, что DBA с посредственными навыками получают слишком большой кредит доверия. G>>Кстати по этой же причине последние годы появилось повальное увлечение NoSQL базами. Они банально проще и работа с ними более прямолинейна.
V>И кто тут косностью страдает? V>NoSql хорош не по этому, а потому что аппаратура позволяет отказаться от реляционки. В т.ч. быстродействующие внешние носители, а не только размер ОП. Сдаётся мне, ты фундаментально не понимаешь происходящих процессов.
При чем тут внешние ностели? В большинстве NoSQL баз производительность падает до неприличных значений когда БД перестает влезать в ОП.
А SQL умудряется вполне достойно работать на базах объемами в сотни раз превышающими ОП на том же железе.
Но для большинства программистов разница SQL или NoSQL как раз в том как с базой работать. NoSQL предлагает самый прямолинейный подход — сериализация объектов целиком, даже думать не надо, просто вызвал Save и все. Проблемы начинаются когда данные оказываются сильно связанными, присутствуют циклы в связях. Тогда NoSQL предлагает такой же прямолинейный подход — тяни все объекты и делай join руками или делай индекс и напрямую к индексу обращайся. SQL все это делает внутри, далеко не очевидным образом, что и вызывает проблемы у программистов.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
IT>За громоздкую и никому не нужную архитектуру. За тормоза. За кривой SQL.
Какой-то неуловимый джо...
IT>За кривой маппинг, вспомним маппинг энумераторов.
А конкретнее?
IT>За бестолковые решения, делающие некоторые фичи совершенно бесполезными.
Кому-то это мешает, кроме самих разработчиков ef?
IT>Возьмём тут же студию или WPF, которым стало можно пользоваться лишь после того, как его стали применять в студии.
Логично, пользователей новых технологий MS как-то совсем мало. Хайп гораздо больше, чем реальных применений.
EF только последний год начал применяться и то не за счет мапинга или Linq, а за счет задрачивания под конкретные сценарии.
IT>
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Запись switch через оператор '?'. Зачем придумали switch он не нужен, ага?
Затем что switch в C# придумали хреново, не включая моск. Поэтому он не может быть выражением. Надо доделывать язык. Я с Мэдсом на эту тему говорил, он полностью согласен, и даже что то в этом направлении они уже ковыряли. Но это уже другая тема.
НС>>И в случае таких нарезок твой статический чекер идет лесом, так как запрос собирается динамически. AP>Это ложь! Просто нет слов! После нескольких десятков постов выясняется, что ты ничего не понял. Просто ничего, ни капли. Даже не пытался понять.
Кто то что то там заливался про эмоции . Выключай истерику и включай моск.
Это — правда. Как только ты вместо своего творчества на тему query builder начнешь клеить строки, так твой статический анализатор сразу идет в лес. А если спецфункцию изобретать для свитча — так и для LINQ тоже можно добавить функцию, с сохранением всех пряников от наличия expression tree, в отличие от.
IT>linq провайдер должен сам разобраться и построить правильный SQL.
Спорно. Провайдер не должен умствовать в таких местах — иначе как я построю запрос "верни мне все накладные, где ShippedDate не задано"?
Здравствуйте, Alexander Polyakov, Вы писали:
IT>>Тебе знаком такой термин — рефакторинг базы данных? Нет? AP>Рефакторинг БД приходилось делать.
IT>>... предоставляют 100%-ный контроль над кодом, работающим с БД. AP>Именно для этих целей и были сделаны методы CheckAllQueries и FindUsages(tableName, columnName=null). CheckAllQueries автоматически генерирует тесты для всех вариантов всех запросов (запуская их в режиме SchemaOnly).
Интересно. А как происходит генерация вариантов параметров запроса?
Как разруливаются ситуации с декомпозированными запросами, т.е. когда тело собирается кодом, расположенным в разных методах?
Как разруливаются ситуации с декомпозицией "поперёк" границы сборок?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
IT>>linq провайдер должен сам разобраться и построить правильный SQL. S>Спорно. Провайдер не должен умствовать в таких местах — иначе как я построю запрос "верни мне все накладные, где ShippedDate не задано"?
linq2db такое генерит когда dateTime == null. Для EF нужно руками разные запросы на null и не-null делать.
S>А вот раскрывать выражения на клиенте — можно: S>
Здравствуйте, Sinclair, Вы писали:
S>Спорно. Провайдер не должен умствовать в таких местах — иначе как я построю запрос "верни мне все накладные, где ShippedDate не задано"?
Непонятна суть претензий. Так и построишь — передашь null в качестве значения dateTime. То что в сиквеле для сравнения с null требуются отделльные операторы — злобный и неисправимый косяк.
S>А вот раскрывать выражения на клиенте — можно: S>
Здравствуйте, gandjustas, Вы писали: G>В таком условии если dateTime==null, то запрос должен вернуть все записи.
А, виноват — неверно прочитал условие. Тут, конечно же, провайдер должен аккуратно обрабатывать такие ситуации.
Я, по привычке, ожидал стандартного where ShippedDate == @dateTime or @dateTime is null, который до сих пор плохо оптимизируется SQL-серверами.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Непонятна суть претензий. Так и построишь — передашь null в качестве значения dateTime. То что в сиквеле для сравнения с null требуются отделльные операторы — злобный и неисправимый косяк.
Перепутал задачи
S>>А вот раскрывать выражения на клиенте — можно: S>>
НС>Чем это лучше "t => (t.ShippedDate == dateTime.Value || dateTime == null)"?
Этого — ничем. Это лучше where t.ShippedDate = @dateTime or @dateTime is null в SQL, т.к. сиквел-сервер не занимается partial evaluation, constant propagation и прочими мелочами, привычными для обычных ЯП.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Я, по привычке, ожидал стандартного where ShippedDate == @dateTime or @dateTime is null, который до сих пор плохо оптимизируется SQL-серверами.
Так в этом, собственно, и был смысл примера — показать почему LINQ способен более эффективные запросы делать, нежели вьюшки или хранимки.
G>Насчет "путь в никуда" — очень даже ясно куда — EF7.
То что lightweight ORM, коим и должен быть EF7 путь в куда, твердили много лет назад. Но кто-то очень упертый отказывался признавать, что EF6 путь в никуда, и продолжал накручивать этого уродца с упорством достойным иного применения. Наконец-то уже и до разработчиков дошло (либо их просто сменили на адекватных)... Один ты, похоже, остался
G>Upgrade from EF6 to EF7 is a key scenario for us, both in terms of existing code and existing knowledge. We’ll be keeping the same concepts and patterns wherever it makes sense. The upgrade to EF7 will require some changes to your code. Our aim is that code that uses the core functionality of the DbContext API will upgrade easily, code that makes use of the lower level APIs in EF may require more complicated changes.
"Конечно же переход на EF7 — это ключевой сценарий для нас. Поэтому мы постараемся сохранить ту же концепцию и паттерны, там где это имеет смысл. Переход, конечно же, потребует некоторых изменений в вашем коде. Наша задача, чтобы ваш код, который использует ключевую функциональность пострадал меньше всего..."
Таким образом, переводя с политкорректного на разговорный — ребята даже не планируют толком API сохранять. Прекрасный путь в куда — удачи товарищи! =)
G>Но я понимаю что все факты расходятся с твоей верой, поэтому ты ищешь проблемы в других.
Ты сам-то понял какие факты привел? =))
Здравствуйте, gandjustas, Вы писали:
G>А ты что с чем сравниваешь? Мапить many-to-many никто кроме ef не умеет, поэтому даже сравнить не с чем...
Причем тут many2many? Это банальная связь один ко многим. Есть класс Order, который содержит набор товаров Product.
Отдельна жопа в том, что свойство Product обязательно должно быть ICollection<Product>, никаких тебе IEnumerable<> или Product[]. Хорошо хоть от virtual избавились, но не сильно спасает. Это все к вопросу о кривой концепции — когда EF делали, считали что LazyLoading это основной сценарий и все дизайнили под него, вот до сих пор хвосты и торчат.
G>Перепиши с промежуточной таблицей\классом проблем не будет, делает красивые inner join.
Не нужна здесь промежуточная таблица. На linq2SQL я могу сделать так:
context.GetTable<Order>().GroupJoin(
context.GetTable<Product>(), o => o.Id, p => p.OrderId,
(o, p) => new Order
{
Id = o.Id,
UserID = o.UserId,
Products = p.ToArray()
}).ToArray();
Или вообще в лоб:
context.GetTable<Order>().Select(
new Order
{
Id = o.Id,
UserID = o.UserId,
Products = context.GetTable<Product>().Where(p=>p.OrderId==o.Id).ToArray()
}).ToArray();
И в обоих случаях будет один и тот же SQL запрос, в два раза эффективнее чем в EF, просто потому что там не будет дополнительного искуственного столбца и сортировки по нему.
И, что характерно, никаких ограничений на POCO классы — ему совершенно пофиг на что мапить, лишь бы тип подходящий был.
А EF так не умеет — не позволяет его хитропридуманная модель. Все запрос в таком стиле генерят исключение о невозможности построить linq выражение — что логично, нельзя править напрямую значения классов в обход внутренней модели. Конечно пользователь ее не видит, но палки в колеса она ставит на каждом шагу.
И это инструмент, который "идеально решает задачи для которых он делался"? Не смеши меня.
G>По странному стечению обстоятельств именно эта кривая архитектура\идеология позволяет мапить many-to-many
Многие ко многим мне нужно раз в год, по обещанию, как-нибудь ручками напишу. А вот запросы с left join у меня через один и если инструмент не может делать их эффективно, то он идет на свалку.
это к вопросу о "many seldom used features and capabilities in the code base that hamper performance and complicate development".
Здравствуйте, IB, Вы писали:
IB>Или вообще в лоб: IB>
IB> context.GetTable<Order>().Select(
IB> new Order
IB> {
IB> Id = o.Id,
IB> UserID = o.UserId,
IB> Products = context.GetTable<Product>().Where(p=>p.OrderId==o.Id).ToArray()
IB> }).ToArray();
IB>
IB>И в обоих случаях будет один и тот же SQL запрос, в два раза эффективнее чем в EF, просто потому что там не будет дополнительного искуственного столбца и сортировки по нему.
Прикольно!
А можешь показать, какой SQL генерится в том и том случаях?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Ночной Смотрящий, Вы писали: НС>Так в этом, собственно, и был смысл примера — показать почему LINQ способен более эффективные запросы делать, нежели вьюшки или хранимки.
Да. По факту, есть всего три способа работы с "динамическими" запросами:
1. Кодируем всё в SQL. Нет такого запроса, который нельзя было бы выразить в терминах SQL:
select * from orders where (ShippedDate >= @shipDateFrom or @shipDateFrom is null) and (ShippedDate <= @shipDateTo or @shipDateTo is null)
1.а. Используем процедурное расширение SQL:
if (@shipDateFrom is null)
begin
if (@shipDateTo is null)
select * from orders
else
select * from orders where ShippedDate <= @shipDateTo
end
else begin
if (@shipDateTo is null)
select * from orders where ShippedDate >= @shipDateFrom
else
select * from orders where ShippedDate >= @shipDateFrom and ShippedDate <= @shipDateTo
end
2. Клеим строку динамически. Не очень важно — внутри SQL или снаружи:
q = 'select * from orders where 1=1 '
if (@shipDateFrom is not null)
q = q + 'AND where ShippedDate >= @shipDateFrom '
if (@shipDateTo is null)
q = q + 'AND ShippedDate <= @shipDateTo '
exec(q, @shipDateFrom, @shipDateTo);
3. Строим дерево запроса, и выполняем оптимизации. Либо вручную, либо автоматом (при помощи proven техник, хорошо известных из разработки компиляторов). SQL-Сервер этим не занимается, и слава байту — у него и так много работы; всю stateless работу лучше выносить за его пределы.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Ночной Смотрящий, Вы писали:
V>>Ага, пошли ходить зигзагами. )) V>>Рефакторинг работал. НС>И как, можно было решарпером переименовать поле в БД?
А при чем здесь Linq и синхронизация кода и модели БД???
Тогда это было никак на любой технологии. Маппинг шел через атрибуты BLT, аргументы атрибутов — текст. Да и сейчас, если дата-контекст описывать руками, а не на живом соединении, то вовсе никак. Автоматический рефакторинг был только для кода. Если в поле менялось поле — то надо было обновить и маппинг.
V>>Всей разницы, что мы объекты проекций описывали явно, вместо автогенерирования компилятором анонимных типов. НС>При чем тут анонимные типы и проекции? Банальное выражение фильтра foo.Bar > 4 ты как записывал?
прямо так и записывал, переопределенные операторы же ж...
потому что:
class FooMeta {
Field<int> Bar { get; }
...
}
class Db {
FooMeta Foo { get; }
}
Пояснения нужны?
V>>Конечно, наколотили свой аналог expression tree над выражениями SQL НС>Да я уже давно все понял про твой трехколесный велосипед. И все проблемы этого велосипеда тоже прекрасно знаю.
Дык, модель автоматом генерилась. Опять же, спасибо "кишкам" BLT, которые экономили приличную часть работы даже для таких хелперов.
А проблемы таких велосипедов мы тоже прекрасно знаем, и? На тот момент это было лучшее решение из всевозможных виденных на дотнете.
НС>А нафига мне твои теоретические идеальные DBA, если и я и IT в реальных ситуациях видим совсем другое?
Почему идеальные? Обычные. Просто я в кач-ве DBA видел именно грамотных в этом деле людей. Но у нас как-то было без перегибов в сторону "разработка от базы". Т.е. не DBA разрабатывал базу, а ПМ выступал в роли аналитика, собирал инфу. Обсуждали командой вместе, вместе принимали решения по архитектуре на всех 3-х слоях. Т.е. программист БД знал, как данные идут на сервер приложений а от него — на десктопного клиента. Программист клиента знал, откуда берутся данные и что с ними в процессе доставки происходит. Но на стороне БД было оч много запрограммированного функционала, и оно было оправдано. По крайней мере на тех технологиях. Linq, положа руку на, еще в стадии становления. Провайдеры пока кривые и косые, низлежащее ADO тоже не блещет. Например, я лично баг отправлял в MS когда-то по парсеру MS SQL потока. Исправили потом в одном из SP.
В банках и на биржах тебе рассмеются в лицо, если ты им предложишь что-то на дотнете-Linq, для чего-то, где нужна хоть какая-то надежность.
Даже этот сайт, несложное, по-сути, приложение (это без попыток наезда) периодически выдаёт ошибки базы. А переспросишь страницу — всё ОК. Несерьезно. В банках и на бирже такое недопустимо принципиально. И я не говорю, что вы, программисты, в этом виноваты. Я как никто другой знаю, что нет. Вас можно обвинить только в том, что вы не навесили какие-нить костыли-воркараунды для этого случая, чтобы самостоятельно перезапросить построение страницы и отдать её, пусть на секунду позже, но без стыдливого окошка с сообщением об ошибке. Ну вот такова на сегодня надежность этих технологий, что тут сделаешь? Я почти сразу столкнулся с тем, что под нагрузкой ADO.Net периодически глюкало еще с самых первых версий. Блин, я такого даже вообразить не мог, когда пользовался ODBC или OLE DB, там надежность была железобетонная. Это же БАЗА, ёптить! )))
Зато участок кода с причиной тормозов обычно небольшой.
НС>>>Нет там рекурсии. От слова "совсем". V>>Ну тогда пример нерелевантный, бо ты как аргумент решил привести чьи-то кривые руки. Нафига там были временные таблицы, тогда?
НС>Так проще писать. Сложные запросы на много страниц на SQL плохо читаемы, со средствами декомпозиции бедулька, CTE больше засирает чем упрощает порой. Поэтому берут выборку, кладут во временную таблицу, и потом последовательно в несколько шагов ее ковыряют.
Охренеть. ))
Запросы на много страниц как раз неплохо сокращаются вьюхами и табличными ф-ями, содержащими самые популярные для базы наборы джоинов. Они почти всегда одни и те же, эти основные джоины.
НС>А если там еще и пейджинг, да total к нему нужен ... Это ж до последней версии такого уродца надо было сочинять. А тут наклал все во времянку, а потом из нее нужную страничку и total выдернул.
Ну ты хоть понимаешь, кривизну какого уровня ты описываешь? Ну вот я что-то такое и предполагал.
Это как на C# создать/инициализировать миллион сложных объектов, а потом использовать парочку самых последних созданных. Как программист тот DBA был г-но, сорри за прямую речь. Наверно это был какой-то бывший админ без профильного образования. Те разрабы БД, с которыми я имел дело — обычные программисты-системотехники, которые волею случая постепенно осели в программизме SQL на оч многих и разных по архитектуре серваках. Даже средней руки программист не сотворит того, что ты описал. Ты описал примерно то же, что я часто вижу в скриптах — "лишь бы хоть как-то работало". Скрипты обычно тоже пишут те еще "программисты". ))
НС>Разный, да не совсем. Количество вариантов в реальности сильно ограничено. А если кто сочинил что то новое — ну будет при первом запросе компиляция, не смертельно.
Наверно у меня недостаточно инфы или мы не понимаем друг друга... Вот я делаю выборку с итогом по некоему товару, скажем, из довольно большой таблицы движений, и каждый раз запрашиваю итоги по другому товару, будет ли тут кеширование запроса, если это не хранимка с параметром или табличная ф-ия, а прямо в тексте подаваемого запроса фигурирует новое числовое некое ID товара?
Здравствуйте, Sinclair, Вы писали:
S>А можешь показать, какой SQL генерится в том и том случаях?
Да все просто как рельс — нужно через left join выбрать одну большую простыню заказов и продуктов в заказах, а дальше в памяти разобрать по объектам.
Только EF, для своих внутренних нужд, еще вкрячивает дополнительный столбец типа CASE WHEN (Product.ID IS NULL) THEN CAST(NULL as int) ELSE 1 END as C1,
оборачивает это в еще один внешний запрос и сортирует результат — ORDER BY Order.Id ASC, C1 ASC
Стоимость этой операции увеличивает общую стоимость запроса больше чем в два раза. И есть у меня стойкое подозрение, что это упражнение EF проделывает с каждым left join-ом.
Здравствуйте, vdimas, Вы писали:
НС>>И как, можно было решарпером переименовать поле в БД? V>А при чем здесь Linq и синхронизация кода и модели БД???
При чем тут синхронизация? Я переименовал поле в БД. Теперь мне надо переименовать это поле во всем прикладном коде. В случае LINQ типы БД интегрированы в язык, поэтому работает самый обыкновенный рефакторинг. А вот в случае склейки строк или твоих экзерсисов на тему query builder все намного печальнее.
V>А проблемы таких велосипедов мы тоже прекрасно знаем, и? На тот момент это было лучшее решение из всевозможных виденных на дотнете.
В контексте топика никого тот момент не волнует, к чему ты его приплел? Сейчас есть expression tree, поэтому всю это кривоватую хрень можно смело выкинуть.
НС>>А нафига мне твои теоретические идеальные DBA, если и я и IT в реальных ситуациях видим совсем другое? V>Почему идеальные? Обычные.
Ну вот а обычных я имел возможность наблюдать в дикой природе с соответствующими выводами.
V>В банках и на биржах тебе рассмеются в лицо, если ты им предложишь что-то на дотнете-Linq
Ты просто не в теме. IT, кстати, в отличие от тебя, последнее время в основном в финансово-банковской сфере работает. И вот, такое дело, его наблюдения почему то полностью совпадают с моими.
V>, для чего-то, где нужна хоть какая-то надежность.
О, программисты АЭС. Давненько их тут не появлялось.
V>Запросы на много страниц как раз неплохо сокращаются вьюхами и табличными ф-ями, содержащими самые популярные для базы наборы джоинов.
Затрахаешься на каждый запрос уникальные функции плодить. А CTE, который, по идее, должен эту проблему решать, вышел , как это обычно у стандартизаторов sql почему то водится, удивительнейшим образом черезжопный.
V> Они почти всегда одни и те же, эти основные джоины.
Что ты в джойны все упираешься? Есть много разных конструкций, раздувающих запросы до неизведанных высот.
V>Ну ты хоть понимаешь, кривизну какого уровня ты описываешь?
Это вот такая реальность и такие DBA.
НС>>Разный, да не совсем. Количество вариантов в реальности сильно ограничено. А если кто сочинил что то новое — ну будет при первом запросе компиляция, не смертельно. V>Наверно у меня недостаточно инфы или мы не понимаем друг друга... Вот я делаю выборку с итогом по некоему товару, скажем, из довольно большой таблицы движений, и каждый раз запрашиваю итоги по другому товару, будет ли тут кеширование запроса, если это не хранимка с параметром или табличная ф-ия, а прямо в тексте подаваемого запроса фигурирует новое числовое некое ID товара?
А зачем прямо в тексте то? Параметры отменили что ли?
Здравствуйте, IB, Вы писали:
IB>Да все просто как рельс — нужно через left join выбрать одну большую простыню заказов и продуктов в заказах, а дальше в памяти разобрать по объектам. IB>Только EF, для своих внутренних нужд, еще вкрячивает дополнительный столбец типа CASE WHEN (Product.ID IS NULL) THEN CAST(NULL as int) ELSE 1 END as C1, IB>оборачивает это в еще один внешний запрос и сортирует результат — ORDER BY Order.Id ASC, C1 ASC
красавцы, чо. IB>Стоимость этой операции увеличивает общую стоимость запроса больше чем в два раза. И есть у меня стойкое подозрение, что это упражнение EF проделывает с каждым left join-ом. .
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Ну вот а обычных я имел возможность наблюдать в дикой природе с соответствующими выводами.
Меня всегда умиляют вот эти рассказы про мега-DBA. Примерно так же, как админы радуются выпадающим им окошкам типа "произошла непонятная ошибка, обратитесь к администратору". Ну, я — админ, мне к кому обращаться?
Это я к тому, что это у меня опыт работы с БД с 1991. Все рассказы про мегалогику в идеальных спроках, которые придумываются вместе с со специалистом в UX, и меинтейнятся потом с помощью "инструментов автоматической проверки" — городские легенды.
В жизни колонку с опечаткой типа ProdactCode держат в том же виде десятилетиями, ибо невозможно гарантировать корректность кода после переименования. Даже если бы существовал волшебный способ лёгким манием руки принудить перекомпиляцию всех хранимок в базе, это никак не поможет отловить dynamic SQL. А без Dynamic SQL невозможно написать сколь-нибудь сложный код — потому что средств декомпозиции в SQL никаких нету.
И чем больше размер проекта — тем хуже ситуация. Если в проектике на троих есть шанс, что хотя бы один из авторов держит в голове ~90% логики и представляет, что от чего зависит, то в проекте на 60 человек главная мантра — "работает — не трогай". Я занимался разгребанием результатов деятельности "профессиональных DBA", в том числе и себя же на пять лет младше.
И в итоге, на основании своего богатого жизненного опыта и глубокого понимания того, как работает SQL сервер, и, что ещё важнее — как он не работает, я считаю linq манной небесной. К сожалению, его мало кто хорошо готовит. Но принципиальная разница между ним и чем-угодно видна как раз опытному DBA, который в гробу видал мейнтенанс всех этих 2000 хранимок в БД. И это ещё если мы говорим про частный проектик, где все изменения контролируются командой разработчиков, у которых есть точные данные от DBA про статистику использования и конкретные размеры конкретных таблиц. Про коробочный продукт, который должен уметь обновляться в unattended режиме, и при этом корректно проглатывать все кастомизации, сделанные местным DBA, я вообще молчу.
А тут кругом ходят люди, которые явно SQL видели только в пересказе, и вещают мне про то, как я (как DBA) должен любить всю эту порнографию. Ха-Ха.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S> Даже если бы существовал волшебный способ лёгким манием руки принудить перекомпиляцию всех хранимок в базе...
Я опасаюсь вторых священных войн, но всё равно интересно: зачем вообще в 21 веке используют "хранимки"? Одни тут прогресс двигают, квадратики рисуют, MVC, MVVM и т.п., а другие шмякают эти "процедуры 20 века" и в ус не дуют! Что там такого "волшебного" делается, чего нельзя сделать на серверной стороне обычным кодом внутри "модели"?
Здравствуйте, btn1, Вы писали:
B>Я опасаюсь вторых священных войн, но всё равно интересно: зачем вообще в 21 веке используют "хранимки"? Одни тут прогресс двигают, квадратики рисуют, MVC, MVVM и т.п., а другие шмякают эти "процедуры 20 века" и в ус не дуют! Что там такого "волшебного" делается, чего нельзя сделать на серверной стороне обычным кодом внутри "модели"?
Сегодня спроки нужны в основном для услады паранойки. Кому-то всё ещё кажется, что они работают быстрее, кто-то ими накрывает все таблицы, чтобы типа обеспечить сикьюрити.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, btn1, Вы писали:
B>Здравствуйте, Sinclair, Вы писали:
S>> Даже если бы существовал волшебный способ лёгким манием руки принудить перекомпиляцию всех хранимок в базе...
B>Я опасаюсь вторых священных войн, но всё равно интересно: зачем вообще в 21 веке используют "хранимки"? Одни тут прогресс двигают, квадратики рисуют, MVC, MVVM и т.п., а другие шмякают эти "процедуры 20 века" и в ус не дуют! Что там такого "волшебного" делается, чего нельзя сделать на серверной стороне обычным кодом внутри "модели"?
Волшебного ничего, но затянуть полбазы в память чтобы показать последние 10 заказов, никому не кажется хорошей идеей.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>При чем тут синхронизация? Я переименовал поле в БД. Теперь мне надо переименовать это поле во всем прикладном коде.
Во всем прикладном коде так и переименовывается решарпером.
НС>В случае LINQ типы БД интегрированы в язык, поэтому работает самый обыкновенный рефакторинг. А вот в случае склейки строк или твоих экзерсисов на тему query builder все намного печальнее.
V>>А проблемы таких велосипедов мы тоже прекрасно знаем, и? На тот момент это было лучшее решение из всевозможных виденных на дотнете. НС>В контексте топика никого тот момент не волнует, к чему ты его приплел?
Началось...
Ты показал пример на Linq без спец-синтаксиса, я ответил, что у нас выглядело фактически так же.
НС>Сейчас есть expression tree, поэтому всю это кривоватую хрень можно смело выкинуть.
В том синтаксисе что ты показал — достижения не большие, прямо скажем.
НС>Ну вот а обычных я имел возможность наблюдать в дикой природе с соответствующими выводами.
Я тоже говнокодеров видел много, и?
V>>В банках и на биржах тебе рассмеются в лицо, если ты им предложишь что-то на дотнете-Linq НС>Ты просто не в теме.
Я как раз давно и плотно в теме.
НС>IT, кстати, в отличие от тебя, последнее время в основном в финансово-банковской сфере работает.
Ну я прекрасно знаю, что именно в этой "сфере" делают на дотнете. Это околосфера возле сферы. ))
НС>И вот, такое дело, его наблюдения почему то полностью совпадают с моими.
Пока не увижу в новостях, что где-то вышел движок биржи на Linq или банковский оп-день — это всё сказки про белого бычка. Оттуда уже даже Джава вымывается с большой скоростью.
V>>, для чего-то, где нужна хоть какая-то надежность. НС>О, программисты АЭС. Давненько их тут не появлялось.
Для движка биржи и банковского оп-дня нужна не меньшая надежность. Предположи, как построена технологически та же NASDAQ? CME? SGX?
V>>Запросы на много страниц как раз неплохо сокращаются вьюхами и табличными ф-ями, содержащими самые популярные для базы наборы джоинов. НС>Затрахаешься на каждый запрос уникальные функции плодить.
Ты упорно не понимаешь о чем речь... а говоришь, что в теме.
V>> Они почти всегда одни и те же, эти основные джоины. НС>Что ты в джойны все упираешься? Есть много разных конструкций, раздувающих запросы до неизведанных высот.
Даже в них те же самые повторяющиеся конструкции.
V>>Ну ты хоть понимаешь, кривизну какого уровня ты описываешь? НС>Это вот такая реальность и такие DBA.
Бред. Ты показал просто плохого программиста. Хороший админ базы не есть хороший программист базы. Я же о последних, ес-но. Не зря даже в настройках уровня доступа это разные роли.
НС>А зачем прямо в тексте то? Параметры отменили что ли?
Здравствуйте, gandjustas, Вы писали:
G>Волшебного ничего, но затянуть полбазы в память чтобы показать последние 10 заказов, никому не кажется хорошей идеей.
В данном натянутом примере — да. А реальный? Ну и не забываем, что "хранимки" — они тоже не с секторами диска работают, им тоже нужен доступ к записям, которые тоже физически вытаскиваются в операбельную структуру. Итак?...
Здравствуйте, btn1, Вы писали:
B>Здравствуйте, gandjustas, Вы писали:
G>>Волшебного ничего, но затянуть полбазы в память чтобы показать последние 10 заказов, никому не кажется хорошей идеей.
B>В данном натянутом примере — да. А реальный? Ну и не забываем, что "хранимки" — они тоже не с секторами диска работают, им тоже нужен доступ к записям, которые тоже физически вытаскиваются в операбельную структуру. Итак?...
Чтобы не путаться:
1) Хранимки — набор sql операторов, которые выполняются на стороне СУБД без раундтрипов с клиентом
2) В принципе ничего не мешает отправить такой же набор операторов одним батчем с клиента на сервер
3) Хранимки лишь обеспечивают инкапсуляцию логики в базе
Поэтому перефразирую вопрос — "может вообще всю логику выполнять в приложении, а не в SQL?"
Однозначно нельзя. Даже если отбросить вопросы надежности хранения, особенно при конкурентной работе.
Выполнение SQL запроса оптимизируется с точки зрения обращения к диску (который является самой медленной частью любой системы). Например для получения тех же 10 последних заказов текущего пользователя СУБД даже не будет поднимать с диска все записи о заказах (которых могут быть миллионы). Индексы в СУБД позволяют считать с диска ровно столько, сколько необходимо для получения результатов запроса, причем в уже отсортированном виде.
Здравствуйте, btn1, Вы писали:
B>Я опасаюсь вторых священных войн, но всё равно интересно: зачем вообще в 21 веке используют "хранимки"? Одни тут прогресс двигают, квадратики рисуют, MVC, MVVM и т.п., а другие шмякают эти "процедуры 20 века" и в ус не дуют! Что там такого "волшебного" делается, чего нельзя сделать на серверной стороне обычным кодом внутри "модели"?
Если отбросить инерцию мышления и карго культы, то хранимки — это способ превратить SQL сервер в application server с RPC-протоколом. Это может быть полезно, например, в случаях наличия большого количества клиентов (веб-приложение, даже сложное и с большой нагрузкой — это один клиент).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>[/sql] S>1.а. Используем процедурное расширение SQL: S>
S>if (@shipDateFrom is null)
S>begin
S> if (@shipDateTo is null)
S> select * from orders
S> else
S> select * from orders where ShippedDate <= @shipDateTo
S>end
S>else begin
S> if (@shipDateTo is null)
S> select * from orders where ShippedDate >= @shipDateFrom
S> else
S> select * from orders where ShippedDate >= @shipDateFrom and ShippedDate <= @shipDateTo
S>end
S>
Процедура со сложностью поддержки аргументов n^2 имени маляр Шлемиэля.
НС>>А нафига мне твои теоретические идеальные DBA, если и я и IT в реальных ситуациях видим совсем другое?
V>Провайдеры пока кривые и косые
В чем это выражается?
V>низлежащее ADO тоже не блещет. Например, я лично баг отправлял в MS когда-то по парсеру MS SQL потока. Исправили потом в одном из SP.
Я видел баг в .NET 1.1, говорят был еще баг в .NET 2.0. Если что, текущая версия .NET 4.5.1. про баги не слышал.
V>В банках и на биржах тебе рассмеются в лицо, если ты им предложишь что-то на дотнете-Linq, для чего-то, где нужна хоть какая-то надежность.
Внезапно видел Linq в банковском софте.
V>Даже этот сайт, несложное, по-сути, приложение (это без попыток наезда) периодически выдаёт ошибки базы.
Ты про дедлоки? Как это связано с Linq и ADO.NET?
V>Блин, я такого даже вообразить не мог, когда пользовался ODBC или OLE DB, там надежность была железобетонная.
База, как и любой внешний сервис может отвалится, не предупредив приложение. Все возможные технологии отказоустойчивости все равно дают даунтайм на время failover. И дело вовсе не в ODBC или ADO.NET.
Но даже если база не падает, то твой запрос, даже самый безобидный, может отвалиться по куче причин. Начиная от банального дедлока, заканчивая происками resource governor.
V>Это же БАЗА, ёптить! )))
Ты слишком мало работал с промышленными СУБД, если так говоришь.
V>Запросы на много страниц как раз неплохо сокращаются вьюхами и табличными ф-ями, содержащими самые популярные для базы наборы джоинов. Они почти всегда одни и те же, эти основные джоины.
Дело не во вьюхах и джоинах, а в предикатах и проекциях. Это две самые изменяемые части запросов.
Для примера тот же интернет-магазин средней руки, в нем есть таблица товаров из котром можно выбирать:
1) По бренду
2) По наличию
3) По гарантии
А еще можно сортировать по:
1) Цене
2) Названию
И еще надо постраничное разбиение не забыть.
Даже если ты сделаешь вьюху, то все равно надо поверх нее сгенерировать около 15 запросов. И это мы еще проекции не считали.
Можно сделать это все на стороне базы, но надо будет клеить строки, что на стороне приложения делается гораздо проще.
V>Вот я делаю выборку с итогом по некоему товару, скажем, из довольно большой таблицы движений, и каждый раз запрашиваю итоги по другому товару, будет ли тут кеширование запроса, если это не хранимка с параметром или табличная ф-ия, а прямо в тексте подаваемого запроса фигурирует новое числовое некое ID товара?
Что такое кеширование запроса? SQL Server кеширует планы, чтобы не перекомпилировать.
Планы запросов кешируются всегда. Но по умолчанию для каждого запроса будет отдельный план (любой более-менее сложный запрос не параметризуется автомачтически). Для запросов с параметрами или для хранимок будет один план для любых параметров. Это может быть как хорошо, так и плохо. Если план стабилен (одинаково хорош для любых параметров), то кеширование планов улучшает работу. Если план нестабилен (как в большинстве нетривиальных хранимок), то кеширование планов мешает и надо вызывать перекомпиляцию.
Здравствуйте, vdimas, Вы писали:
V>Пока не увижу в новостях, что где-то вышел движок биржи на Linq или банковский оп-день — это всё сказки про белого бычка.
А ты видишь в новостях про биржи на ODBC или опердни на ADO?
Работа с данными не самая важная часть приложения, хотя зачастую и самая ресурсоемкая. А Linq вообще не более чем генератор запросов, от которого можно в будущем отказаться, если активная разработка уже не ведется (как сделали в StackOverflow).
Но именно этот генератор запросов позволяет разрабатывать приложения с огромной скоростью, не нагружая DBA написанием селектов.
Здравствуйте, gandjustas, Вы писали:
G>Поэтому перефразирую вопрос — "может вообще всю логику выполнять в приложении, а не в SQL?"
G>Однозначно нельзя. Даже если отбросить вопросы надежности хранения, особенно при конкурентной работе.
Тут ничего отбрасывать и не нужно: сервис типа СУБД и создан для того, чтобы всё было надёжно — ему пофиг, откуда пришёл запрос.
G>Выполнение SQL запроса оптимизируется с точки зрения обращения к диску (который является самой медленной частью любой системы).
Разве для запроса к данным есть разница, пришёл он от хранимки или от внешнего клиента??
Пока что всё отличие хранимки от ВК(внеш.клиент) — отсутствие у ВК процедурной части. Напомню: обе сущности сидят на стороне сервера.
Попробую схематично изобразить моё представление:
Внешний клиент:
Клиент -> носитель, передающий SQL запрос (API сервера) -> обработчик запроса внутри СУБД (со всеми кэшами, оптимизациями и т.п.)
Хранимка:
Исходник (PL/SQL, T-SQL) -> некий процедурный псевдокод(ПП). Сервер исполняет этот ПП (в меру скорости своей виртуальной машины) -> ПП делает промежуточные SQL обращения к данным -> обработчик запроса внутри СУБД (со всеми кэшами, оптимизациями и т.п.)
----------------------------------------------------------
Итого, даже если допустить разницу в представлении записи для ПП и для ВК(хотя какой смысл это делать?), я не думаю, что это сильно влияет на производительность. ПП — он тоже ведь существует не в абстрактном ЦПУ с бесконечной производительностью — это просто МОДУЛЬ, внешний по отн. к внутренним механизмам СУБД и исполняющийся на том же процессоре, что и ВК (только ещё посмотреть, чей код быстрее — скомпилированного ВК или ПП!).
Получается, с ВК мы имеем всю мощь ЯВУ со всем мыслимыми библиотеками, а с ПП — убогий набор языковых средств, который удосужились сделать разработчики СУБД. Поэтому опять подымается вопрос: накой нам хранимки? С ними мы:
1. Имеем геморой с подключением к проекту дополнительного языка (много ли найдётся спецов, досконально знающих C# и при этом так же хорошо владеющих PL/SQL?)
2. Хуже того: создавая хранимки, мы резко всаживаем в зад крюк проприетарщины — попробуй, смени MS SQL на Oracle! И не просто "перепиши все хранимки", а ещё правильно это сделай (см. п.1 про спецов).
3. ВК — это ещё и широчайшая свобода технологий: хочешь — авторизуйся через AD, хочешь — прикрути защиту через HASP, не понравилось — есть ещё сотни библиотек, которых не существует в СУБД, но которые ты можешь юзать в ВК.
4. Уже упомянутый геморой с рефакторингом: есть море утилит, вытаскивающих структуру БД и синхронизирующую с текущим набором классов. Но чтобы сделать то же самое с хранимками — это уже двойной гемор для самой синхронизации и ещё n-кратный, если надо синхронизировать другой тип СУБД.
5. Теряем в гибкости. Переписать/перекомпоновать свой сервис под новые требования — это несколько часов в студии, весело жонглируя модулями. Делать то же самое в хранимках — может оказаться вообще невозможным! (см. п. 3) Не говоря про "никакие" средства рефакторинга на стороне СУБД.
В результате народ продолжает писать хранимки, свято веря в древние легенды о производительности, хотя никаких замеров даже не пытаются сделать. И ДАЖЕ если мы теряем сколько-то процентов на ВК, это с лихвой окупается гибкостью самого решения.
Здравствуйте, Sinclair, Вы писали:
S>Если отбросить инерцию мышления и карго культы, то хранимки — это способ превратить SQL сервер в application server с RPC-протоколом.
+1!!
S> Это может быть полезно, например, в случаях наличия большого количества клиентов (веб-приложение, даже сложное и с большой нагрузкой — это один клиент).
Ну так это уже вопрос устройства веб-сервера! (и даже при самом убогом веб-сервере можно сделать целую ферму таких серверочков + балансировка)
Тут уже нужно бенчмаркать: может статься так, что серверу приложений выгоднее (временно) выстроить очередь, но быстро её обработать за счёт отсутствия чужих локов на таблице, чем генерить десять разных клиентов БД, каждый из которых будет ждать своего обслуживания, но зато они "как бы сразу" приняты к обработке.
Но как бы то ни было, тут всё равно не видно, за счёт чего хранимка может выигрывать: фактически, хранимка — это тот же процедурный код вокруг данных: как только данные получены, всё будет зависеть только от скорости работы этого процедурного кода, что хранимка, что модуль сервера приложений.
Здравствуйте, vdimas, Вы писали:
V>В банках и на биржах тебе рассмеются в лицо, если ты им предложишь что-то на дотнете-Linq, для чего-то, где нужна хоть какая-то надежность.
Можно я рассмеюсь в лицо тебе сидя в банке и используя дотнет-Linq уже много лет? Спасибо!
V>Я почти сразу столкнулся с тем, что под нагрузкой ADO.Net периодически глюкало еще с самых первых версий. Блин, я такого даже вообразить не мог, когда пользовался ODBC или OLE DB, там надежность была железобетонная. Это же БАЗА, ёптить! )))
За последние несколько лет была только одна неразрешимая проблема с надёжностью ADO.NET. Задача, которая крутилась месяцами (Windows Service) иногда вылетала к понедельнику. Препарирование проблемы показало, что админы по восткресеньям жестко перегружали сервер БД. БД — Sybase — это важно. При этом при обращении к этой БД в такой ситуации возникало исключение в нативной части Sybase провайдера. После примерно пары десятков таких исключений Sybase провайдер сшибал нафиг .NET runtime. Отловить и восстановиться после такого исключения невозможно. Пришлось делать восстановление работоспособности приложения средствами самой Winndows. Через пару лет переход на новую версию Sybase драйвера проблема решилась сама собой.
Итого имеем. Ненадёжность ADO.NET была обусловлена наличием нативного кода в и без того глючном драйвере Sybase, написанного криворукими китайцами.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Итого имеем. Ненадёжность ADO.NET была обусловлена наличием нативного кода в и без того глючном драйвере Sybase, написанного криворукими китайцами.
Даже не так.
Ненадёжность ADO.NET была обусловлена наличием нативного кода в и без того глючном драйвере Sybase, написанного криворукими китайцами и необходимостью еженедельной перегрузки DBA-ями "супернадёжной" и одной из наиболее распространённой БД в банках, не имеющей к .NET никакого отношения.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, btn1, Вы писали:
B>Попробую схематично изобразить моё представление:
B>Внешний клиент:
B>Клиент -> носитель, передающий SQL запрос (API сервера) -> обработчик запроса внутри СУБД (со всеми кэшами, оптимизациями и т.п.)
B>Хранимка:
B>Исходник (PL/SQL, T-SQL) -> некий процедурный псевдокод(ПП). Сервер исполняет этот ПП (в меру скорости своей виртуальной машины) -> ПП делает промежуточные SQL обращения к данным -> обработчик запроса внутри СУБД (со всеми кэшами, оптимизациями и т.п.) B>---------------------------------------------------------- B>Итого, даже если допустить разницу в представлении записи для ПП и для ВК(хотя какой смысл это делать?), я не думаю, что это сильно влияет на производительность. ПП — он тоже ведь существует не в абстрактном ЦПУ с бесконечной производительностью — это просто МОДУЛЬ, внешний по отн. к внутренним механизмам СУБД и исполняющийся на том же процессоре, что и ВК (только ещё посмотреть, чей код быстрее — скомпилированного ВК или ПП!).
Промежуточный код, называемый "планом запроса" используется как для хранимок, так и для запросов от приложения (adhoc запросов). Планы запроса однозначно быстрее, потому что оптимизируют чтение с диска. Приложению для начала нужно все данные затянуть в память и с ними работать, а для СУБД это не требуется.
B>Получается, с ВК мы имеем всю мощь ЯВУ со всем мыслимыми библиотеками, а с ПП — убогий набор языковых средств, который удосужились сделать разработчики СУБД. Поэтому опять подымается вопрос: накой нам хранимки? С ними мы: B>1. Имеем геморой с подключением к проекту дополнительного языка (много ли найдётся спецов, досконально знающих C# и при этом так же хорошо владеющих PL/SQL?) B>2. Хуже того: создавая хранимки, мы резко всаживаем в зад крюк проприетарщины — попробуй, смени MS SQL на Oracle! И не просто "перепиши все хранимки", а ещё правильно это сделай (см. п.1 про спецов). B>3. ВК — это ещё и широчайшая свобода технологий: хочешь — авторизуйся через AD, хочешь — прикрути защиту через HASP, не понравилось — есть ещё сотни библиотек, которых не существует в СУБД, но которые ты можешь юзать в ВК. B>4. Уже упомянутый геморой с рефакторингом: есть море утилит, вытаскивающих структуру БД и синхронизирующую с текущим набором классов. Но чтобы сделать то же самое с хранимками — это уже двойной гемор для самой синхронизации и ещё n-кратный, если надо синхронизировать другой тип СУБД. B>5. Теряем в гибкости. Переписать/перекомпоновать свой сервис под новые требования — это несколько часов в студии, весело жонглируя модулями. Делать то же самое в хранимках — может оказаться вообще невозможным! (см. п. 3) Не говоря про "никакие" средства рефакторинга на стороне СУБД.
B>В результате народ продолжает писать хранимки, свято веря в древние легенды о производительности, хотя никаких замеров даже не пытаются сделать. И ДАЖЕ если мы теряем сколько-то процентов на ВК, это с лихвой окупается гибкостью самого решения.
Вопрос не корректно поставлен. Как в хранимке, так и в клиентском приложении надо писать одинаковые запросы, которые проходят через абсолютно одинаковый пайплайн исполнения. Иначе не видать производительности.
1) Геморрой подключения нового яызка остается, только если не пользуешься Linq в C#, но даже он не освобождает от необходимости понимания какие запросы летят в базу.
2) Проблема со сменой СУБД не менее актуальна, опять-таки Linq поможет сгладить проблему, но устранить её.
3) Наличие хранимок в базе не делает ненужным клиентское приложение.
4) Неактуальная проблема на сегодня. Те же утилиты могут генерить методы по хранимкам. В F# такое реализовано в виде TypeProvider.
5) Это следствие п1
По факту, если сравнивать хранимки vs SQL запросы в коде приложения (при учете того, что это одинаковые запросы), то почти паритет. В харнимках чуть сложнее делать данимаческие запросы, но меньше раундтрипов до клиента и проще хинтами запинать запросы. Кроме того при изменении запроса в хранимке не требуется редеплой приложений. Особо актуально это было во времена клиент-серверных приложений, смотрящих напрямую в базу. Но даже сейчас, когда повсюду трехзвенки, редеплой сервера может быть сложной операцией.
Но при наличии Linq-провайдеров в БД преимущества сильно на стороне написания Linq запросов, которые трансформируются в SQL запросы.
Здравствуйте, btn1, Вы писали:
B>Здравствуйте, Sinclair, Вы писали:
S>>Если отбросить инерцию мышления и карго культы, то хранимки — это способ превратить SQL сервер в application server с RPC-протоколом.
B>+1!!
S>> Это может быть полезно, например, в случаях наличия большого количества клиентов (веб-приложение, даже сложное и с большой нагрузкой — это один клиент).
B>Ну так это уже вопрос устройства веб-сервера! (и даже при самом убогом веб-сервере можно сделать целую ферму таких серверочков + балансировка)
B>Тут уже нужно бенчмаркать: может статься так, что серверу приложений выгоднее (временно) выстроить очередь, но быстро её обработать за счёт отсутствия чужих локов на таблице, чем генерить десять разных клиентов БД, каждый из которых будет ждать своего обслуживания, но зато они "как бы сразу" приняты к обработке.
То есть ты считаешь, что очередь в приложении может быть выгоднее очереди внутри СУБД? Гранулярность блокировок в СУБД — одна запись, соответственно запросы, получающие две разные записи не будут выстраиваться в очередь. А на уровне приложения ты сможешь сделать гранулярность на уровне таблиц. Теоретически можно и с ключами отдельных записей делать блокировки, но тогда сразу убьешься об дедлоки.
Здравствуйте, gandjustas, Вы писали:
G>Планы запроса однозначно быстрее, потому что оптимизируют чтение с диска. Приложению для начала нужно все данные затянуть в память и с ними работать, а для СУБД это не требуется.
Разве? Если я делаю выборку на 1М записей, я даже получаю их порциями, а обрабатываю вообще по одной. Неужто сервер не имеет оптимизаций на случай "клиент попросил много записей, но их не обязательно отсылать все сразу"?
G>Вопрос не корректно поставлен. Как в хранимке, так и в клиентском приложении надо писать одинаковые запросы, которые проходят через абсолютно одинаковый пайплайн исполнения. Иначе не видать производительности.
Ты говоришь очевидное и мною подразумеваемое условие. Вопрос вообще не про LINQ, он ставится так: Необходимо сделать низкоуровневую работу на уровне записей БД, чтобы освободить бизнес-логику от SQL-специфики.
Два варианта: пишем непереносимые хранимки на языке, специфичном для данной СУБД (и даже для версии СУБД), второй вариант — на сервере приложений, внутри "классов-моделей", пишем на обычном ЯВУ команды, делая все те же действия/запросы, что и в хранимке. Ответ по-моему очевиден: классы-модели.
G>1) Геморрой подключения нового яызка остается, только если не пользуешься Linq в C#, но даже он не освобождает от необходимости понимания какие запросы летят в базу.
Не путай "подключить SQL к C#" с "подключить PL/SQL к C#"! Если SQL мало-мальски стандартизован, то проприетарные недоязыки уж точно пятое колесо!
G>2) Проблема со сменой СУБД не менее актуальна, опять-таки Linq поможет сгладить проблему, но устранить её.
Смена БД, имеющей хранимки, НА ПОРЯДОК сложнее БД с чисто таблицами. Я утверждаю только это, ты с этим согласен?
G>В харнимках чуть сложнее делать данимаческие запросы, но меньше раундтрипов до клиента и проще хинтами запинать запросы.
Согласен. Но я предполагаю, что сервер не настолько туп и не настолько проседает в производительности, чтобы скатываться к хранимкам — далеко не все базы требуют производительности биллинговых систем.
G> Кроме того при изменении запроса в хранимке не требуется редеплой приложений.
А что, "изменение хранимки" у нас бесплатное?? Ровно такой же редеплой, только вместо перезаписи DLLек — загляд и залаз в базу. Точно такая же опасная операция.
G>Но при наличии Linq-провайдеров в БД преимущества сильно на стороне написания Linq запросов, которые трансформируются в SQL запросы.
Не про LINQ речь, но я тебя понял. Ты согласен с тем, что на сегодня нет никаких серьёзных причин писать хранимки?
Здравствуйте, gandjustas, Вы писали:
G>То есть ты считаешь, что очередь в приложении может быть выгоднее очереди внутри СУБД? Гранулярность блокировок в СУБД — одна запись
Если я пишу в таблицу море записей, я могу вообще со всей очереди собрать данные на запись и заструячить одним пакетом — клиент-то один! Если же пишут разные клиенты БД, для каждого из них серверу придётся аккуратно встать в режим "на, записывай!", синхронизируя внутреннее состояние. Разные клиенты — это как враги, сервер должен позаботиться о том, чтобы они не передрались за ресурсы Единый клиент имеет больше информации о логике операций.
Да и не об этом речь, а о хранимках — очень сомнительно, что у них есть какое-то кратное преимущество при обслуживании большого количества запросов перед кодом на сервере приложений.
Здравствуйте, btn1, Вы писали:
B>Здравствуйте, gandjustas, Вы писали:
G>>Планы запроса однозначно быстрее, потому что оптимизируют чтение с диска. Приложению для начала нужно все данные затянуть в память и с ними работать, а для СУБД это не требуется.
B>Разве? Если я делаю выборку на 1М записей, я даже получаю их порциями, а обрабатываю вообще по одной. Неужто сервер не имеет оптимизаций на случай "клиент попросил много записей, но их не обязательно отсылать все сразу"?
Никто не делает выборки на миллион записей. Делают выборки типа 100 последних заказов клиента с каким то id. SQL достанет записи из индекса, прочитав менее 10 страниц (8 килобайт).
Предположим ты захотел сделать это на стороне приложения, тогда ты должен прочитать все заказы, которых миллионы, то есть поднять с диска около около гб данных, прокачать по сети, пробежаться по всем, выбрать которые нужны и отсортировать их по убыванию, выбрать первые 100 и показать.
Учитывая, что таких запросов в секунду может приходить много, и по разным клиентам посчитай какой объем данных надо будет обрабатывать на каждый запрос.
А ведь это примитивный запрос.
G>>1) Геморрой подключения нового яызка остается, только если не пользуешься Linq в C#, но даже он не освобождает от необходимости понимания какие запросы летят в базу.
B>Не путай "подключить SQL к C#" с "подключить PL/SQL к C#"! Если SQL мало-мальски стандартизован, то проприетарные недоязыки уж точно пятое колесо!
У каждой субд свой диалект.
G>>2) Проблема со сменой СУБД не менее актуальна, опять-таки Linq поможет сгладить проблему, но устранить её.
B>Смена БД, имеющей хранимки, НА ПОРЯДОК сложнее БД с чисто таблицами. Я утверждаю только это, ты с этим согласен?
Нет, ибо зависит от запросов. Например если динамическая генерация запросов на TSQL написана на c#, то ей гораздо сложнее портировать на оракл, чем просто переписать хранимки.
G>> Кроме того при изменении запроса в хранимке не требуется редеплой приложений.
B>А что, "изменение хранимки" у нас бесплатное?? Ровно такой же редеплой, только вместо перезаписи DLLек — загляд и залаз в базу. Точно такая же опасная операция.
Работа субд не останавливается при этом. А приложение таки надо останавливать.
G>>Но при наличии Linq-провайдеров в БД преимущества сильно на стороне написания Linq запросов, которые трансформируются в SQL запросы. B>Не про LINQ речь, но я тебя понял. Ты согласен с тем, что на сегодня нет никаких серьёзных причин писать хранимки?
По сравнению с чем? Для сценария клиент-серверных приложений я бы выбрал инкапсуляцию запросов в базе — представления, функции, триггеры, хранимки. В остальных случаях — linq.
Здравствуйте, btn1, Вы писали:
B>Здравствуйте, gandjustas, Вы писали:
G>>То есть ты считаешь, что очередь в приложении может быть выгоднее очереди внутри СУБД? Гранулярность блокировок в СУБД — одна запись
B>Если я пишу в таблицу море записей, я могу вообще со всей очереди собрать данные на запись и заструячить одним пакетом — клиент-то один! Если же пишут разные клиенты БД, для каждого из них серверу придётся аккуратно встать в режим "на, записывай!", синхронизируя внутреннее состояние. Разные клиенты — это как враги, сервер должен позаботиться о том, чтобы они не передрались за ресурсы Единый клиент имеет больше информации о логике операций.
Может быть и выгоднее, но при чем блокировки? И что делать если у тебя в пакет попали конфликтующие изменения. Один пользователь например хочет увеличить значение поля на единицу, а другой уменьшить.
B>Да и не об этом речь, а о хранимках — очень сомнительно, что у них есть какое-то кратное преимущество при обслуживании большого количества запросов перед кодом на сервере приложений.
Это смотря как писать.
Здравствуйте, btn1, Вы писали:
B>Ну так это уже вопрос устройства веб-сервера! (и даже при самом убогом веб-сервере можно сделать целую ферму таких серверочков + балансировка)
Нет. С точки зрения версионности, вся ферма — это один клиент. Т.е. у нас гарантия непротиворечивости бизнес-логики обеспечивается единым кодом.
Проблемы начинаются тогда, когда у вас в одну и ту же БД одновременно ходят клиенты разных версий или типов.
Тогда единственный способ ограничить их самодеятельность и избежать расхождения логики — гонять их через сервер приложений. Т.е. — или трёхзвенка (которая с точки зрения СУБД является сведением к случаю одного клиента), или хранимки.
B>Но как бы то ни было, тут всё равно не видно, за счёт чего хранимка может выигрывать: фактически, хранимка — это тот же процедурный код вокруг данных: как только данные получены, всё будет зависеть только от скорости работы этого процедурного кода, что хранимка, что модуль сервера приложений.
Хранимка выигрывает не в перформансе, а в стабильности — нет риска, что какой-то багливый клиент снимет деньги со счёта A и забудет положить на счёт Б. Наружу вместо таблиц выставляются RPC-style процедуры; все изменения в логике этих процедур делаются централизованно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, gandjustas, Вы писали:
B>>А что, "изменение хранимки" у нас бесплатное?? Ровно такой же редеплой, только вместо перезаписи DLLек — загляд и залаз в базу. Точно такая же опасная операция. G>Работа субд не останавливается при этом. А приложение таки надо останавливать.
Дело не только в остановке работы, а в количестве мест, где меняются dll-ки.
Хранимка существует ровно в одном экземпляре; весь DDL при развёртывании можно выполнить внутри одной транзакции, и обеспечить консистентную атомарную замену всей логики.
Если с базой работает 1500 копий клиентов из 30 географических мест, то обеспечить их согласованный апгрейд — та ещё логистическая задача. При наличии хранимок, максимум, что получит устаревший клиент — SQL Server Error при попытке вызова хранимки не с теми аргументами (это если изменилась сигнатура). При прямом доступе в базу и логике в "триггерах на клиенте" один "отставший" клиент может втихую поломать полбазы — например, плодя заказы в статусе, который больше никем не поддерживается.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
ИМХО единственное что реально можно пользовать из EF это его LINQ провайдер, т.е. SELECT, пользоваться всем остальным крайне не рекомендовано.
Для меня EF это не ORM а замена для Linq 2 SQL.
Хотя в плане дизайна замена так себе.
Здравствуйте, Sinclair, Вы писали:
G>>Работа субд не останавливается при этом. А приложение таки надо останавливать.
Не факт. Возможно, я хреновый прогер, но бывало такое, что базу приходилось останавливать и поля менялись очень серьёзно (вплоть до объединения двух в один или даже смена типа колонки). ТАКОЕ я бы не стал делать "вживую".
Хотя ваши доводы всё равно не особо впечатляют: если уж данные такие важные, работа сервера приостанавливается (т.е. больше не принимаются соединения клиентов), делается снимок базы, обновляется и запускается параллельно, а потом удаляется устаревшая база.
Но мы опять не о том спорим — ну что у вас, Байконур что ли?? Сервер МОЖНО остановить на время, тут вопрос не о том, кого легче обновить (господи, секундное дело!), а вообще весь жизненный цикл продукта + его развитие. С кодом мы трахаемся куда больше, чем с обновлениями и вот тут эти "хранимки" — поперёк горла.
Здравствуйте, btn1, Вы писали: B>Не факт. Возможно, я хреновый прогер, но бывало такое, что базу приходилось останавливать и поля менялись очень серьёзно (вплоть до объединения двух в один или даже смена типа колонки).
Извините за вопрос не по теме, но почему вы не читаете то, что вам пишут?
Вопрос не про обновления вживую, а про невозможность атомарно проапгрейдить распределённую бизнеслогику.
B>Но мы опять не о том спорим — ну что у вас, Байконур что ли?? Сервер МОЖНО остановить на время, тут вопрос не о том, кого легче обновить (господи, секундное дело!), а вообще весь жизненный цикл продукта + его развитие. С кодом мы трахаемся куда больше, чем с обновлениями и вот тут эти "хранимки" — поперёк горла.
Ещё раз вчитайтесь в вопрос: как вы собираетесь свести обновление 1500 клиентов в 30 офисах и 11 часовых поясах к "секундному делу"?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
S>Интересно. А как происходит генерация вариантов параметров запроса? S>Как разруливаются ситуации с декомпозированными запросами, т.е. когда тело собирается кодом, расположенным в разных методах? S>Как разруливаются ситуации с декомпозицией "поперёк" границы сборок?
Спасибо за вопросы по существу.
Ключевые для понимания моменты описаны здесь.
Здравствуйте, Sinclair, Вы писали:
S>Извините за вопрос не по теме, но почему вы не читаете то, что вам пишут?
Потому что те, кому я отвечаю, съехали в какие-то дебри и толкают мысли, которые интересны только им. Может у меня что-то с русским языком, но я с трудом нахожу общность между моим
Во-первых, речь вообще не про апгрэйд, а про принципиальные возможности хранимок и кода на ЯВУ внутри модели. То есть меня интересуют не косвенные процедуры "так легче чесать левое ухо", а самое главное: работа хранимок/кода в реале и их ALM. Пока что преимуществ хранимок высказано не было, только намёки на теоретический бенефит от работы хранимки "как бы внутри" сервера.
S>Ещё раз вчитайтесь в вопрос: как вы собираетесь свести обновление 1500 клиентов в 30 офисах и 11 часовых поясах к "секундному делу"?
Я отвечу на этот второстепенный вопрос, но продолжать "тему обновлений" не вижу смысла — вы ушли от главного и мусолите детали.
1. Даже если мы возьмём систему, где широко используют хранимки, в ней всё равно не избежать какой-то логики на стороне сервера приложений (рассматриваются только трёхзвенные системы как наиболее передовая архитектура). А значит "обновления хранимок" — лишь часть того, что нужно обновлять на сервере, т.е. мы по-любому не избегаем процедуры обновления сервера.
2. Если у вас 30 филиалов, очевидно, что этим занимается далеко не один человек. Распределить задачу обновления — административная хрень.
3. Если для вас "остановить сервер, обновить, запустить" — проблема, то наверное есть смысл улучшить свою квалификацию? Есть тысячи систем, которые обновляют, и которые продолжают работать — весь вопрос лишь в аккуратности процесса и дотошности контроля качества обновления.
Вопрос "обновления" — вопрос ни о чём, с тем же успехом можно обсудить подсветку T-SQL в студии — это далеко не самое интересное в вопросе "хранимки vs код".
Здравствуйте, btn1, Вы писали:
B>Во-первых, речь вообще не про апгрэйд, а про принципиальные возможности хранимок и кода на ЯВУ внутри модели.
Принципиальные возможности одинаковые. И то и другое полно по тьюрингу.
Тем не менее в коде на ЯВУ надо писать ровно те же запросы, что и в хранимках. Поэтому вопрос как раз не в принципиальных возможностях, а во вполне конкретных проблемах, связанных с обновлением.
B>работа хранимок/кода в реале и их ALM. Пока что преимуществ хранимок высказано не было, только намёки на теоретический бенефит от работы хранимки "как бы внутри" сервера.
Как раз в ALM и есть самая проблема. В базе можно одновременно обновлять схему и логику, причем транзакционно. Если у тебя раздельное обновление кода (в приложении) и схемы (в базе), то надо обеспечить работу старого кода с новой схемой. Даже имея трехзвенное приложение с логикой на сервере, довольно сложно синхронно обновить все экземпляры сервера.
S>>Ещё раз вчитайтесь в вопрос: как вы собираетесь свести обновление 1500 клиентов в 30 офисах и 11 часовых поясах к "секундному делу"? B>Я отвечу на этот второстепенный вопрос, но продолжать "тему обновлений" не вижу смысла — вы ушли от главного и мусолите детали.
То есть хорошего решения для этого случая, кроме логики в базе, практически нет.
B>1. Даже если мы возьмём систему, где широко используют хранимки, в ней всё равно не избежать какой-то логики на стороне сервера приложений (рассматриваются только трёхзвенные системы как наиболее передовая архитектура). А значит "обновления хранимок" — лишь часть того, что нужно обновлять на сервере, т.е. мы по-любому не избегаем процедуры обновления сервера.
Неверно. Логику в базе можно инкасулировать настолько, что клиент многие изменения и не увидит. Хотя для случаев когда приложение монопольно работает с базой такой необходимости нет.
B>2. Если у вас 30 филиалов, очевидно, что этим занимается далеко не один человек. Распределить задачу обновления — административная хрень.
Хорошая отмазка для менеджмента, но по сути перекладывание с больной головы на здоровую.
B>3. Если для вас "остановить сервер, обновить, запустить" — проблема, то наверное есть смысл улучшить свою квалификацию? Есть тысячи систем, которые обновляют, и которые продолжают работать — весь вопрос лишь в аккуратности процесса и дотошности контроля качества обновления.
А если 10 серверов, все остановить? А если 24\7 клиенты ходят? А если не все серверы останавливать, то что станет когда база уже обновится, а не везде еще новый код работает?
Да, проблемы решаемые, но небесплатно. Причем чем больше проблема с обновлением клиентов для СУБД, тем выгоднее логика на стороне СУБД.
Тут нет универсального подхода.
B>Вопрос "обновления" — вопрос ни о чём, с тем же успехом можно обсудить подсветку T-SQL в студии — это далеко не самое интересное в вопросе "хранимки vs код".
По секрету скажу — установка и обновления это основные проблемы во всей разработке. В совокупности гораздо сложнее, чем все написание кода на ЯВУ обычно.
Здравствуйте, gandjustas, Вы писали:
B>>Вопрос "обновления" — вопрос ни о чём, с тем же успехом можно обсудить подсветку T-SQL в студии — это далеко не самое интересное в вопросе "хранимки vs код". G>По секрету скажу — установка и обновления это основные проблемы во всей разработке. В совокупности гораздо сложнее, чем все написание кода на ЯВУ обычно.
Ну если никто не хочет обсуждать возможности хранимок, а уходит в обновления, наверное пора перейти в другой топик?
Я и без секретов скажу: написание логики на T-SQL/PL-SQL — это адЪ (по ср. с абсолютно любым ЯВУ — Java, C#, C++). Поэтому если кто-то пытается опять как в добрые 80-ые понаписать этого хлама-на-выкид — ради бога, только руководство предупредите что "деньги будут просраны, проект — загнётся".
Сейчас даже на элементарный C# нужно тестировать каждого первого, чтобы не брать 1-месячных самоучек, а уж T-SQL... это уже "Кобол сегодняшнего дня", я б на такую тухлятину не поставил и рубля.
Здравствуйте, Sinclair, Вы писали:
S>Ещё раз вчитайтесь в вопрос: как вы собираетесь свести обновление 1500 клиентов в 30 офисах и 11 часовых поясах к "секундному делу"?
Что то мне подсказывает, что 1500 клиентов в 30 офисах, которые напрямую лезут в БД без какого либо middleware — отличный способ прострелить себе яйца ногу, вне зависимости от количества хранимок.
Здравствуйте, btn1, Вы писали:
B>Здравствуйте, gandjustas, Вы писали:
B>>>Вопрос "обновления" — вопрос ни о чём, с тем же успехом можно обсудить подсветку T-SQL в студии — это далеко не самое интересное в вопросе "хранимки vs код". G>>По секрету скажу — установка и обновления это основные проблемы во всей разработке. В совокупности гораздо сложнее, чем все написание кода на ЯВУ обычно.
B>Ну если никто не хочет обсуждать возможности хранимок, а уходит в обновления, наверное пора перейти в другой топик?
Какие возможности тебя интересуют?
B>Я и без секретов скажу: написание логики на T-SQL/PL-SQL — это адЪ (по ср. с абсолютно любым ЯВУ — Java, C#, C++).
Тебе все равно придется делать одни и те же запросы на T-SQL/PL-SQL. Какая еще логика тебя интересует?
Здравствуйте, gandjustas, Вы писали:
B>>Ну если никто не хочет обсуждать возможности хранимок, а уходит в обновления, наверное пора перейти в другой топик? G>Какие возможности тебя интересуют?
Я ж уже спрашивал: Есть ли какие-то особенные качества хранимок, ну просто настолько необходимые, что в 21 веке нужно писать логику при помощи СУБД-шного языка?
(это в противопоставление к коду на обычном ЯВУ, который лежит в "моделях")
B>>Я и без секретов скажу: написание логики на T-SQL/PL-SQL — это адЪ (по ср. с абсолютно любым ЯВУ — Java, C#, C++). G>Тебе все равно придется делать одни и те же запросы на T-SQL/PL-SQL. Какая еще логика тебя интересует?
Я и говорю: при одинаковых SQL запросах, есть ли какая-то серьёзная причина выбирать хранимки вместо нативного кода?
Здравствуйте, btn1, Вы писали:
B>Здравствуйте, gandjustas, Вы писали:
B>>>Ну если никто не хочет обсуждать возможности хранимок, а уходит в обновления, наверное пора перейти в другой топик? G>>Какие возможности тебя интересуют?
B>Я ж уже спрашивал: Есть ли какие-то особенные качества хранимок, ну просто настолько необходимые, что в 21 веке нужно писать логику при помощи СУБД-шного языка? B>(это в противопоставление к коду на обычном ЯВУ, который лежит в "моделях")
тебе уже неоднократно ответили — инкапсуляция, которая дает более простое обновление и поддержку при большом количестве различных клиентов, а также поддерживает целостность данных в сложных случаях. Последнее достигается скорее триггерами и представлениями, а не хранимками.
B>>>Я и без секретов скажу: написание логики на T-SQL/PL-SQL — это адЪ (по ср. с абсолютно любым ЯВУ — Java, C#, C++). G>>Тебе все равно придется делать одни и те же запросы на T-SQL/PL-SQL. Какая еще логика тебя интересует?
B>Я и говорю: при одинаковых SQL запросах, есть ли какая-то серьёзная причина выбирать хранимки вместо нативного кода?
Да, см выше.
Разница по сути небольшая, именно потому что запросы одинаковые будут, а они составляют большую часть sql кода.
Здравствуйте, gandjustas, Вы писали:
G>тебе уже неоднократно ответили — инкапсуляция, которая дает более простое обновление и поддержку при большом количестве различных клиентов
Если не умеешь внимательно читать — злись на себя, а не упрекай. Для тех, кто в танке/с берушами/под косяком:
B>1. Даже если мы возьмём систему, где широко используют хранимки, в ней всё равно не избежать какой-то логики на стороне сервера приложений (рассматриваются только трёхзвенные системы как наиболее передовая архитектура). А значит "обновления хранимок" — лишь часть того, что нужно обновлять на сервере, т.е. мы по-любому не избегаем процедуры обновления сервера.
G>Неверно. Логику в базе можно инкасулировать настолько, что клиент многие изменения и не увидит.
Если ты собрался городить 3-звенку на вот этом маразме из хранимок, это не означает, что все поддерживают это мнение. Более того — архитектурно это верблюд. Сервер приложений для того и придумали, что СУБД — всего-лишь хранилище, причём заменяемое (в идеале) на любое другое (выбор оптимального или которое есть у клиента), а сервер приложений остаётся неизменным и не страдает от диалектов СУБД. Короче, ответ "так легче обновляться" — слишком узкий и в плане 3-звенок вообще бессмысленный.
IT>Это ты всего лишь автоматизировал поиск костылей. Linq устраняет сами костыли. Если они у тебя где-то остались, то ты просто не сможешь скомпилировать приложение.
А можно вот так написать. Я устранил проблемы связанные с динамическим SQL, а LINQ всего лишь предлагает новую модель костылей. Всё же предлагаю вести диалог в более предметном ключе. Предлагаю сравнивать LINQ и автоматически проверяемый динамический SQL. Разве есть принципиальная разница: не скомпилируется или не пройдет CheckAllQueries?
Что касается рефакторинга одной кнопкой, то Москва не сразу строилась, прикрутить к моему подходу рефакторинг одной кнопкой тоже можно. Но, честно говоря, в наших проектах время, затраченное на переименование колонки или таблицы пока не настолько велико, чтобы получить видимый выигрыш от продолжения автоматизации рефакторинга.
Вопрос лишь в поддержке со стороны инструментов: ReSharper-а? Или есть принципиальные вопросы?
Отдельный вопрос про LINQ. Вопрос про ассоциации. Откуда они беруться? В реляционных СУБД никаких ассоциаций нет. Там нет такого понятия. Есть только ограничения для поддержания данных в согласованном состоянии. И только эту роль в реляционных СУБД играют внешние ключи. В запросах внешние ключи не используются (кстати, в dbforge отличный автокомплит по FK). Интересно задаться вопросом, почему за многолетнюю историю SQL не один из вендоров не ввел ассоциации, как термин, как элемент метаданных и как элемент синтаксиса SQL? Может оно и не очень востребовано? Может автокомплита по FK достаточно?
LINQ запросы по ассоциациям поддерживает. Поддерживает он ассоциации, потому что рожден в C#/VB, где отдельного понятия "ассоциации" тоже нет, есть свойства. Таким образом, надо ссылочные свойства сишарпа куда-нибудь промэпить в реляционную модель. Вопрос куда? И сколько телодвижений требуется от программиста? Как видим, вопрос про ассоциаци связан с тем, что мы исповедуем code first или database first? Code first по сути своей гибридный подход: часть базы определяется в C# коде, часть обычными командами DDL. А такая гибридизация, т.е. двойственность, сама может породить проблемы. Database first выглядит более логичным подходом. Тогда C# классы полностью автоматически генерируются по базе. Но как генерируются ассоциации? По FK? А вдруг мне придется снять ограничения целостности, и что мне переписывать все запросы?
Это я всё к чему. К тому, что если уж добавляется какая-то фича в инструментарий для разработчика, то пусть она добавляется по всему стеку, например, если мы используем реляционную СУБД и хотим добавить фичу "запросы по ассоциациям", то это должно быть поддержано и самой СУБД. Мэпинговый (ORM) подход почти наверняка содержит скрытую accidental complexity. Если язык СУБД плох, так давайте улучшать этот язык, а не городить мэпинги. Но, к сожалению, Хейлсберг не хочет just talk to a database:
We could've probably shipped something like LINQ much quicker if we said, "Let's just jam SQL in there or something that is totally SQL Server-specific, and we'll just talk to a database and then we'll have it," but it's not general enough to merit existence in a general-purpose programming language. You very quickly then become a domain-specific programming language, and you live and die by that domain. http://broadcast.oreilly.com/2009/03/an-interview-with-anders-hejls.html
Т.е. одни делают general-purpose язык, другие делают СУБД, а проблемы совместного использования оставляют прикладным разработчикам.
SqlCommand/SqlReader никакого мэпинга не требуют, работают с СУБД на ее родном языке. SqlCommand/SqlReader не поддерживают статическую проверку запросов? У меня такая проверка добавлена.
Кстати, почему в Java 8 сделали LINQ to Object и не сделали LINQ to Database? Вот мнение:
...
Do it "bottom-up", putting most focus on your SQL / relational domain model. In that case, use JDBC or jOOQ and again, transform your results using the Java 8 Streams API.
...
We need true SQL for relational database querying, and we need the Java 8 Streams API for functional transformations of in-memory collections. That's it. Go Java 8! http://tech.pro/blog/1689/does-java-8-still-need-linq-or-is-it-better-than-linq
НС>Потому что в языке нет механизма цитирования кода.
Почему C# 3.0 сделали недоцитирование, а в Java8 не сделали? Если бы речь шла о полноценном цитировании, как в Lisp, еще можно было понять. А так это недоцитирование, может поэтому и не сделали в Java8?
Здравствуйте, Alexander Polyakov, Вы писали:
НС>>Потому что в языке нет механизма цитирования кода. AP>Почему C# 3.0 сделали недоцитирование, а в Java8 не сделали?
Потому что и языки и люди, их разрабатывающие, разные, ваш КО.
Здравствуйте, btn1, Вы писали:
B>Здравствуйте, gandjustas, Вы писали:
G>>тебе уже неоднократно ответили — инкапсуляция, которая дает более простое обновление и поддержку при большом количестве различных клиентов
B>Если не умеешь внимательно читать — злись на себя, а не упрекай. Для тех, кто в танке/с берушами/под косяком:
B>
B>>1. Даже если мы возьмём систему, где широко используют хранимки, в ней всё равно не избежать какой-то логики на стороне сервера приложений (рассматриваются только трёхзвенные системы как наиболее передовая архитектура). А значит "обновления хранимок" — лишь часть того, что нужно обновлять на сервере, т.е. мы по-любому не избегаем процедуры обновления сервера.
Ты сам-то читать умеешь? На это уже отвечал. С логикой на стороне субд необходимости в обновлении сервера меньше. Кроме того код, не завязанный на хранение данных, обновлять проще. Код, который завязан на хранение вынужден поддерживать базу как до обновления, так и после.
G>>Неверно. Логику в базе можно инкасулировать настолько, что клиент многие изменения и не увидит.
B>Если ты собрался городить 3-звенку на вот этом маразме из хранимок, это не означает, что все поддерживают это мнение. Более того — архитектурно это верблюд.
Это слова ни о чем. Пусть верблюд, это лучше чем самописные утконосы.
B>Сервер приложений для того и придумали, что СУБД — всего-лишь хранилище, причём заменяемое (в идеале) на любое другое (выбор оптимального или которое есть у клиента), а сервер приложений остаётся неизменным и не страдает от диалектов СУБД.
Это кто тебе такую глупость сказал?
Трехзвенка появилась потому что веб пошел в массы. До веба трехзвенка была экзотикой и толком никто не знал зачем оно надо.
Если СУБД всего лишь хранилище, то почему её стоимость выше стоимости приложения? Особенно если посмотреть на оракл. А если столько платить, то какой смысл использовать как «всего-лишь хранилище». На практике «всего-лишь хранилище» обеспечивает целостность данных и конкурентный доступ, а также работает эффективно на таких объемах, что врукопашную повторить это нельзя за разумное время. Вот поэтому и пишут логику на стороне субд.
B>Короче, ответ "так легче обновляться" — слишком узкий и в плане 3-звенок вообще бессмысленный.
Ты сам себе противоречишь. Чем больше логики инкапсулировано внутри субд, тем проще поменять субд, ибо нет завязки на диалекты sql.
Здравствуйте, Alexander Polyakov, Вы писали:
IT>>Это ты всего лишь автоматизировал поиск костылей. Linq устраняет сами костыли. Если они у тебя где-то остались, то ты просто не сможешь скомпилировать приложение. AP>Я устранил проблемы связанные с динамическим SQL
Устранил? Не смеши мои тапочки.
Бери код и покажи проект, который автоматом проверит все запросы на корректность http://samsaffron.com/archive/2011/09/05/Digging+ourselves+out+of+the+mess+Linq-2-SQL+created
Не забываем что Linq проверяет все сам, без дополнительных телодвижений со стороны разработчика.
AP>Разве есть принципиальная разница: не скомпилируется или не пройдет CheckAllQueries?
Да, разница огромная. CheckAllQueries не работает с динмическим SQL.
Filter? filter = Filter.Suggested;
Option<string> search = "%test%";
var paging = BatchQuery<Paging<ITagSynonym, int?>>.New(new {
filter, user = new {IsAnonymous = false, IsModerator = false, Id = 1}, tagScoreRequiredToVote = 10,
search, tab = Tab.Newest, start = 0, pageSize = 20
}, @"
SELECT TagSynonyms.Id, SourceTagName, TargetTagName, OwnerUserId, ApprovalDate, TagSynonyms.CreationDate,
AutoRenameCount, Score, SourceTags.Id AS SourceTagId, TargetTags.Id AS TargetTagId, Users.DisplayName
@MainQuery()
ORDER BY
@switch (tab) {
case Tab.Newest:
@:CreationDate DESC, Id
break;
case Tab.Master:
@:TargetTagName ASC, AutoRenameCount DESC, Id
break;
case Tab.Synonym:
@:SourceTagName ASC, AutoRenameCount DESC, Id
break;
case Tab.Votes:
@:Score DESC, TargetTagName ASC, AutoRenameCount DESC, Id
break;
case Tab.Creator:
@:DisplayName, Id
break;
case Tab.Renames:
@:AutoRenameCount DESC, TargetTagName, Id
break;
}
OFFSET @start ROWS FETCH NEXT @pageSize ROWS ONLY
OPTION (OPTIMIZE FOR (@start = 0, @pageSize = 20));
SELECT COUNT(*) @MainQuery();
@helper MainQuery() {<text>
FROM TagSynonyms
LEFT JOIN Tags SourceTags ON SourceTagName = SourceTags.Name
LEFT JOIN Tags TargetTags ON TargetTagName = TargetTags.Name
LEFT JOIN Users ON Users.Id = OwnerUserId
WHERE 1 = 1
@switch (filter) {
case Filter.Active:
@:AND ApprovalDate IS NOT NULL
break;
case Filter.Suggested:
@:AND ApprovalDate IS NULL
if (!user.IsAnonymous && !user.IsModerator) {
@:AND TargetTagName IN (@TargetTagNames())
}
break;
case Filter.Merge:
@:AND ApprovalDate IS NOT NULL AND ISNULL(SourceTags.Count, 0) > 0
break;
}
@if (search.HasValue) {
@:AND (SourceTagName LIKE @search OR TargetTagName LIKE @search)
}
</text>}
@helper TargetTagNames() {<text>
SELECT Name
FROM Tags
WHERE Id IN (SELECT Id
FROM UserTagTotals
WHERE UserId = @user.Id
AND TotalAnswerScort > @tagScoreRequiredToVote)
</text>}").Result();
var rows = paging.Rows;
var count = paging.Count;
G>Да, разница огромная. CheckAllQueries не работает с динмическим SQL.
Ты читать не умеешь? Там всё начинается с динамического SQL.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>>>Я устранил проблемы связанные с динамическим SQL G>>Устранил? Не смеши мои тапочки. G>>Бери код и покажи проект, который автоматом проверит все запросы на корректность http://samsaffron.com/archive/2011/09/05/Digging+ourselves+out+of+the+mess+Linq-2-SQL+created AP>В чем проблема?
Еще раз: Весь код (проект), который проверяет все возможные запросы при компиляции.
G>>Да, разница огромная. CheckAllQueries не работает с динмическим SQL. AP>Ты читать не умеешь? Там всё начинается с динамического SQL.
И заканчивается тонной тестов, которые не явлются проверкой при компиляции.
Как раз читать я умею, даже умею читать то, что явно не написано.
G>>>Да, разница огромная. CheckAllQueries не работает с динмическим SQL. AP>>Ты читать не умеешь? Там всё начинается с динамического SQL. G>И заканчивается тонной тестов, которые не явлются проверкой при компиляции. G>Как раз читать я умею, даже умею читать то, что явно не написано.
Тесты генерируются автоматически, человек в этом не участвует, в чем отличие от компиляции?
Здравствуйте, Alexander Polyakov, Вы писали:
G>>>>Да, разница огромная. CheckAllQueries не работает с динмическим SQL. AP>>>Ты читать не умеешь? Там всё начинается с динамического SQL. G>>И заканчивается тонной тестов, которые не явлются проверкой при компиляции. G>>Как раз читать я умею, даже умею читать то, что явно не написано. AP>Тесты генерируются автоматически, человек в этом не участвует, в чем отличие от компиляции?
Code talks, bullshit walks. Выложи проект.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Code talks, bullshit walks. Выложи проект. AP>Для публичного релиза надо много почистить, но вот выложил. Смотреть Demo\Program.cs.
А где же проверка при компиляции?
Убрал скобку, получил TEI с абсолютно невнятным сообщением что не так.
Работает дико медленно. На этот запрос уходит 2 секунды на тесты, в реальном приложении с сотнями запросов можно долго ждать.
Нереальное количество кода, не знаю что из этого пишется руками, но выглядит страшно.
Как это будет работать при декомпозиции? Когда разные части запроса в разных сборках.
Как я понял параметры пишутся прямо в тело зарпоса, это вызовет plan cache pollution на sql server. Для продакшена нерабочее решение по факту.
G>Убрал скобку, получил TEI с абсолютно невнятным сообщением что не так.
Пости сюда полную распечатку исключения. Объясню, что это сообщение означает.
G>Работает дико медленно. На этот запрос уходит 2 секунды на тесты, в реальном приложении с сотнями запросов можно долго ждать.
Это известное поведение, связано с Roslyn Preview. В Known issues для Roslyn написано:
o After starting Visual Studio, the first build may be slower than expected due to the compilers not being NGen’d in the Preview.
У меня на машине Roslyn установлен через сетап, поэтому он прошел NGen. Можно самому прогнать NGen из консоли (с этим я тоже экспериментировал). У меня на машине CheckAllQueries выполняется 229ms, причем существенную часть занимает открытие первого connection-а. На проекте с сотнями запросов CheckAllQueries укладывается в полторы секунды.
G>Нереальное количество кода, не знаю что из этого пишется руками, но выглядит страшно.
Я думал, ты просил код, чтобы читать его. Руками ничего не пишется. То, что ты называешь "нереальное количество кода" уйдет в библиотеку, я ж предупредил, коду требуется серьезная чистка. Ты смотри, где заточка на конкретный запрос? Такой заточки нет.
G>Как это будет работать при декомпозиции? Когда разные части запроса в разных сборках.
Выложил пример.
G>Как я понял параметры пишутся прямо в тело зарпоса, это вызовет plan cache pollution на sql server. Для продакшена нерабочее решение по факту.
Твой механизм понимания дал сбой, чтобы убедиться в этом, достаточно посмотреть в SQL Profiler и увидеть там параметризованные запросы.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Убрал скобку, получил TEI с абсолютно невнятным сообщением что не так. AP>Пости сюда полную распечатку исключения. Объясню, что это сообщение означает.
Даже не хочу связываться, лучше я Linq буду пользоваться.
G>>Как я понял параметры пишутся прямо в тело зарпоса, это вызовет plan cache pollution на sql server. Для продакшена нерабочее решение по факту. AP>Твой механизм понимания дал сбой, чтобы убедиться в этом, достаточно посмотреть в SQL Profiler и увидеть там параметризованные запросы.
Вижу, не туда смотрел.
G>Под отладчиком дико тормозит...
У меня такое поведение не воспроизводится. Под отладчиком тормозов не наблюдается. Возможно, это также связано с тем, что сборки Roslyn не прошли NGen. Надо на чистой виртуалке будет погонять.
Или может ты опять не туда смотришь...
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Под отладчиком дико тормозит... AP>У меня такое поведение не воспроизводится. Под отладчиком тормозов не наблюдается. Возможно, это также связано с тем, что сборки Roslyn не прошли NGen. Надо на чистой виртуалке будет погонять. AP>Или может ты опять не туда смотришь...
Часы точно идут. Почти 10 сек на прогон тестов одного сложного запроса.
Здравствуйте, btn1, Вы писали:
B>Потому что те, кому я отвечаю, съехали в какие-то дебри и толкают мысли, которые интересны только им. Может у меня что-то с русским языком, но я с трудом нахожу общность между моим B>
Это потому, что вы пренебрегаете существенными деталями.
B>Во-первых, речь вообще не про апгрэйд, а про принципиальные возможности хранимок и кода на ЯВУ внутри модели.
Вы задаёте общий вопрос "зачем могут быть нужны хранимки", но почему-то ожидаете ответа только в одной узкой области. Но выбор способа реализации не исчерпывается рассмотрением характеристик функциональности и производительности.
B>Я отвечу на этот второстепенный вопрос, но продолжать "тему обновлений" не вижу смысла — вы ушли от главного и мусолите детали. B>1. Даже если мы возьмём систему, где широко используют хранимки, в ней всё равно не избежать какой-то логики на стороне сервера приложений (рассматриваются только трёхзвенные системы как наиболее передовая архитектура).
Вы опять не читаете то, что вам пишут. Трёхзвенными системами мир не исчерпывается. Но если мы переходим к трёхзвенке, аргумент про 1500 клиентов исчезает, т.к. у базы остаётся только один клиент.
Тогда причин использовать хранимки остаётся мало. Например, для MS SQL Server объективных причин не остаётся совсем.
B>2. Если у вас 30 филиалов, очевидно, что этим занимается далеко не один человек. Распределить задачу обновления — административная хрень.
Не стоит преуменьшать важность административных хреней. Если вы разработчик, то администраторы — ваши клиенты. В нашем насквозь прогнившем коммерческом мире класть болт на потребности клиентов — не лучшая идея.
B>3. Если для вас "остановить сервер, обновить, запустить" — проблема, то наверное есть смысл улучшить свою квалификацию?
Для меня — нет, не проблема. А в какой-нибудь телекоммуникационной компании минута простоя удачно выбранного сервера обходится примерно в $2M. С этой точки зрения есть принципиальная разница в остановке сервера на 30 секунд и на 30 минут.
B>Вопрос "обновления" — вопрос ни о чём, с тем же успехом можно обсудить подсветку T-SQL в студии — это далеко не самое интересное в вопросе "хранимки vs код".
Ну, я догадываюсь, что конкретно вас может интересовать. Хотя намеренно сужать область своих интересов — странно.
Ок, поясню в рамках выбранной вами модели (трёхзвенное приложение): для "взрослых" СУБД различий практически нет. Потому что возможности интерактивного и процедурного диалектов совпадают. А вот, скажем, в interbase до сих пор есть три разных диалекта. В интерактивном SQL (т.е. в том, который уезжает с клиента) нету процедурных расширений — т.е. никаких if или циклов. Все ветвления придётся делать на стороне клиента, а это — раундтрипы. В особо удачных случаях время исполнения запроса может только из-за этого вырасти в разы. А это, в свою очередь, означает удлинение удержания блокировок, и оказывает каскадный эффект на производительность. Понятно, не в лучшую сторону.
Вот в таких случаях хранимые процедуры по-прежнему объективно выгодны.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Что то мне подсказывает, что 1500 клиентов в 30 офисах, которые напрямую лезут в БД без какого либо middleware — отличный способ прострелить себе яйца ногу, вне зависимости от количества хранимок.
Ну, это и есть причина, по которой от client-server девяностых ведущие собаководы перешли к трёхзвенке
Тем не менее, как мы знаем, старые приложения не умирают. Просто новые пишутся с такой скоростью, что их процент растёт
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
B>>1. Даже если мы возьмём систему, где широко используют хранимки, в ней всё равно не избежать какой-то логики на стороне сервера приложений (рассматриваются только трёхзвенные системы как наиболее передовая архитектура). А значит "обновления хранимок" — лишь часть того, что нужно обновлять на сервере, т.е. мы по-любому не избегаем процедуры обновления сервера.
В нормальной современной трёхзвенке логика в триггерах и хранимках — адское зло.
Потому, что бизнес-логика распиливается на две части, без каких-либо очевидных правил выбора.
При написании кода разработчик мечется между тем, чтобы написать новую хранимку, поправить старую, или просто зафигачить код на шарпе. Править базу — страшно, потому что в отличие от кода на шарпе, никто тебе не покажет все места использования. В итоге рождаются уродцы типа "давайте вызовем хранимку, а потом выкинем все результаты, кроме первого", убивающие производительность.
Рефакторинг такого слоёного пирожка — тоже кошмар.
Ну и вообще — все случаи боевого применения такой ерунды, которые видел лично я, сводятся к хранимкам для CRUD. За такое вообще надо сразу приговаривать по статье 332.3 УК, за неимением более подходяшей статьи. А если такое встречется в коммерческом проекте — то по законам военного времени.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Кстати, почему в Java 8 сделали LINQ to Object и не сделали LINQ to Database? Вот мнение
Оно неправильное. Весь ответ в том, что Java разрабатывают кретины. Сначала 5 лет делали generic'и, и умудрились их сделать самым кривым из возможных способов. Он оказался:
1) Обратно несовместим — код с generic'ами для JRE 1.5 не мог работать на JRE 1.4
2) С type erasure, который изначально делался в попытках сохранить совместимость с пунктом 1.
Потом Sun начал делать лямбы, которые им пришлось осиливать аж 10 лет. Это уже была просто полнейшая некомпетентность сразу по всем направлениям.
Здравствуйте, Cyberax, Вы писали:
C>Оно неправильное. Весь ответ в том, что Java разрабатывают кретины. Сначала 5 лет делали generic'и, и умудрились их сделать самым кривым из возможных способов. Он оказался: C>1) Обратно несовместим — код с generic'ами для JRE 1.5 не мог работать на JRE 1.4 C>2) С type erasure, который изначально делался в попытках сохранить совместимость с пунктом 1.
А почему код с generic'ами для JRE 1.5 не мог работать на JRE 1.4, если типы херятся?
Здравствуйте, Sinclair, Вы писали:
S>Ну и вообще — все случаи боевого применения такой ерунды, которые видел лично я, сводятся к хранимкам для CRUD. За такое вообще надо сразу приговаривать по статье 332.3 УК, за неимением более подходяшей статьи.
По моему статья 228 отлично подойдет для таких случаев.
Здравствуйте, Jack128, Вы писали:
C>>1) Обратно несовместим — код с generic'ами для JRE 1.5 не мог работать на JRE 1.4 C>>2) С type erasure, который изначально делался в попытках сохранить совместимость с пунктом 1. J>А почему код с generic'ами для JRE 1.5 не мог работать на JRE 1.4, если типы херятся?
Два ответа:
1) Версия байт-кода у JDK 1.5 другая, так что JDK 1.4 их не понимает.
2) Пришлось так сделать из-за того, что массивы позволяют обходить типизацию.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Sinclair, Вы писали:
S>>Ну и вообще — все случаи боевого применения такой ерунды, которые видел лично я, сводятся к хранимкам для CRUD. За такое вообще надо сразу приговаривать по статье 332.3 УК, за неимением более подходяшей статьи. G>По моему статья 228 отлично подойдет для таких случаев.
Ну, формально-то мы говорим о 273/2, но по смыслу нужна статья из 33 главы, но в нынешних редакциях её нет.
А если по главе 25, то надо инкриминировать 230, 237 и 238.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Cyberax, Вы писали:
C>Оно неправильное. Весь ответ в том, что Java разрабатывают кретины. Сначала 5 лет делали generic'и, и умудрились их сделать самым кривым из возможных способов. Он оказался: C>1) Обратно несовместим — код с generic'ами для JRE 1.5 не мог работать на JRE 1.4 C>2) С type erasure, который изначально делался в попытках сохранить совместимость с пунктом 1.
Куда смешнее другое — в дотнете дженерики сделали с существенными ограничениями и ввели констрейны, так как там дженерик компилируется как дженерик, а конкретные аргументы в него подставляются в рантайме. Это дает свои плюсы, но накладывает ряд ограничений. В джаве же дженерики почти исключительно компиляторный сахар, так что всякую фигню типа использования параметра типа в качестве базового класса реализовать было несложно. Вобщем, карго-культ какой то.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>А можно вот так написать. Я устранил проблемы связанные с динамическим SQL,
Динамического SQL по ссылке не найдено. Ты не путаешь термин "динамический" с "plain"?
AP>а LINQ всего лишь предлагает новую модель костылей.
Как раз костыль находится по твоей ссылке. Похожий способ, только гораздо круче использовался ещё в примерах к самым первым версиям Nemerle. Но в результате не прижился и так и остался на уровне примера. Причин тому много, но все они так или иначе завязаны на отсутствие типизации. Автоматическая проверка корректности SQL — это хорошо, но это лишь решение одной проблемы, которая в случае LINQ даже не рассматривается.
AP>Всё же предлагаю вести диалог в более предметном ключе. Предлагаю сравнивать LINQ и автоматически проверяемый динамический SQL. Разве есть принципиальная разница: не скомпилируется или не пройдет CheckAllQueries?
Конечно, есть. "Не скомпилируется" выдаёт тебе сразу место проблемы и рассказывает что не так. Check говорит, что не шмагла где-то там, иди, мужик, разбирайся.
AP>Что касается рефакторинга одной кнопкой, то Москва не сразу строилась, прикрутить к моему подходу рефакторинг одной кнопкой тоже можно. Но, честно говоря, в наших проектах время, затраченное на переименование колонки или таблицы пока не настолько велико, чтобы получить видимый выигрыш от продолжения автоматизации рефакторинга.
Во-первых, я очень сильно сомневаюсь, что прикрутить рефакторинг к твоему коду можно. Во-вторых, давай не забывать про навигацию. Переименовывать поле может нужно и не так часто, но искать его использование, получать по нему информацию требуется постоянно.
AP>Вопрос лишь в поддержке со стороны инструментов: ReSharper-а? Или есть принципиальные вопросы?
Думаю, будут проблемы. Для решарпера твой SQL — это всего лишь строковый литерал. Попробуй заставить его думать по-другому.
AP>Отдельный вопрос про LINQ. Вопрос про ассоциации. Откуда они беруться? В реляционных СУБД никаких ассоциаций нет. Там нет такого понятия. Есть только ограничения для поддержания данных в согласованном состоянии. И только эту роль в реляционных СУБД играют внешние ключи. В запросах внешние ключи не используются (кстати, в dbforge отличный автокомплит по FK). Интересно задаться вопросом, почему за многолетнюю историю SQL не один из вендоров не ввел ассоциации, как термин, как элемент метаданных и как элемент синтаксиса SQL?
Надеюсь, претензии к ассоциациям у тебя возникли лишь из желания поспорить. ER диаграмы используются для проектирования СУБД уже десятки лет. Тот факт, что SQL не поддерживает чего-то подобного ассоциациям проблема не ассоциаций, а SQL. Тем не менее любой нормальный дизайн БД без связей между таблицами не обходится, просто потому, что такой дизайн бесполезен. Ассоциация — это всего лишь навсего материализация связи между таблицами, крайне полезная штука, позволяющая экономить тонны кода. При проектировании связи между таблицами определяются всегда, иметь такое ещё и в коде очень круто. И, кстати, некоторые вендоры таки используют ассоциации в своих диалектах SQL.
AP>Может оно и не очень востребовано? Может автокомплита по FK достаточно?
SQL один из самых древних из используемых сегодня языков. Это правда. Но так же он и один из самых консервативных. То же самое относится и к средствам разработки на SQL. Они толком не развиваются и не изменяются годами. Даже наиболее продвинутый тул — Management Studio пребывает почти в одном и том же виде уже десяток лет. За это время в C# появились дженерики, поддержка функционального программирования, LINQ и всерьёз заговорили о реальном метапрограммировании. Т.е. C# пережил в своём развитии несколько поколений, а SQL ни одного. Почему так? Виноват ли в этом C# и LINQ?
AP>LINQ запросы по ассоциациям поддерживает. Поддерживает он ассоциации, потому что рожден в C#/VB, где отдельного понятия "ассоциации" тоже нет, есть свойства. Таким образом, надо ссылочные свойства сишарпа куда-нибудь промэпить в реляционную модель. Вопрос куда? И сколько телодвижений требуется от программиста?
Количество требуемых телодвижений равняется нулю. Ассоциации генерируются автоматически по метаданным из БД.
AP>Как видим, вопрос про ассоциаци связан с тем, что мы исповедуем code first или database first? Code first по сути своей гибридный подход: часть базы определяется в C# коде, часть обычными командами DDL. А такая гибридизация, т.е. двойственность, сама может породить проблемы. Database first выглядит более логичным подходом. Тогда C# классы полностью автоматически генерируются по базе. Но как генерируются ассоциации? По FK? А вдруг мне придется снять ограничения целостности, и что мне переписывать все запросы?
Иногда приходится делать и такое. В этом случае ассоциацию можно дописать русками.
AP>Т.е. одни делают general-purpose язык, другие делают СУБД, а проблемы совместного использования оставляют прикладным разработчикам.
Вообще-то Хейльсберг говорит немного о другом. Ну да фиг с ним.
AP>SqlCommand/SqlReader никакого мэпинга не требуют, работают с СУБД на ее родном языке. SqlCommand/SqlReader не поддерживают статическую проверку запросов? У меня такая проверка добавлена.
Я же говорю. Проверка SQL — это здорово, ты решил одну единственную проблему, которой в случае использования LINQ не существует вообще.
LINQ, конечно, можно и нужно критиковать, это вовсе не идеальный иструмент. Идеальным может стать специализированный встроенный DSL, который транслируется компилятором не в примитивы исполняемого кода, а в термины, близкие к SQL, готовые или почти готовые к исполнению. Тогда можно будет получить очень эффективный и совместимый с SQL инструмент. Но для этого нужно дождаться, когда у разработчиков компиляторов соответсвующим образом повернуться мозги и они дадут нам в руки возможность, позволяющую подружить друг с другом разные языки. Пока же это только мечты. Тем не менее, LINQ — это самый прямой путь к идеалу на сегодняшний день. Ты пытаешься подобраться к этому идеалу с другой стороны, со стороны SQL, а не со стороны компилятора. Сомневаюсь, что у такого подхода есть хоть какие-то перспективы.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Это не делает чести ни банкам, ни биржам. Местами они так, конечно, работают, но видно невооруженным взглядом, что очень плохо работают, медленно и неэффективно. По мере сил мы эту ситуацию меняем и надо признать не без успеха.
Вообще-то в последние лет 5 идет полный отказ вообще от каких-либо технологий "управляемых VM", бо они работают плохо и дают крайне низкую фактическую статистику надежности.
V>>"Полубожественный" доставило. Но это следовало понимать не как божественный, а как "бинго!" для оппонента, от которого за версту несет "поколением next". У меня возникла догадка, она подтвердилась. Всего-то и делов. Другой мир, прям. Других слов нет.
IT>Ты считаешь, что лучше, когда от тебя за версту несёт нафталином и гниловатым запахом разлагающихся технологий? Прямо некрофилизм какой-то. Фу. Ужас.
Я считаю, что если человек не решал сложные задачи, то как бы смешно смотреть, как он учит жизни других. Всё, что может этот человек я могу делать не подключая мозг и даже будучи сильно пьян. Я пытался с ним как-то обсуждать работу дотнетной VM, он даже толком не понимает, как она работает. ))
Да и тебя несет малость. Сейчас не 2005-й год, чтобы так задорно петь дифирамбы дотнету — это нелепо смотрится в 2014-м. Поезд уже ушел. Технология в течении 10 лет показывала себя как ненадежная и неэффективная. Это по-факту попыток использования на крупнейших мировых биржах и банках. Сама платформа еще сырая и ты, как программист, тут бессилен, бо это вне твоей компетенции — ты лишь пользователь платформы. Определённую нишу она заняла — это там, где надо неторопливо выдавать что-то в веб на странички или как веб-сервисы или через родственные веб-ориентированные АПИ. Это ВСЁ! Т.е. из промышленного применения технологии — действительно всё! Там же, где требуется быстро и надежно — прямо на сегодня оттуда сие недоразумение вымыто, как и джава. Увы, сие медицинский факт. И до устаревания этого факта должно пройти примерно десяток лет, не меньше... чтобы критическая масса поколения next превысила опыт потери просто тонн денег и была выполнена еще одна попытка в этом направлении.
И не надо тут пальцы вейром насчет "по мере сил мы эту ситуацию меняем и надо признать не без успеха". Это всё введение в заблуждение непосвящённых читателей. Я прекрасно в курсе ЧТО ИМЕННО могли доверить пилить на дотнете, если речь о биржах и банках.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, IT, Вы писали:
IT>>Это не делает чести ни банкам, ни биржам. Местами они так, конечно, работают, но видно невооруженным взглядом, что очень плохо работают, медленно и неэффективно. По мере сил мы эту ситуацию меняем и надо признать не без успеха.
V>Вообще-то в последние лет 5 идет полный отказ вообще от каких-либо технологий "управляемых VM", бо они работают плохо и дают крайне низкую фактическую статистику надежности.
Это только в твоей голове идет. А по факту почти 100% веб-сайтов используют «управляемые вм», почти 100% line-of-business систем от crm до складского учета и управления персоналом. Процессинг крупнейших банков написан на java, android и windows phone приложения по большей части на java и .net. Самый массовый почтовый сервер — exchange написан на .net
QL>NotSupportedException: "Explicit construction of entity type '...' in query is not allowed."
Это linq2sql? у меня работает прекрасно, без замечаний, генерит такой же результат как и groupJoin — все по честному.
Здравствуйте, vdimas, Вы писали:
V>Вообще-то в последние лет 5 идет полный отказ вообще от каких-либо технологий "управляемых VM", бо они работают плохо и дают крайне низкую фактическую статистику надежности.
Кажется, я начинаю догадываться. Ты про какую-то другую альтернативную реальность, я прав?
V>Да и тебя несет малость. Сейчас не 2005-й год, чтобы так задорно петь дифирамбы дотнету — это нелепо смотрится в 2014-м. Поезд уже ушел. Технология в течении 10 лет показывала себя как ненадежная и неэффективная.
Не стоит рассуждать о дотнете, который был в 2005-м году сегодня, когда на дворе 2014-й. Поставь новую версию и убедись сам.
V>Это по-факту попыток использования на крупнейших мировых биржах и банках.
Опять рупь за сто Я работаю в крупнейшем мировом банке и в данный момент занимаюсь миграцией одной системы с "супернадёжного и суперэффективного" железа и софта на .NET. Причём именно её процессинговой, серверной части. Морда и так уже давно написана на .NET.
V>Сама платформа еще сырая и ты, как программист, тут бессилен, бо это вне твоей компетенции — ты лишь пользователь платформы.
Всё же обнови свою версию .NET на более свежую.
V>Определённую нишу она заняла — это там, где надо неторопливо выдавать что-то в веб на странички или как веб-сервисы или через родственные веб-ориентированные АПИ. Это ВСЁ! Т.е. из промышленного применения технологии — действительно всё! Там же, где требуется быстро и надежно — прямо на сегодня оттуда сие недоразумение вымыто, как и джава. Увы, сие медицинский факт. И до устаревания этого факта должно пройти примерно десяток лет, не меньше... чтобы критическая масса поколения next превысила опыт потери просто тонн денег и была выполнена еще одна попытка в этом направлении.
Одно из двух. Либо ты говоришь о софте, валовое количество которого не превышает пол процента, либо ты действительно из другой альтернативной реальности. В моей практике нестабильную работу приложений, написанных на .NET, можно пересчитать по пальцам одной руки и все они связаны либо с кривым нативным кодом, либо с кривыми руками программистов. Про эффективность я вообще молчу. На 80% процентов она определяется архитектурой приложения и небольшое отставание .net от нативного кода как правило легко компенсируется за счёт более высокого уровня технологии.
V>И не надо тут пальцы вейром насчет "по мере сил мы эту ситуацию меняем и надо признать не без успеха". Это всё введение в заблуждение непосвящённых читателей. Я прекрасно в курсе ЧТО ИМЕННО могли доверить пилить на дотнете, если речь о биржах и банках.
Дружище, я тебя хорошо понимаю. Последние несколько лет жизни ты потратил, находясь в плену иллюзий и домыслов, среди ветхих и безнадёжно устаревших технологий. И тебе трудно осознавать, что все эти годы потрачены зря. Но тебе придётся смириться. Не ты первый. Кто-то когда-то считал, что мир покоится на трёх слонах, кто-то утверждал, что 640KB памяти компьютеру хватит до скончания веков. Но технический прогресс остановить пока не получилось ни у кого.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
V>>Это по-факту попыток использования на крупнейших мировых биржах и банках. IT>Опять рупь за сто Я работаю в крупнейшем мировом банке и в данный момент занимаюсь миграцией одной системы с "супернадёжного и суперэффективного" железа и софта на .NET. Причём именно её процессинговой, серверной части. Морда и так уже давно написана на .NET.
Я никогда не работал на крупнейших банках — но только мой опыт 8-ми летний в вендорах банковского софта, показал, что все к уже тому времени когда я влился в это дело — перешли на дотнет (2006 год).
А на самом деле пацаны начали пробовать .NET ещё в бетах. И пока плюсники там всё ещё отлаживали свои формы — и они жутко маргали — по факту получилось, что нет был принят и до сих пор позиций не сдает. Если где-то существуют не дотнет приложения — то только legacy.
Я за свою опыт — самолично перевел карточный процессинг с легаси C/C++ на дотнет. И кстати, жалоб в итоге стало меньше, а точнее — пропали совсем. Потому что тот бред что был в C/C++ (и это не проблема языка, это проблема сложности поддержки, и разрешения проблем) — никуда не годился. Можно было часами медитировать, и медитировали по факту в сумме не одну сотню часов — и всё равно стабильной работы не добились. А вот легаси версия обросла процессом-креш-хэндлером со снятием минидампов и прочего. Только оно никак не окупилось — дампы показали, что креш происходит, из-за того, что environment уже запорчен, другими процессами, которые успешно отработали (когда?, часом раньше, или только что?). Короче говоря — в задаче где всё, что нужно получить сообщение, прогнать его через HSM с пристрастием — обработать и ответить — упасть не возможно. Я в нетной версии даже защитился от кривых дров HSM, и в случае buffer overrun/underrun — заложил жесткий FailFast. И... как и ожидалось — ну нет этого.
Так что в общем, Игорь, — люто плюсую.
PS: Я давно развязался с этими штуками. Теперь больше направлен на американский, и тоже банковский рынок. Как ни странно — там тоже везде используют дотнет.
AP>>... устранил проблемы связанные с динамическим SQL, IT>Динамического SQL по ссылке не найдено. Ты не путаешь термин "динамический" с "plain"?
Хм..., попытаюсь понять, почему ты не нашел по ссылке динамического SQL. Вот здесь
у Sinclair в пункте 2 динамический SQL или нет? НС>Нет. Там попытка его замены статическим (фиговая).
Это не динамический SQL?
2. Клеим строку динамически. Не очень важно — внутри SQL или снаружи:
q = 'select * from orders where 1=1 '
if (@shipDateFrom is not null)
q = q + 'AND where ShippedDate >= @shipDateFrom '
if (@shipDateTo is null)
q = q + 'AND ShippedDate <= @shipDateTo '
exec(q, @shipDateFrom, @shipDateTo);
Здравствуйте, Alexander Polyakov, Вы писали:
IT>>Динамического SQL по ссылке не найдено. Ты не путаешь термин "динамический" с "plain"? AP>Хм..., попытаюсь понять, почему ты не нашел по ссылке динамического SQL. Вот здесь
НС>С точки зрения клиента БД — нет, не динамический.
С точки зрения СУБД это динамический SQL. Это общепринятая трактовка термина “динамический SQL”. Именно этой трактовкой я и пользуюсь.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Ты хочешь абстрагироваться от СУБД?
Я хочу сказать, что с точки зрения клиентской библиотеки этот код статический. По определению — потому что текст запроса не зависит от значений, вычисляемых в рантайме. Все строго, в математическом смысле формально.
q = 'select * from orders where 1=1 '
if (@shipDateFrom is not null)
q = q + 'AND where ShippedDate >= @shipDateFrom '
if (@shipDateTo is null)
q = q + 'AND ShippedDate <= @shipDateTo '
exec(q, @shipDateFrom, @shipDateTo);
НС>... потому что текст запроса не зависит от значений, вычисляемых в рантайме. Все строго, в математическом смысле формально.
Как же не зависит, значение shipDateFrom получается из того, что пользователь ввел в поле ввода. Если пользователь ничего не ввел, то shipDateFrom равно null.
Если пользователь ничего не ввел, текст запроса такой:
select * from orders where 1=1
Если пользователь ввел какую-либо дату, то текст запроса такой:
select * from orders where 1=1 AND where ShippedDate >= @shipDateFrom
Аналогично для параметра shipDateTo. В итоге получаются четыре разных текста запросов в зависимости от рантайм параметров. Все строго, в математическом смысле формально.
Здравствуйте, Alexander Polyakov, Вы писали:
IT>>Ага, и как ты решил проблему верификации такого SQL? AP>Последовательно описано в разделах 2, 3, 4, 5. И далее в разделах 7, 8 и 9.1.
Ты IL анализируешь, проверяя все if-ы во всех комбинациях зайдет/не зайдет?
Здравствуйте, Alexander Polyakov, Вы писали:
IT>>Ага, и как ты решил проблему верификации такого SQL? AP>Последовательно описано в разделах 2, 3, 4, 5. И далее в разделах 7, 8 и 9.1.
Еще вопрос:
Используя LINQ можно сделать, например, такой метод:
Например, "Take(10)" — это ж нужно вставлять "TOP 10" в середину уже добавленной строки в StringBuilder. Как оно потом будет статически верифицироваться?
A>Ты IL анализируешь, проверяя все if-ы во всех комбинациях зайдет/не зайдет?
Нет, IL код используется только для поиска методов для тестирования, см. раздел "4. Автоматический поиск методов для тестирования".
public static QFragment ApplyFilter(Func<object, QFragment> items, ...)
{
return new {items, ...}.QFragment(@"
@if(foo) {
@:SELECT * FROM (@items(null)) _ WHERE ...
}
@if(bar) {
@:SELECT * FROM (@items(null)) _ ORDER BY ...
}
@if(baz) {
@:SELECT TOP 10 * FROM (@items(null)) _
}");
}
A>Как оно потом будет статически верифицироваться?
Тестируются запросы, в которых вызывается ApplyFilter:
var xxx = Query<Xxx>.New(new {...}, @"
...
@Foo.ApplyFilter(@<text>SELECT * FROM zzz</text>, ...)
...").List();
Здравствуйте, Alexander Polyakov, Вы писали:
A>>Как с твоим подходом сделать что-то подобное? AP>
AP> public static QFragment ApplyFilter(Func<object, QFragment> items, ...)
AP> {
AP> return new {items, ...}.QFragment(@"
AP>@if(foo) {
AP> @:SELECT * FROM (@items(null)) _ WHERE ...
AP>}
AP>@if(bar) {
AP> @:SELECT * FROM (@items(null)) _ ORDER BY ...
AP>}
AP>@if(baz) {
AP> @:SELECT TOP 10 * FROM (@items(null)) _
AP>}");
AP> }
AP>
Это не эквивалентный код Что будет если foo, bar и baz одновременно true? А сверху если сверху еще наложен .Select, который пушит проекции в подзапросы. То твой генератор начинает нервно курить в сторонке.
В этом и есть слабость твоего подхода — как не автоматизируй склейку строк, она все равно останется склейкой строк.
Здравствуйте, Alexander Polyakov, Вы писали:
IT>>Ага, и как ты решил проблему верификации такого SQL? AP>Последовательно описано в разделах 2, 3, 4, 5. И далее в разделах 7, 8 и 9.1.
Всё так сложно? А в двух словах идую описать?
Если нам не помогут, то мы тоже никого не пощадим.
G>Это не эквивалентный код Что будет если foo, bar и baz одновременно true?
Да, я невнимательно прочитал исходный код, эквивалентный вот такой код:
public static QFragment ApplyFilter(Func<object, QFragment> items, ...)
{
return new {items, ...}.QFragment(@"
SELECT @if(baz) {<text>TOP 10</text>} *
FROM (@items) _
@if(foo) {
@:WHERE ...
}
@if(bar) {
@:ORDER BY ...
}");
}
G>А сверху если сверху еще наложен .Select, который пушит проекции в подзапросы.
Давай примеры.
G>То твой генератор начинает нервно курить в сторонке.
Если только в твоем воображении.
G>В этом и есть слабость твоего подхода — как не автоматизируй склейку строк, она все равно останется склейкой строк.
Склейка строк это сила!!!
IT>Всё так сложно? А в двух словах идую описать?
Там как раз последовательно, естественно и просто написано.
В двух словах так.
Был такой old-school-ый подход выделять DAL и покрывать его тестами. Писать такие тесты довольно рутинное занятие. А рутинные, однообразные операции надо отделять и поручать машине. Вот я это и сделал.
Фрагмент кода, который формирует запрос, записываем как функцию от параметров определенных типов. Тестовые значения для параметров определяем по типу и подставляем их. И честно входим в тестовый рантайм. Обычно типы это: bool, enum и вариации на тему double dispatch: Option, Choice и т.д.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Это не эквивалентный код Что будет если foo, bar и baz одновременно true? AP>Да, я невнимательно прочитал исходный код, эквивалентный вот такой код: AP>
А если будет два условия на where, то станет совершенно нечтиаемо.
G>>А сверху если сверху еще наложен .Select, который пушит проекции в подзапросы. AP>Давай примеры.
Дери результат функции ApplyFilter и сделай .Select
Даже если в подзапросе группировка, которую sql сам не соптимизирует.
G>>То твой генератор начинает нервно курить в сторонке. AP>Если только в твоем воображении.
Сделай .select и посмотри сгененированный запрос.
G>>В этом и есть слабость твоего подхода — как не автоматизируй склейку строк, она все равно останется склейкой строк. AP>Склейка строк это сила!!!
Была, до появления linq.
G>А если будет два условия на where, то станет совершенно нечтиаемо.
Ошибаешься:
public static QFragment ApplyFilter(Func<object, QFragment> items, ...)
{
return new {items, ...}.QFragment(@"
SELECT @if(baz) {<text>TOP 10</text>} *
FROM (@items) _
WHERE 1 = 1 /*1 = 0*/
@if(foo) {
@:AND/*OR*/ ...
}
@if(foo2) {
@:AND/*OR*/ ...
}
@if(bar) {
@:ORDER BY ...
}");
}
А вот для LINQ простейшая замена AND на OR приводит к тому, что запрос надо записывать совершенно по другому. Видим, что, если запрос не надо строить, то посредством компилятора LINQ предлагает краткий синтаксис "cond1 || cond2". Если же запрос надо строить, то компилятор нам уже не поможет, и остается лепить DSL средствами C#. Как пишет сам Anders Hejlsberg LINQ не разрабатывался для динамического построения запросов.
А поскольку команда Хейлсберга уже давно отошла от вопросов взаимодействия с реляционными СУБД, то изменений ждать не приходится.
G>Дери результат функции ApplyFilter и сделай .Select
В чем проблема?
var xxx = Query<Xxx>.New(new {...}, @"
SELECT *
FROM (@Foo.ApplyFilter(...)) _").List();
G>Даже если в подзапросе группировка, которую sql сам не соптимизирует.
Proof link в студию или ты опять сочиняешь.
В СУБД движок, который перезаписывает запрос и генерирует план его выполнения, гораздо круче любого LINQ провайдера. И СУБД честно отводит на это ощутимое время, а потом использует кэш. Тут важно то, что ключом в кэше является сама строка запроса. А у LINQ провайдера ключа подходящего нет.
Кстати, то, что СУБД не оптимизирует вот такое "... = @p1 OR @p1 IS NULL" связанно именно с кэшем планов. Либо надо бегать по дереву и тогда теряем в производительности кэша, либо отдать это на откуп пользователю, пусть он генерирует разные тексты для запросов, которые будут разными ключами в кэше.
G>Сделай .select и посмотри сгененированный запрос.
Посмотрел. Всё в порядке.
AP>>Склейка строк это сила!!! G>Была, до появления linq.
И такой остается, поскольку человек видит текст, а не деревья выражений. Как пишется код? Реализуется некоторый функционал F1. Потом реализуется еще F2...FN. У F1...FN наблюдаются общие фрагменты кода, т.е. текста. Для "Don't repeat yourself" эти фрагменты надо выделить и поставить их вызовы в нескольких местах. "Don't repeat" это значит не повторять фрагменты текста. Нарезка текста на фрагменты самая естественная схема декомпозиции кода. C# предлагает такую декомпозицию для кода, который компилируется непосредственно в IL для исполнения, и не предлагает такой декомпозиции для IQueryable, выражения для которого компилируются в структуры данных для генерации SQL строк.
Не понял, как проекция пропушится во все подзапросы?
G>>Даже если в подзапросе группировка, которую sql сам не соптимизирует. AP>Proof link в студию или ты опять сочиняешь.
Так попробуй сам сделать.
AP>В СУБД движок, который перезаписывает запрос и генерирует план его выполнения, гораздо круче любого LINQ провайдера. И СУБД честно отводит на это ощутимое время, а потом использует кэш. Тут важно то, что ключом в кэше является сама строка запроса. А у LINQ провайдера ключа подходящего нет.
При чем тут это?
AP>Кстати, то, что СУБД не оптимизирует вот такое "... = @p1 OR @p1 IS NULL" связанно именно с кэшем планов. Либо надо бегать по дереву и тогда теряем в производительности кэша, либо отдать это на откуп пользователю, пусть он генерирует разные тексты для запросов, которые будут разными ключами в кэше.
Да, и linq тут спасает. Хоть и "ключа поодходящего нет" (с)
G>>Сделай .select и посмотри сгененированный запрос. AP>Посмотрел. Всё в порядке.
Именно, и проекции попапил в том числе в подзапросы. Как склейкой строк такое повторить?
AP>>>Склейка строк это сила!!! G>>Была, до появления linq. AP>И такой остается, поскольку человек видит текст, а не деревья выражений. Как пишется код? Реализуется некоторый функционал F1. Потом реализуется еще F2...FN. У F1...FN наблюдаются общие фрагменты кода, т.е. текста. Для "Don't repeat yourself" эти фрагменты надо выделить и поставить их вызовы в нескольких местах. "Don't repeat" это значит не повторять фрагменты текста. Нарезка текста на фрагменты самая естественная схема декомпозиции кода. C# предлагает такую декомпозицию для кода, который компилируется непосредственно в IL для исполнения, и не предлагает такой декомпозиции для IQueryable, выражения для которого компилируются в структуры данных для генерации SQL строк.
Ты чего курил? В этой теме уже раз 100 приводили декомпозицию IQueryable, хоть комбинаторами (в том числе обобщенными), хоть руками деревья выражений пиши, хоть dlinq (который используется в новых веб-формах для фильтров и сортировок).
G>Не понял, как проекция пропушится во все подзапросы?
Чего? Нормально условие задачи сформулировать можешь?
G>>>Даже если в подзапросе группировка, которую sql сам не соптимизирует. AP>>Proof link в студию или ты опять сочиняешь. G>Так попробуй сам сделать.
Как же я сделаю то, чего нет? Короче, слив засчитан.
AP>>В СУБД движок, который перезаписывает запрос и генерирует план его выполнения, гораздо круче любого LINQ провайдера. И СУБД честно отводит на это ощутимое время, а потом использует кэш. Тут важно то, что ключом в кэше является сама строка запроса. А у LINQ провайдера ключа подходящего нет. G>При чем тут это? AP>>Кстати, то, что СУБД не оптимизирует вот такое "... = @p1 OR @p1 IS NULL" связанно именно с кэшем планов. Либо надо бегать по дереву и тогда теряем в производительности кэша, либо отдать это на откуп пользователю, пусть он генерирует разные тексты для запросов, которые будут разными ключами в кэше. G>Да, и linq тут спасает. Хоть и "ключа поодходящего нет" (с)
Это "спасение" за счет уменьшения производительности кэша. Разработчики СУБД давно бы сделали это, но не считаю, что это стоит потерь производительности кэша. А изготовители LINQ провайдеров вынуждены хотя бы таким кэшем прикрывать уж совсем неприличные тормоза (на неприлично простой задаче по генерации текста).
G>Именно, и проекции попапил в том числе в подзапросы. Как склейкой строк такое повторить?
Выше уже приводил код.
G>Ты чего курил? В этой теме уже раз 100 приводили декомпозицию IQueryable, хоть комбинаторами (в том числе обобщенными), хоть руками деревья выражений пиши, хоть dlinq (который используется в новых веб-формах для фильтров и сортировок).
100-ый раз повторяю, Хейлсберг не разрабатывал LINQ для построения запросов. А у вас доступа к компилятору нет, поэтому ваши решения либо сводят всю идею linq-а на нет, либо убогие частные случаи.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Был такой old-school-ый подход выделять DAL и покрывать его тестами. Писать такие тесты довольно рутинное занятие. А рутинные, однообразные операции надо отделять и поручать машине. Вот я это и сделал.
Понятно. Т.е ты решил типичную задачу для типо-опасных инструментов — покрытие как можно большего количества кода юнит тестами, чтобы убедиться, что этот код не упадёт в рантайм. Т.е. ты решил проблему, которая для типо-безопасных инструментов просто не существует.
Что тут можно сказать. Во-первых, такие тесты будут работать либо бесконечно долго, либо не дадут 100% гарантии. Скорее всего поначалу они будут работать приемлемо долго, а с ростом кодовой базы приемлемо будет плавно переходить в неприемлемо. При этом 100%-го покрытия всё равно не будет. А вот компилятор даёт 100% гарантии типо-безопасности без дополнительных временных накладных расходов. Т.е. как я уже сказал, такой проблемы просто не существует и решать её не надо. Во-вторых, такой подход принуждает к использованию отдельного слоя, т.е. диктует разработчику архитектуру приложения, что всегда является несомненным минусом. В-третьих, сколько бы ни было тестов и каким бы не было покрытие, но нахождение ошибки всё равно откладывается на неопределённый срок, до тех пор пока программист не запустит тесты. При этом он может что-нибудь сломать и узнать об этом через пол часа, когда он занимается уже совсем другой задачей. А для типизированных решений ошибки видны уже в студии при наборе текста, ещё до копмиляции. При этом точность диагностики абсолютная, а тест выдаёт лишь примерную локализацию и как правило не очень внятную причину ошибки.
Что касается конкретного решения. Ковыряние в IL — это, конечно, прикольно, но ещё больше замедляет выполнение тестов, ещё больше накладывает ограничений на код и ещё больше зажимает приложение в тисках предлагаемой архитектуры. Решение, скажем, на атрибутах могло бы быть гораздо проще и более гибким. К тому же, насколько мне известно, подобные решения уже существуют в том числе и от MS.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Не понял, как проекция пропушится во все подзапросы? AP>Чего? Нормально условие задачи сформулировать можешь?
Еще раз: сгенери сложный запрос с помощью linq, сделай .select с проекцией и увидишь, что проекции попали во все подзапросы.
G>>>>Даже если в подзапросе группировка, которую sql сам не соптимизирует. AP>>>Proof link в студию или ты опять сочиняешь. G>>Так попробуй сам сделать. AP>Как же я сделаю то, чего нет? Короче, слив засчитан.
Да просто на SQL напиши запрос с подзапросом, в котором есть группировка и посмотри план.
Примерно так:
select field1 from (select field1, field2,... from table group by field1, field2,...)
SQL Server в этом случае сам не протакливает проекции в позапросы, а честно выполнит все вычисления с затягиванием данных с диска, даже если это совсем неоптимально.
AP>>>В СУБД движок, который перезаписывает запрос и генерирует план его выполнения, гораздо круче любого LINQ провайдера. И СУБД честно отводит на это ощутимое время, а потом использует кэш. Тут важно то, что ключом в кэше является сама строка запроса. А у LINQ провайдера ключа подходящего нет. G>>При чем тут это? AP>>>Кстати, то, что СУБД не оптимизирует вот такое "... = @p1 OR @p1 IS NULL" связанно именно с кэшем планов. Либо надо бегать по дереву и тогда теряем в производительности кэша, либо отдать это на откуп пользователю, пусть он генерирует разные тексты для запросов, которые будут разными ключами в кэше. G>>Да, и linq тут спасает. Хоть и "ключа поодходящего нет" (с) AP>Это "спасение" за счет уменьшения производительности кэша.
Это же лучше, чем уменьшение производительности запроса. Если запросов много, то планы из кеша не будут вытеснены, а если мало, то пофиг.
AP>Разработчики СУБД давно бы сделали это, но не считаю, что это стоит потерь производительности кэша.
Разработчики СУБД рассчитывают на то, что разработчики приложений будут писать запросы со стабильными планами. Дополнительный анализ стабильности плана может дорого стоить.
Но люди это люди, и они стремятся сократит затраты на разработку и поддержку, поэтому пишут запросы общего вида, что ведет к снижению эффективности.
Кстати Oracle умеет определять такие проблемы с планами и генерирует разные планы автоматом.
AP>А изготовители LINQ провайдеров вынуждены хотя бы таким кэшем прикрывать уж совсем неприличные тормоза (на неприлично простой задаче по генерации текста).
Какие неприличные тормоза? 0,4 мс на запрос, это меньше статистической погрешности от общего времени выполнения запроса.
Твое решение тратит гораздо больше времени в процессе написания, причем время программистов на 3 порядка дороже, чем время железки.
G>>Именно, и проекции попапил в том числе в подзапросы. Как склейкой строк такое повторить? AP>Выше уже приводил код.
Ты не понял. Вот есть Linq запрос, который генерирует sql такого вида:
select field1, field2,... from (select field1, field2,... from t where...)
Потом выполняется .Select(e => e.field1) и результирующий SQL получается такой:
select field1 from (select field1 from t where...)
Рассчитывать что сам SQL Server такое соптимизирует нельзя.
Вот и как это сделать склейкой строк?
G>>Ты чего курил? В этой теме уже раз 100 приводили декомпозицию IQueryable, хоть комбинаторами (в том числе обобщенными), хоть руками деревья выражений пиши, хоть dlinq (который используется в новых веб-формах для фильтров и сортировок). AP>100-ый раз повторяю, Хейлсберг не разрабатывал LINQ для построения запросов. А у вас доступа к компилятору нет, поэтому ваши решения либо сводят всю идею linq-а на нет, либо убогие частные случаи.
Если повторить чушь 100 раз она правдой не ставит.
Кстати Linq делал не Хейлсберг, а Мейер. Он подобное еще в 90-х делал на хаскеле, именно с прицелом на построение SQL запросов из кода (внезапно).
Доступ к компилятору для генерации деревьев выражений не нужен. Компилятор только преобразует лябмды в Expression Tree. Никто тебе не мешает любое дерево выражений собрать руками и обработать его как захочешь. Примеры кода тебе уже приводили раз десять, которые по объему и скорости работы сильно выигрывают у твоего решения.
Причем как бы ты не старался, все равно бегать по деревьям ET оказывается быстрее, чем ковырять IL, а потом выполнять реальные запросы к базе. Да и качество генерируемого SQL у Linq повыше, чем у самописных запросов (а учитывая время, затраченное на написание — гораздо выше). Linq может сгенерировать столько вариантов запроса, сколько руками замучаешься писать и поддерживать, даже имея удобный механизм для склейки строк.
G>Да просто на SQL напиши запрос с подзапросом, в котором есть группировка и посмотри план. G>Примерно так: G>
G>select field1 from (select field1, field2,... from table group by field1, field2,...)
G>
G>SQL Server в этом случае сам не протакливает проекции в позапросы, а честно выполнит все вычисления с затягиванием данных с диска, даже если это совсем неоптимально.
Давай полный source code: DDL скрипт базы данных, SQL запрос, LINQ запрос и сгенерированный LINQ-ом SQL. Пока это выглядит как твои фантазии. Кстати, такое часто встречается, любители linq такое нафантазируют о СУБД, что уши вянут.
Игорь, всё же будет лучше, если ты прочитаешь мою ссылку. Иначе мы будем тратить время на разбор твоих заблуждений, которые не имеют отношения к моему решению.
IT> Т.е. ты решил проблему, которая для типо-безопасных инструментов просто не существует.
Да, верно. Но также верно и симметричное утверждение. У типо-безопасных инструментов есть проблемы, которые просто не существуют для другого класса инструментов.
IT>Что тут можно сказать. Во-первых, такие тесты будут работать либо бесконечно долго, либо не дадут 100% гарантии. Скорее всего поначалу они будут работать приемлемо долго, а с ростом кодовой базы приемлемо будет плавно переходить в неприемлемо. При этом 100%-го покрытия всё равно не будет. А вот компилятор даёт 100% гарантии типо-безопасности без дополнительных временных накладных расходов.
Компилятор C# тоже может работать бесконечно долго. Например, вот на этом коде компилятору не хватает памяти и он падает:
Описание этой проблемы можно почитать здесь.
IT>без дополнительных временных накладных расходов.
При росте кодовой базы временные расходы на компиляцию тоже растут.
IT>Во-вторых, такой подход принуждает к использованию отдельного слоя, т.е. диктует разработчику архитектуру приложения, что всегда является несомненным минусом.
Это не верно. Ни какого отдельного слоя не требуется. Запросы Query<My>.New можно писать где угодно. Они будут найдены и протестированы.
IT>В-третьих, сколько бы ни было тестов и каким бы не было покрытие, но нахождение ошибки всё равно откладывается на неопределённый срок, до тех пор пока программист не запустит тесты. При этом он может что-нибудь сломать и узнать об этом через пол часа, когда он занимается уже совсем другой задачей. А для типизированных решений ошибки видны уже в студии при наборе текста, ещё до копмиляции. При этом точность диагностики абсолютная, а тест выдаёт лишь примерную локализацию и как правило не очень внятную причину ошибки.
Какие полчаса, на реальных проектах мы укладываемся в полторы секунды на все запросы. А если надо быстрее, запускаем проверку той части запросов, с которой работаем в данный момент, это несколько сот миллисекунд. Всё как при обычном unit-тестировании. Или ты в принципе против unit-тестирования?
IT>При этом точность диагностики абсолютная, а тест выдаёт лишь примерную локализацию и как правило не очень внятную причину ошибки.
Точность диагностики примерно такая же как при компиляции. В сообщении указывается файл и строка, где начинается запрос, сам запрос и сообщение от СУБД.
Есть даже Find Usages для сущностей базы данных: таблиц, колонок и т.д.
IT>Что касается конкретного решения. Ковыряние в IL — это, конечно, прикольно, но ещё больше замедляет выполнение тестов, ещё больше накладывает ограничений на код и ещё больше зажимает приложение в тисках предлагаемой архитектуры. Решение, скажем, на атрибутах могло бы быть гораздо проще и более гибким. К тому же, насколько мне известно, подобные решения уже существуют в том числе и от MS.
Ни каких архитектурных тисков нет. Это ты придумал сам. По ссылке описано ровно обратное. Там последовательно описывается как мы наращиваем функционал и с чем мы оказываемся после каждого пункта. Такое последовательное описание дает четкое понимание для clear exit strategy. Можно выйти после любого из пунктов.
Отмечу, что класс Query всего лишь удобный способ заполнения SqlCommand. В остальном чистый ADO.NET.
IT>Решение, скажем, на атрибутах могло бы быть гораздо проще и более гибким.
На какие элементы кода ты предлагаешь навешивать атрибуты?
IT>К тому же, насколько мне известно, подобные решения уже существуют в том числе и от MS.
По правилам хорошего тона тут должны быть ссылки. Очень любопытно посмотреть.
G>Кстати Oracle умеет определять такие проблемы с планами и генерирует разные планы автоматом.
Полного решения этой проблемы нет ни в одной СУБД, в которой есть кэш планов. Описано здесь.
Проблема не в реализации, проблема логическая. Полное решение проблемы не совместимо с быстрым кэшем планов. Еще раз повторю, то, что делает linq можно легко делать внутри СУБД, но этого не делают, поскольку СУБД не может себе позволить так транжирить производительность. А linq вынужден это делает. СУБД выставляет гибкий интерфейс текстовых запросов, и предлагает пользователям воспользоваться этой гибкостью и формулировать запрос точно без растранжиривания производительности.
IT>Может у тебя не самая свежая версия. Я довно nuget не обновлял. Может в этом проблема.
Только что обновил nuget пакеты. Ничего не поменялось. Здесь написано, что версия от July 11 2014, поэтому твое предположение о несвежей версии не прокатило. Разберись, плиз, в треде все данные есть.
Здравствуйте, gandjustas, Вы писали:
V>>Вообще-то в последние лет 5 идет полный отказ вообще от каких-либо технологий "управляемых VM", бо они работают плохо и дают крайне низкую фактическую статистику надежности. G>Это только в твоей голове идет. А по факту почти 100% веб-сайтов используют «управляемые вм», почти 100% line-of-business систем от crm до складского учета и управления персоналом. Процессинг крупнейших банков написан на java, android и windows phone приложения по большей части на java и .net. Самый массовый почтовый сервер — exchange написан на .net
G>И никто не собирается отказываться.
G>А где ты отказ видел?
Специально для жителей крайнего севера автоповтор:
Определённую нишу она заняла — это там, где надо неторопливо выдавать что-то в веб на странички или как веб-сервисы или через родственные веб-ориентированные АПИ. Это ВСЁ! Т.е. из промышленного применения технологии — действительно всё! Там же, где требуется быстро и надежно — прямо на сегодня оттуда сие недоразумение вымыто, как и джава. Увы, сие медицинский факт.
Ах, да, я забыл еще про написание ГУИ на дотнете.
Но это я специально опустил. Ведь нелепо обсуждать сие на сегодня, бо прямо сейчас на плюсах-QT или HTML/HTML-5 писать клиентский ГУИ тоже получается аж бегом. А на Objective-C его тоже просто тонны написаны. Кароч, написание ГУИ давно ушло из области "сложных задач", слишком много всеобъемлющих ГУИ-фреймворков на сегодня под кучу языков и платформ.
В общем, ключевое для дотнета я подчеркнул — неторопливо.
По факту же были попытки использовать управляемые среды чуть более широко, чем упомянутые мной ниши, а именно:
— кодеки
— обработка данных (signal processing)
— обработка финансовых данных в реалтайме (а не "складская программка" или "учет персонала")
— банковский реалтайм-процессинг
— диспетчеризация сетевых пакетов, в т.ч. для нужд цифровой телефонии и мультикаста для конференций (а сие сплошная "логика", а не низкоуровневая "механика")
— движки игр (не скриптовый "клей", а именно сами геометрические/физические движки)
— движки бирж и платформы клиентов под них же
— ...
Список можно продолжать бесконечно. В этом списке — эпик фейлы и просто невероятные тонны зря выброшенных на дотнет денег. Так что, смирись. На сегодня ситуация такова, что перед новым серьезным заходом индустрии на дотнет потребуется минимум десяток лет... чтобы забыть все эти бесконечные дотнетные эпик фейлы. Переписывали обратно на традиционные технологии.
Почему так вышло? ИМХО, ситуация была следующей. В начале 2000-х резко попер веб и всякие "новые технологии". Понятное дело, что появилось желание реализовать многие системы "по-новому". Да только те, что сделали ставку на дотнет, сильно облажались. Нейтивные технологии тоже на месте не стояли, те же плюсы образца 2005-го года — это совсем другой язык в сравнении с плюсами 1995-го года. А о сравнительном качестве компиляторов даже говорить не прилично. Поэтому С/С++ на сегодня — промышленный стандарт для разработок в мильонах прикладных ниш, где дотнету делать нечего вообще еще долго. (Справедливости ради можно отметить резкий рост эффективности скриптовых движков за это же время, а так же движков исполнения запросов/процедур в серверах БД, что отбирает у дотнета даже то, что дотнет отобрал у плюсов)
Именно поэтому на сегодня дотнет популярен как клиент к БД, где не надо торопиться. Именно в этой нише ты и существуешь, как и практически все популярные местные дотнетчики... кроме пары, занимающихся исключительно ср-вами для девелоперов. ))
Насчет банковского процессинга на джаве — всё не так просто. Ты и тут слышал звон да не знаешь где он. Этот процессинг на самом деле на Оракле и на его нейтивной поддержке маппинга (ограниченного) джавовских типов в поля базы. Весь процессинг выполняется сервером БД, а не внешним мифическим джава-приложением. Доля кода на PL-1 в реалтайм-обработке намного-намного выше доли кода на джава. На последней пишут обычно там, где отношение сложность/требуемое_быстродействие сравнительно большое. Чаще всего неспешную, но сложную аналитику какую-нить, а так же почти всегда тела всей этой мутотни для генерирования неспешных XML-ответов на XML-запросы неспешных ГУИ-клиентов (или веб-серваков). Кароч, всякую, не приведи господи, хрень, какую я и обозначил с самого начала.
Вот тебе ниша управляемых платформ. Очень узко, как по мне. Даже с учетом ГУИ, в т.ч. мобильного. Там тоже уже многое на скриптах и HTML делается.
Да и вообще, вменяемый по отзывчивости ГУИ на сегодня — это вовсе не андроид. Даже не брать яблоки, а клёвый по отзывчивости WP8 — это вовсе не дотнет, это WP WinRT, т.е. COM+Win32. Просто для вас сделали бинд этого АПИ на дотнет, но можно писать и напрямую на плюсах и что-то более-менее серьезное народ пишет на плюсах под WP8 аж бегом. Например, только десятки программ-конкурентов Viber, всевозможные "офисы", медиа-плейеры, шифровальщики траффиков, системные утилиты по оптимизации памяти, просмотрщики форматов файлов и т.д. и т.п. — унутре всё сплошь нейтивное, хоть и под мобилки. Иногда формочки ГУИ разве что дотнетные или HTML (особенно формочки с настройками/сеттингами), но доля трудозатрат на такой ГУИ в более-менее сложном мобильном приложении не видна и под микроскопом в общем объеме работ.
Так что нишу "формочек с полями"... ну да, ну да... оставьте для дотнетной CRM.
Когда-то я подобное на VB лабал... "Клей", он и в Африке "клей". Что-то сложное пишешь на плюсах и выставляешь как COM, затем непринужденно пользуешь из "клея", в т.ч. из скриптов. ))
Не спорю, что дотнет — это хороший "клей"... это очень даже крутой клей, в сравнении с динамически-типизированными языками.)))
VB, кста, был статически типизирован при включении соотв. опции.
V>Определённую нишу она заняла — это там, где надо неторопливо выдавать что-то в веб на странички или как веб-сервисы или через родственные веб-ориентированные АПИ. Это ВСЁ! Т.е. из промышленного применения технологии — действительно всё! Там же, где требуется быстро и надежно — прямо на сегодня оттуда сие недоразумение вымыто, как и джава. Увы, сие медицинский факт.
От повторения чушь правдой не станет. Сайты, которые обслуживают пользователей миллионами за доли секунды, написанные на .NET, Java и даже Ruby встречаются гораздо чаще, чем написанные на С++.
Вот для последних трех олимпиад сайт были на .NET, как-то не было претензий из-за неторопливости.
А про надежность — бред полнейший, код на C++ в среднем гораздо менее надежен, тупо больше мест где можно ошибиться.
V>Ах, да, я забыл еще про написание ГУИ на дотнете. V>Но это я специально опустил. Ведь нелепо обсуждать сие на сегодня, бо прямо сейчас на плюсах-QT или HTML/HTML-5 писать клиентский ГУИ тоже получается аж бегом. А на Objective-C его тоже просто тонны написаны. Кароч, написание ГУИ давно ушло из области "сложных задач", слишком много всеобъемлющих ГУИ-фреймворков на сегодня под кучу языков и платформ.
Да-да, наверное потому что ручное управление памятью так круто, что в swift решили сделать его автоматическим
Тем не менее это все величины бесконечно малого порядка по сравнению с JavaScript, который вполне managed.
V>В общем, ключевое для дотнета я подчеркнул — неторопливо.
Странно, как же сайты для олимпиад делали. Наверное просто у тебя забыли спросить.
V>По факту же были попытки использовать управляемые среды чуть более широко, чем упомянутые мной ниши, а именно: V>- кодеки V>- обработка данных (signal processing) V>- обработка финансовых данных в реалтайме (а не "складская программка" или "учет персонала") V>- банковский реалтайм-процессинг V>- диспетчеризация сетевых пакетов, в т.ч. для нужд цифровой телефонии и мультикаста для конференций (а сие сплошная "логика", а не низкоуровневая "механика") V>- движки игр (не скриптовый "клей", а именно сами геометрические/физические движки) V>- движки бирж и платформы клиентов под них же V>- ...
Ты наверное не в курсе:
1) Банковских процессингов на java полно, например в сбере. Да и непонятно зачем ему скорость вообще.
2) Erlang был придуман и успешно работает как раз для диспетчеризации сетевых пакетов, а он сильно медленнее .NET
3) Unity3d, на котором делается большинство мобильных игр сегодня, написан на C#.
4) Обработку сигналов я сам писал на .NET более одного раза, никто на скорость и надежность не жаловался.
5) В некоторых европейских банках обработка финансовых данных в реалтайме делается на F#, в остальных на Java
6) Знаю как минимум один движок биржи на .NET и клиент тоже на .NET
Только кодеки почти нет смысла писать на управляемых языках, ибо числомолотилка. Проще написать прототип на высокоуровневом языке, а потом автоматически или полуавтоматически сконвертировать в C.
Кстати такой конвертор уже есть в .NET, так что и кодеки не за горами.
V>Список можно продолжать бесконечно. В этом списке — эпик фейлы и просто невероятные тонны зря выброшенных на дотнет денег. Так что, смирись. На сегодня ситуация такова, что перед новым серьезным заходом индустрии на дотнет потребуется минимум десяток лет... чтобы забыть все эти бесконечные дотнетные эпик фейлы. Переписывали обратно на традиционные технологии.
Помоему это все твои фантазии. Или ты судишь по одному неудачному примеру. Так неудач у того же C++ на два порядка больше. Особенно там где реально высокие нагрузки и нетривиальные задачи.
Не далее как вчера драйвер блютуса (вполне себе unmanaged) поломал запись экрана. Вот тебе и надежность неуправляемого кода.
Здравствуйте, fddima, Вы писали:
F>А на самом деле пацаны начали пробовать .NET ещё в бетах. И пока плюсники там всё ещё отлаживали свои формы — и они жутко маргали
Формы )))
На сегодня внутри банков популярен веб-интерфейс. Т.е. морды вебовские дотнетные.
В двух банках, где я был клиентом, мне выдали клиентский софт написанный оп-па, на дельфях. ))
Вернее, морда на дельфях + несколько до боли знакомых сишных DLL, под сетку и под шифрование. ))
F>по факту получилось, что нет был принят и до сих пор позиций не сдает. Если где-то существуют не дотнет приложения — то только legacy.
Так и есть. Всё неспешное, утилиты, веб-морды, отчетность — на дотнете. Кароч, везде, где надо залезть в базу и скорость отклика в сотню миллисекунд, а то и секунды — это нормально.
Насчет старых программ на сях.
Коллега! Дык, и С++ ныне совсем не тот. И библиотеки под него. И сейчас может оказаться легче переписать старые С++ программы с использованием новых библиотек. Там разница в объеме до 5-ти раз может выйти. ))) А в надежности — на многие порядки.
Здравствуйте, IT, Вы писали:
V>>Вообще-то в последние лет 5 идет полный отказ вообще от каких-либо технологий "управляемых VM", бо они работают плохо и дают крайне низкую фактическую статистику надежности. IT>Кажется, я начинаю догадываться. Ты про какую-то другую альтернативную реальность, я прав?
Нет. Это итог попыток использования дотнета за последние лет 10. Везде идёт отказ от него в чем-то более-менее требующем надежности и предсказуемости.
V>>Да и тебя несет малость. Сейчас не 2005-й год, чтобы так задорно петь дифирамбы дотнету — это нелепо смотрится в 2014-м. Поезд уже ушел. Технология в течении 10 лет показывала себя как ненадежная и неэффективная. IT>Не стоит рассуждать о дотнете, который был в 2005-м году сегодня, когда на дворе 2014-й. Поставь новую версию и убедись сам.
Офигенный аргмент. ))
Серьезно. Вот огромная система, целый конгломерат приложений, всё вместе составляющих биржу, входящую в 5-ку крупнейших, уже 3 года как полностью отказалась от дотнета для чего-то более-менее серьезного, кроме неспешных задач или сайтостроения. Потратила на "игры" с этой технологией астрономические суммы. А ты с таким невинным толкаешь такие фразы. Не стыдно?
Не боись. На многих обслуживающих нишах дотнет остался. Я бы даже сказал — его достаточно много. Он убран только оттуда, где требуется надежность, скорость, предсказуемость. Убрали же его из-за регулярных сбоев/отказов. Даже если на сегодня дотнет в 10 раз надежнее и безотказнее, чем в 2005-м, то этого еще всё еще слишком и слишком мало.
Технология всё-равно сырая. В 2009-м я потратил более недели на поиски причин периодических глюков подключения к майкрософтному SQL-серваку и обнаружил рефлектором прикольный баг парсера потока от SQL-сервака, когда идёт нарезка блоб-полей... Ну что тут говорить??? В святая-святых, в драйвере общения с базой(!!!) кривой индусский код.
Причем, кривизна не только в том месте, где был баг. Сам код кривой до невероятности. В сравнении с нейтивными опенсорсными дровами под какую-нить БД для Линухов — это же просто детский лепет, а не драйвер клиента БД!!!
Смирись. Технология еще сырая. И я не говорю, что ты в этом виноват или любой другой программист на дотнете. Но таковы дела. Очень много функционала. Действительно много. Он бесплатен. Т.е. совершенно эта прорва функционала бесплатна. Качество не может быть хорошим в короткие сроки при таких раскладах. Просто руки не будут успевать делать всю эту прорву функционала качественно.
Поэтому дотнет представляет из себя островки неплохих, иногда просто блестящих технологий (самый лучший в мире ГЦ, например) в океане низкопробнейшего кода, составляющего саму платформу. Без тошноты рыться в его кишках (а ведь до сих пор бывает обязательно надо!!! фига себе!!!) — просто невозможно. Качество разработки не на высоте и об этом знает весь мир.
V>>Это по-факту попыток использования на крупнейших мировых биржах и банках.
IT>Опять рупь за сто Я работаю в крупнейшем мировом банке и в данный момент занимаюсь миграцией одной системы с "супернадёжного и суперэффективного" железа и софта на .NET. Причём именно её процессинговой, серверной части. Морда и так уже давно написана на .NET.
Удивил. )))
Морда на нете уже много лет где. А насчет "процессонговой" части любопытно. Бо самый рантайм-процессинг все-равно выполняется серверами БД, а не внешними приложениями. А внешняя аналитика или неспешный пересчет всего и вся по закрытию банковского дня может запросто быть написан на чем-то управляемом. Собсно, это уже десяток лет так и есть.
V>>Сама платформа еще сырая и ты, как программист, тут бессилен, бо это вне твоей компетенции — ты лишь пользователь платформы. IT>Всё же обнови свою версию .NET на более свежую.
А разве не сама в винде обновляется?
А разве когда ставишь 13-ю студию не обновилась?
V>>Определённую нишу она заняла — это там, где надо неторопливо выдавать что-то в веб на странички или как веб-сервисы или через родственные веб-ориентированные АПИ. Это ВСЁ! Т.е. из промышленного применения технологии — действительно всё! Там же, где требуется быстро и надежно — прямо на сегодня оттуда сие недоразумение вымыто, как и джава. Увы, сие медицинский факт. И до устаревания этого факта должно пройти примерно десяток лет, не меньше... чтобы критическая масса поколения next превысила опыт потери просто тонн денег и была выполнена еще одна попытка в этом направлении.
IT>Одно из двух. Либо ты говоришь о софте, валовое количество которого не превышает пол процента, либо ты действительно из другой альтернативной реальности. В моей практике нестабильную работу приложений, написанных на .NET, можно пересчитать по пальцам одной руки и все они связаны либо с кривым нативным кодом, либо с кривыми руками программистов. Про эффективность я вообще молчу. На 80% процентов она определяется архитектурой приложения и небольшое отставание .net от нативного кода как правило легко компенсируется за счёт более высокого уровня технологии.
Мде-с... Ну вот как с тобой общаться?
Ты сидишь в крайне узкой нише разработок и считаешь, что на этом всё! ))
А что за пределами этой узенькой ниши — так сразу "альтернативная реальность".
Причем, в этой твоей нише, действительно, тормоза дотнета особой рояли не играют! Поэтому он там и прижился. И я это знаю более чем неплохо, бо до дотнета в той же самой нише использовал тоже не самые шустрые технологии... смысла не было в складских/бухгалтерских программах и прочих бизнес-программах куда-то торопиться.
V>>И не надо тут пальцы вейром насчет "по мере сил мы эту ситуацию меняем и надо признать не без успеха". Это всё введение в заблуждение непосвящённых читателей. Я прекрасно в курсе ЧТО ИМЕННО могли доверить пилить на дотнете, если речь о биржах и банках.
IT>Дружище, я тебя хорошо понимаю. Последние несколько лет жизни ты потратил, находясь в плену иллюзий и домыслов, среди ветхих и безнадёжно устаревших технологий. И тебе трудно осознавать, что все эти годы потрачены зря. Но тебе придётся смириться. Не ты первый. Кто-то когда-то считал, что мир покоится на трёх слонах, кто-то утверждал, что 640KB памяти компьютеру хватит до скончания веков. Но технический прогресс остановить пока не получилось ни у кого.
Бла-бла-бла.
Не ты первый, кто развел крупные компании на серьезные инвестиции в никуда. Я не желаю тебе неудачи, ес-но. Но я хорошо знаю, чем закончились практически 100% попыток переехать на дотнет в банковской сфере за последний десяток лет. И ты это хорошо знаешь. Вон у вас даже морда на дотнете. ))) Дай бог тебе размочить, наконец, это разгромный сухой счет, конечно... хоть как-то оправдать этот бесконечный дотнетный эпик-фейл и тонны выброшенных на игры с ним денег.
V>>Определённую нишу она заняла — это там, где надо неторопливо выдавать что-то в веб на странички или как веб-сервисы или через родственные веб-ориентированные АПИ. Это ВСЁ! Т.е. из промышленного применения технологии — действительно всё! Там же, где требуется быстро и надежно — прямо на сегодня оттуда сие недоразумение вымыто, как и джава. Увы, сие медицинский факт.
G>От повторения чушь правдой не станет. Сайты, которые обслуживают пользователей миллионами за доли секунды, написанные на .NET, Java и даже Ruby встречаются гораздо чаще, чем написанные на С++.
Т.е. ты не понял, почему сайты пишут на дотнете и php/ruby, а движки, типа Asterisk или виндовый или самсунговый медиа-сервера на сях?
G>Помоему это все твои фантазии. Или ты судишь по одному неудачному примеру. Так неудач у того же C++ на два порядка больше. Особенно там где реально высокие нагрузки и нетривиальные задачи.
Да почему же фантазии-то??? Есть дотнетные аналоги Asterisk-у и даже дотнетные медиа-сервера есть, и даже куча алгоритмов кодеков на дотнет переведена. Даже офисы какие-то на дотнете есть и даже просмотрщики PDF. Кароч, почти всё, что сделано на нейтиве уже давным-давно опробовано на дотнете и вряд ли по одному разу только. Какие проблемы-то? Просто не нужны никому, бо сливают нейтиву безбожно. От того и не востребованы.
Я же вполне четко обозначил промышленную дотнетную нишу. И конкретно ты в ней тоже сидишь, кста. Неужели ты не видишь позицию собственной ниши среди многообразия остальных??? Да и про "заказуху" я тебе не раз уже писал...
Жаль, что конкретно ты не понимаешь ни слова из того, что я тебе отвечаю. А разжевывать до дна формат сайта не позволяет. Блин, ты настолько невпопад попытался насыпать аргументы, что мне придется сделать паузу с тобой еще на годик.
Здравствуйте, vdimas, Вы писали:
V>Поэтому С/С++ на сегодня — промышленный стандарт для разработок в мильонах прикладных ниш, где дотнету делать нечего вообще еще долго.
Почему же вакасий C++ на hh в 2 раза меньше только одного .NET. А если посчитать в совокупности по всем платформам, то на порядок меньше.
Ты точно в своем мире живешь.
V>Именно поэтому на сегодня дотнет популярен как клиент к БД, где не надо торопиться. Именно в этой нише ты и существуешь, как и практически все популярные местные дотнетчики... кроме пары, занимающихся исключительно ср-вами для девелоперов. ))
Именно поэтому наверное сайты олимпиад сделали на .NET. Вот только там торопиться надо еще как, ибо клиентов миллионы, а серваков от силы десятки.
Ну и самое главное, что написать эти сайты на C++ не хватило бы времени между олимпиадами.
V>Насчет банковского процессинга на джаве — всё не так просто. Ты и тут слышал звон да не знаешь где он. Этот процессинг на самом деле на Оракле и на его нейтивной поддержке маппинга (ограниченного) джавовских типов в поля базы. Весь процессинг выполняется сервером БД, а не внешним мифическим джава-приложением. Доля кода на PL-1 в реалтайм-обработке намного-намного выше доли кода на джава. На последней пишут обычно там, где отношение сложность/требуемое_быстродействие сравнительно большое. Чаще всего неспешную, но сложную аналитику какую-нить, а так же почти всегда тела всей этой мутотни для генерирования неспешных XML-ответов на XML-запросы неспешных ГУИ-клиентов (или веб-серваков). Кароч, всякую, не приведи господи, хрень, какую я и обозначил с самого начала.
Да не мифическим, а вполне конкретным. А в СУБД основная проблема — чтение\запись на диск, к тому на чем оно написано имеет весьма отдаленное отношение. Вот например storage-движок для Excheange таки переписали на .NET, чтобы быстрее работал.
Кстати, если весь процессинг выполняется сервером БД, то почему все остальное на C++ не написали? Ты ведь утверждаешь что было бы надежнее.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>
V>>>Определённую нишу она заняла — это там, где надо неторопливо выдавать что-то в веб на странички или как веб-сервисы или через родственные веб-ориентированные АПИ. Это ВСЁ! Т.е. из промышленного применения технологии — действительно всё! Там же, где требуется быстро и надежно — прямо на сегодня оттуда сие недоразумение вымыто, как и джава. Увы, сие медицинский факт.
G>>От повторения чушь правдой не станет. Сайты, которые обслуживают пользователей миллионами за доли секунды, написанные на .NET, Java и даже Ruby встречаются гораздо чаще, чем написанные на С++.
V>Т.е. ты не понял, почему сайты пишут на дотнете и php/ruby, а движки, типа Asterisk или виндовый или самсунговый медиа-сервера на сях?
Я думаю искоючительно по историческим причинам. В 2004 году, когда Asterisk только начинался не было быстрой реализации java и .NET, поэтому написали на C, переписывать сегодня никто не станет.
Даже вон Microsoft не хочет свой Lync переписать полностью на .NET, хотя клиент глючный до невозможности (неуправляемый код — ага), а уже два мажорных релиза было. А MetroLync весь переписали на JS и отлично работает, правда функций поменьше.
G>>Помоему это все твои фантазии. Или ты судишь по одному неудачному примеру. Так неудач у того же C++ на два порядка больше. Особенно там где реально высокие нагрузки и нетривиальные задачи.
V>Да почему же фантазии-то??? Есть дотнетные аналоги Asterisk-у и даже дотнетные медиа-сервера есть, и даже куча алгоритмов кодеков на дотнет переведена. Даже офисы какие-то на дотнете есть и даже просмотрщики PDF. Кароч, почти всё, что сделано на нейтиве уже давным-давно опробовано на дотнете и вряд ли по одному разу только. Какие проблемы-то? Просто не нужны никому, бо сливают нейтиву безбожно. От того и не востребованы.
Опять твои фантазии. Сейчас никому не надо переписывать существующие приложения и библиотеки с C на .NET. Исследовательские проекты — могут быть, а промышленные — тупо не за чем. Не потому что .NET плох, а потому что нативное приложение уже написано. Даже самые глючные неохотно переписывают, ибо экономически не оправдано.
V>Я же вполне четко обозначил промышленную дотнетную нишу. И конкретно ты в ней тоже сидишь, кста. Неужели ты не видишь позицию собственной ниши среди многообразия остальных??? Да и про "заказуху" я тебе не раз уже писал...
Это всего лишь твои фантазии. При, которые тают, при рассмотрении экономических факторов.
V>Жаль, что конкретно ты не понимаешь ни слова из того, что я тебе отвечаю. А разжевывать до дна формат сайта не позволяет. Блин, ты настолько невпопад попытался насыпать аргументы, что мне придется сделать паузу с тобой еще на годик.
А смысл? ты точно также будешь говорить про кодеки, астериск и процессинг, который "на самом деле выполняется в базе данных", и какую-то магическую реалтайм обработку.
Основная характеристика нужности языков и платформ не в количестве приложений, для старых языков их всегда будет больше, а в количестве вакансий. Вот зайди прямо сейчас на HH и сравни C++ с .NET\С# или Java.
НС>>>А нафига мне твои теоретические идеальные DBA, если и я и IT в реальных ситуациях видим совсем другое?
V>>Провайдеры пока кривые и косые G>В чем это выражается?
В их коде. Посмотри каким-нить декомпиллером.
V>>низлежащее ADO тоже не блещет. Например, я лично баг отправлял в MS когда-то по парсеру MS SQL потока. Исправили потом в одном из SP. G>Я видел баг в .NET 1.1, говорят был еще баг в .NET 2.0. Если что, текущая версия .NET 4.5.1. про баги не слышал.
От чего же тогда сайт регулярно выдает экран с ошибкой? )))
V>>В банках и на биржах тебе рассмеются в лицо, если ты им предложишь что-то на дотнете-Linq, для чего-то, где нужна хоть какая-то надежность. G>Внезапно видел Linq в банковском софте.
А ключевое слово не распарсил? Так-то дотнета полно везде, ес-но.
V>>Даже этот сайт, несложное, по-сути, приложение (это без попыток наезда) периодически выдаёт ошибки базы. G>Ты про дедлоки? Как это связано с Linq и ADO.NET?
Я про экран с ошибкой. Плюют в меня эксепшеном в дефолтной "растеризации".
V>>Блин, я такого даже вообразить не мог, когда пользовался ODBC или OLE DB, там надежность была железобетонная. G>База, как и любой внешний сервис может отвалится, не предупредив приложение.
Просто так ничего не отваливается. Отваливается чаще всего не база, не запрос, а тупо сам коннекшен. А вот почему отваливается коннекшен... Особенно, если на одном его конце ВНЕЗАПНО случился ГЦ или драйвер некорректно сформировал или распарсил запрос — это надо отдельную тему надо заводить, чтобы объяснить тебе происходящее.
G>Все возможные технологии отказоустойчивости все равно дают даунтайм на время failover. И дело вовсе не в ODBC или ADO.NET.
Не жужжи. Беспричинного отваливания второго звена трехзвенки от первого звена, при том, что географически они обычно связаны по локалке, а то и вовсе на одном железе... кароч, до дотнета я такого вообще никогда не наблюдал. )))
Фишка в том, что база не держит ненужное соединение долго. Не любит плохого клиента. А дотнетному парсеру на другой стороне порой потормозить. Ума же нет залить сначала нужные данные (или разумный их объем), потом парсить. Так тупо и парсит "по-живому" из сетки. OLEDB-драйвер работал через overlapped, т.е. фактически был многозадачен при одном прикладном потоке. А этот, убогий дотнетный, использует блокирующее чтение. Я бы его тоже периодически отваливал бы за его убогость.
G>Но даже если база не падает, то твой запрос, даже самый безобидный, может отвалиться по куче причин. Начиная от банального дедлока, заканчивая происками resource governor.
Дедлок в базе? )))
Тут кто-то пишет на курсорах пошагово? Не распланировав уровни блокировки данных? А, не! Тут же все крутые Linq-программисты, всё делается одним запросом, откуда дедлок-то?
V>>Это же БАЗА, ёптить! ))) G>Ты слишком мало работал с промышленными СУБД, если так говоришь.
Мне просто есть с чем сравнить. У меня тоже постоянно глючило с базой на дотнете. И не только у меня. Да у всех. Нет-нет, да глюканёт. А до дотнета — вообще никогда. Это же БАЗА, ёптить! ))
V>>Запросы на много страниц как раз неплохо сокращаются вьюхами и табличными ф-ями, содержащими самые популярные для базы наборы джоинов. Они почти всегда одни и те же, эти основные джоины.
G>Дело не во вьюхах и джоинах, а в предикатах и проекциях. Это две самые изменяемые части запросов.
Ох, как же с тобой сложно общаться. ))
Ну конечно же! Предикаты и проекции — самые изменяемый части!!! Методом несложной дедукции выводим, что джоины — это самые устойчивые конструкции в разных запросах. А что я предлагал запихивать во вьюхи? Ах, блин! Неужели их же?
G>Для примера тот же интернет-магазин средней руки, в нем есть таблица товаров из котром можно выбирать: G>1) По бренду G>2) По наличию G>3) По гарантии
G>А еще можно сортировать по: G>1) Цене G>2) Названию
G>И еще надо постраничное разбиение не забыть.
G>Даже если ты сделаешь вьюху, то все равно надо поверх нее сгенерировать около 15 запросов. И это мы еще проекции не считали.
Если для полной инфы по товару надо сделать джоин по примерно 5-ти таблицам (и это еще скромно), то я обязательно сделаю такую вьюху, где будет описан этот джоин. И буду пользовать её в сотнях разных запросов. Примаешь, вьюха для сервака "прозрачна". Т.е. это как текстовый макрос. Не бойся, что вьюха "выбирает" все поля, а тебе нужно в проекции всего пяток, нифига лишнего на самом деле не выбирается. Это просто уже предкомпиллированный приличный кусок SQL-конструкции.
G>Можно сделать это все на стороне базы, но надо будет клеить строки, что на стороне приложения делается гораздо проще.
Когда лишняя сотня миллисекунд не важна, то делай что хошь, господя.
V>>Вот я делаю выборку с итогом по некоему товару, скажем, из довольно большой таблицы движений, и каждый раз запрашиваю итоги по другому товару, будет ли тут кеширование запроса, если это не хранимка с параметром или табличная ф-ия, а прямо в тексте подаваемого запроса фигурирует новое числовое некое ID товара? G>Что такое кеширование запроса? SQL Server кеширует планы, чтобы не перекомпилировать.
G>Планы запросов кешируются всегда. Но по умолчанию для каждого запроса будет отдельный план (любой более-менее сложный запрос не параметризуется автомачтически). Для запросов с параметрами или для хранимок будет один план для любых параметров.
В том-то и дело, что не существует в природе "запросов с параметрами". Есть просто запросы и есть хранимки с параметрами. ))
Существует драйвер базы и временная хранимка уровня соединения на той стороне. Просто драйвер базы даёт такой синтаксис, что как бы просто запрос с как бы параметрами. Поэтому всё, что верно для хранимок, верно и для т.н. "запросов с параметрами".
G>Это может быть как хорошо, так и плохо. Если план стабилен (одинаково хорош для любых параметров), то кеширование планов улучшает работу. Если план нестабилен (как в большинстве нетривиальных хранимок), то кеширование планов мешает и надо вызывать перекомпиляцию.
Характерно, что именно подобные рассуждения я и имел ввиду, когда писал оставленный процитированный свой же абзац. Потому что параметры в запросы могут подставляться разным способом. В случае твоего Linq на каждое новое значение ID может генериться тупо другой итоговый текст с другим числовым ID, а не параметром. И как ты предлагаешь держать это всё под контролем сквозь всё приложение, где у нас будет запрос с параметром, а где тупо другой текст с другим числовым ID?
Здравствуйте, gandjustas, Вы писали:
V>>Т.е. ты не понял, почему сайты пишут на дотнете и php/ruby, а движки, типа Asterisk или виндовый или самсунговый медиа-сервера на сях? G>Я думаю искоючительно по историческим причинам. В 2004 году, когда Asterisk только начинался не было быстрой реализации java и .NET, поэтому написали на C, переписывать сегодня никто не станет.
Не, ну вы дотнетчики упоротые до невменяемости. Я тебе русским языком говорю, что дотнетных ПРОМЫШЛЕННЫХ проектов уровня Asterisk было минимум дофига. Ни один не взлетел. Не потому что был плохо написан. Наоборот!!! Asterisk был плохо написан и вот только лет 5 как почти переписан более-менее. Просто замечательнейшие проекты с замечательным кодом не взлетели, потому что на дотнет. Потому что разница throughput в 3-5 раз на том же железе, а уж относительно стабильности latency — так вообще жопа, разброс более чем на порядок отличается от разброса той же величины на нейтиве.
G>Даже вон Microsoft не хочет свой Lync переписать полностью на .NET, хотя клиент глючный до невозможности (неуправляемый код — ага), а уже два мажорных релиза было. А MetroLync весь переписали на JS и отлично работает, правда функций поменьше.
Я ж говорю, упоротые до невозможности.
Историческая справка. Еще в далеком 2003-м году пошли разговоры о том, что вот оч скоро Microsoft выпустит новую подсистему GUI для виндов. Т.е. настолько принципиально новую, что испокон веков работающая уже почти 30 лет подсистема ГУИ User32 уйдёт сразу в небытие! И все приложухи надо будет писать с помощью этой новой подсистемы! И конечно! КОНЕЧНО! Эта подсистема будет вся такая из себя управляемая. И с т.з. интероперабельности эффективнее будет ЛЮБЫЕ приложухи тоже, ес-но, писать сразу управляемыми. И эти первые беты будущего GUI, а тогда еще под изящным кодовым названием были доступны еще тогда же узкому кругу посвященных...
8 лет!!! Млять, 8 лет WPF пытался взлететь и не взлетел!!! И на мобилках вообще представлял из себя адЪ!! Поэтому там делали попытку приделать полунейтивный сервелат. А потом всего за 2 года было написано тоже самое полностью на нейтиве, причем, оно летает как на десктопе Win8, так и на мобильном WP8. И жрет батарейку мало. И теперь оно не WPF, а WinRT. А для дотнета сделали тонююююсенькую такую прослоечку. Ну "клей" же и есть "клей".
Кароч. Этот мега-эпик-фейл дотнетного WPF, который произошел прямо внутри MS, и который оттянул выход следущего поколения виндов минимум на пять лет!!! Который выжрал тонны денег самой MS и всех тех, кто это убожество использовал, а потом таки вынужден был перейти на WinRT.
Млять, каким надо быть упоротым, чтобы каждый день эти 10 лет наблюдать эту трагедию космического масштаба и не делать выводов? Не понимать, что у дотнета, в общем-то, никакой универсальности, а только вполне определенная ниша неспешных "бизнес-вычислений", веб-АПИ, веб-морд и несложной логики на юзверских аппликухах, которая выполняется со скоростью не чаще кликанья мышкой (или чем там сейчас на тач-скринах?).
Еще раз медленно.
8 лет дотнетных попыток для реализации самого масштабного изменения виндов за всю её историю — фейл. Потеря времени и миллиардов денег.
2 года той же самой разработки на нейтиве — мега-успех. Задешево.
Вопросы?
V>>Да почему же фантазии-то??? Есть дотнетные аналоги Asterisk-у и даже дотнетные медиа-сервера есть, и даже куча алгоритмов кодеков на дотнет переведена. Даже офисы какие-то на дотнете есть и даже просмотрщики PDF. Кароч, почти всё, что сделано на нейтиве уже давным-давно опробовано на дотнете и вряд ли по одному разу только. Какие проблемы-то? Просто не нужны никому, бо сливают нейтиву безбожно. От того и не востребованы.
G>Опять твои фантазии. Сейчас никому не надо переписывать существующие приложения и библиотеки с C на .NET. Исследовательские проекты — могут быть, а промышленные — тупо не за чем. Не потому что .NET плох, а потому что нативное приложение уже написано. Даже самые глючные неохотно переписывают, ибо экономически не оправдано.
Тебя в гугле видимо забанили. )))
Существовала одно время потребность в полностью байткодных приложениях. Тогда еще по наивности носились с "бинарной" переносимостью. Оч многие проекты были сделаны на дотнете. Сосредоточься. Не обязательно переписаны существующие, как бедняга EverNote или яховский мессенджер. А именно другие конторы, то бишь конкуренты, вложились в версии аналогичного, но дотнетного. Поверь, список ниш, где был опробован дотнет в коммерческих проектах — невероятно огромен. И пролетели все как один. Кроме ниш сайты/магазины/склад/бухучет/морда_лица_формочки.
Ты не в курсе, ты просто даже не представляешь масштабы этого эпик-фейла. Ты сразу влез в ту нишу, где дотнету место, поэтому не матерился на него мильон раз за эти годы. А люди матерились столько, что тебе лучше не слышать. Как оправдание сложившейся ситуации ты приводишь аргумент "legacy aplication", что, мол, нет смысла переписывать. Дудки и еще раз дудки. Да! Именно! На дотнете, действительно, дешевле зачастую переписать с 0-ля, чем поддерживать старое нейтивное приложение. И где это имеет смысл — так и делают. Жаль, что ниш этих кот наплакал. Вокруг всё нейтивное. Даже браузер, в котором отображается твоя веб-морда. Даже SQL-сервак и IIS. )))
G>Основная характеристика нужности языков и платформ не в количестве приложений, для старых языков их всегда будет больше, а в количестве вакансий. Вот зайди прямо сейчас на HH и сравни C++ с .NET\С# или Java.
Ну так сайты и прочая заказуха как у тебя, фиг ли. А ты бы считал не вакансии, а реальные кол-ва инсталляций продуктов. Для объективности зайди на вакансии той же MS/Intel/Samsung и вообще любых серьезных контор, делающих коробочные продукты и увидишь реальное положение дел в промышленной разработке, а не в заказухе под конкретного клиента некоего единичного экземпляра системы.
Здравствуйте, gandjustas, Вы писали:
V>>Именно поэтому на сегодня дотнет популярен как клиент к БД, где не надо торопиться. Именно в этой нише ты и существуешь, как и практически все популярные местные дотнетчики... кроме пары, занимающихся исключительно ср-вами для девелоперов. )) G>Именно поэтому наверное сайты олимпиад сделали на .NET. Вот только там торопиться надо еще как, ибо клиентов миллионы, а серваков от силы десятки. G>Ну и самое главное, что написать эти сайты на C++ не хватило бы времени между олимпиадами.
Эти сайты написаны на конструкторах сайтов. Там писать нечего. Новостной сайт ВООБЩЕ ничего не делает. Только накладывает инфу из базы на шаблон. Причем, торопиться там не надо, странички достаточно перегенерить со скоростью поступления этих новостей. А это даже не каждую минуту, амиго.
А на мильон юзверей для чтения выдаёт уже нейтивный IIS, конечно... даже не выходя из ядра.
Основной-то трафик — картинки и видео.
G>Да не мифическим, а вполне конкретным. А в СУБД основная проблема — чтение\запись на диск, к тому на чем оно написано имеет весьма отдаленное отношение. Вот например storage-движок для Excheange таки переписали на .NET, чтобы быстрее работал.
А чего же MS SQL на .NET не переписали, чтобы быстрее работал?
G>Кстати, если весь процессинг выполняется сервером БД, то почему все остальное на C++ не написали? Ты ведь утверждаешь что было бы надежнее.
V>Определённую нишу она заняла — это там, где надо неторопливо выдавать что-то в веб на странички или как веб-сервисы или через родственные веб-ориентированные АПИ. Это ВСЁ! Т.е. из промышленного применения технологии — действительно всё! Там же, где требуется быстро и надежно — прямо на сегодня оттуда сие недоразумение вымыто, как и джава. Увы, сие медицинский факт.
V>Ах, да, я забыл еще про написание ГУИ на дотнете. V>Но это я специально опустил. Ведь нелепо обсуждать сие на сегодня, бо прямо сейчас на плюсах-QT или HTML/HTML-5 писать клиентский ГУИ тоже получается аж бегом. А на Objective-C его тоже просто тонны написаны. Кароч, написание ГУИ давно ушло из области "сложных задач", слишком много всеобъемлющих ГУИ-фреймворков на сегодня под кучу языков и платформ.
V>В общем, ключевое для дотнета я подчеркнул — неторопливо. V>- ...
V>Список можно продолжать бесконечно. В этом списке — эпик фейлы и просто невероятные тонны зря выброшенных на дотнет денег. Так что, смирись. На сегодня ситуация такова, что перед новым серьезным заходом индустрии на дотнет потребуется минимум десяток лет... чтобы забыть все эти бесконечные дотнетные эпик фейлы. Переписывали обратно на традиционные технологии.
я скажу за игропром — все инструменты по созданию/редактированию внутриигрового контента на дотнете (те самые гуи). https://github.com/SonyWWS/ATF как паблик линк. Про контору где я, ничего писать не могу. Могу только молчать как рыба и глазами сигналить что ты в альтернативно-реальном бреду. Так что в рантайм игры ничего дотнетного не попадает, но кода на дотнете не меньше чем.
Здравствуйте, Ночной Смотрящий, Вы писали:
V>>Nullable булевское поле имеет тот же тип, что и предикат. НС>Нет. "WHERE tbl.BoolField" в большинстве диалектов написать нельзя, только "WHERE tbl.BoolField = 1".
Приплыли. Ты путаешь тип выражения и синтаксис языка. )))
V>> И вообще, я плохо понимаю причины твоих уточнений именно этого момента. НС>Потому что обрабатываются разные типы обычно существенно по разному.
Э, нет. Значения одинаковых типов одинаково обрабатываются. Может ты имел ввиду, что разные конструкции языка по-разному обрабатываются?
Просто есть четкий синтаксис относительно того, что есть предикат. Посмотри его БНФ, предикат обязательно состоит из выражений и логических операторов, кроме случаев вложенных запросов (и LIKE для строк). Так вот, эти самые выражения в составе предиката — они родимые и есть. И я писал об этом:
Предикат может выглядеть как (арифметическое_выражение > @X). Левая часть пригодна для упрощений. Тот же самый механизм пойдет и на вычислимое поле, по которому идет join, например.
Например, на стороне провайдера Linq после оптимизаций некое "WHERE 1" должно исчезать из целевого выражения, а некое "WHERE 0" уничтожать свой уровень запроса (подзапроса) целиком. Например, на верхнем уровне запроса в подбной ситуации даже не нужно обращаться к серваку, сразу возвращать пустую коллекцию, null или default(T) в зависимости от типа результата.
Здравствуйте, vdimas, Вы писали:
НС>>Нет. "WHERE tbl.BoolField" в большинстве диалектов написать нельзя, только "WHERE tbl.BoolField = 1". V>Приплыли. Ты путаешь тип выражения и синтаксис языка. )))
Ничего я не путаю. Логические и арифметические выражения в SQL разделены на уровне синтаксиса. Это я тебе как человек, который несколько парсеров SQL уже написал и сейчас еще один пишет говорю. Так что не надо мне баки про БНФ забивать, я его для сиквела почти наизусть уже помню.
V>>> И вообще, я плохо понимаю причины твоих уточнений именно этого момента. НС>>Потому что обрабатываются разные типы обычно существенно по разному. V>Э, нет.
Здравствуйте, IT, Вы писали:
IT>Ненадёжность ADO.NET была обусловлена наличием нативного кода в и без того глючном драйвере Sybase, написанного криворукими китайцами и необходимостью еженедельной перегрузки DBA-ями "супернадёжной" и одной из наиболее распространённой БД в банках, не имеющей к .NET никакого отношения.
Ну а этот сайт чего периодически выдаёт ошибку подключения к базе? Тоже Sybase?
Если ты называешь глюком вылет всего рантайма нафик, то у нас разные представления о глюках. Поэтому, твоё "итого" не считается.
Здравствуйте, IT, Вы писали:
V>>В банках и на биржах тебе рассмеются в лицо, если ты им предложишь что-то на дотнете-Linq, для чего-то, где нужна хоть какая-то надежность. IT>Можно я рассмеюсь в лицо тебе сидя в банке и используя дотнет-Linq уже много лет? Спасибо!
Нельзя. Пока оперативный учет целиком и полностью всем кластером не переедет на Linq и в базе не останется ни одного триггера и хранимки. А вот когда переедет, тогда и вернемся к этому еще раз. Сие событие мы узнаем из газет, бо это будет прецендент.
А для чего в банках используется дотнет прямо на сейчас — все хорошо знают: клиентское ПО (рабочие места), отчетность, неспешная аналитика, пересчет итогов, бухгалтерия и т.д. Кароч, примерно так же, как в складских программах.
Здравствуйте, Ночной Смотрящий, Вы писали:
V>>Ну продолжай. В кластерах же бывают разные принципы разделения данных. НС>В NoSql принцип обычно один используют — hash partitioning.
Т.е. тупое масштабирование вширь, правильно?
Ну так это оно и есть. Получаем простое умножение скорости внешнего носителя на кол-во узлов кластера.
Я так и писал:
аппаратура позволяет отказаться от реляционки. В т.ч. быстродействующие внешние носители, а не только размер ОП.
Наверно криво написал. Не только возросший размер ОП ставит под сомнение целесообразность классических реляционок, но и возросшие скорости обмена с внешними носителями тоже делают их ненужными.
Кароч, как только сложность алгоритмов перестанет измеряться кол-вом чтений страниц, т.е. как только эти затраты перестанут быть определяющими, тогда реляционки сдохнут окончательно.
Здравствуйте, vdimas, Вы писали:
IT>>Ненадёжность ADO.NET была обусловлена наличием нативного кода в и без того глючном драйвере Sybase, написанного криворукими китайцами и необходимостью еженедельной перегрузки DBA-ями "супернадёжной" и одной из наиболее распространённой БД в банках, не имеющей к .NET никакого отношения. V>Ну а этот сайт чего периодически выдаёт ошибку подключения к базе? Тоже Sybase?
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
НС>>>>А нафига мне твои теоретические идеальные DBA, если и я и IT в реальных ситуациях видим совсем другое?
V>>>Провайдеры пока кривые и косые G>>В чем это выражается?
V>В их коде. Посмотри каким-нить декомпиллером.
Нормальный код, почти все провайдеры сейчас в опенсорс, декомпилер не нужен.
Провайдеры сложная штука, пишут их только профи. Ты бы такой не написал в жизни.
V>>>низлежащее ADO тоже не блещет. Например, я лично баг отправлял в MS когда-то по парсеру MS SQL потока. Исправили потом в одном из SP. G>>Я видел баг в .NET 1.1, говорят был еще баг в .NET 2.0. Если что, текущая версия .NET 4.5.1. про баги не слышал.
V>От чего же тогда сайт регулярно выдает экран с ошибкой? )))
Из-за дедлока, а ты сообщение не читал? Один раз еще видел YSOD из-за того что база недоступна. Ни разу ошибок провайдера за 7 лет не видел на RSDN.
V>>>В банках и на биржах тебе рассмеются в лицо, если ты им предложишь что-то на дотнете-Linq, для чего-то, где нужна хоть какая-то надежность. G>>Внезапно видел Linq в банковском софте.
V>А ключевое слово не распарсил? Так-то дотнета полно везде, ес-но.
Ты хочешь сказать про надежность? А чем Linq ненадежен?
V>>>Даже этот сайт, несложное, по-сути, приложение (это без попыток наезда) периодически выдаёт ошибки базы. G>>Ты про дедлоки? Как это связано с Linq и ADO.NET?
V>Я про экран с ошибкой. Плюют в меня эксепшеном в дефолтной "растеризации".
Приложи скриншот, я не пойму о чем ты. Или хотябы текст ошибки.
V>>>Блин, я такого даже вообразить не мог, когда пользовался ODBC или OLE DB, там надежность была железобетонная. G>>База, как и любой внешний сервис может отвалится, не предупредив приложение.
V>Просто так ничего не отваливается. Отваливается чаще всего не база, не запрос, а тупо сам коннекшен. А вот почему отваливается коннекшен... Особенно, если на одном его конце ВНЕЗАПНО случился ГЦ или драйвер некорректно сформировал или распарсил запрос — это надо отдельную тему надо заводить, чтобы объяснить тебе происходящее.
Какой драйвер, ты о чем? При чем тут ГЦ? Такое ощущение что ты все слова а одном предложении написал.
G>>Все возможные технологии отказоустойчивости все равно дают даунтайм на время failover. И дело вовсе не в ODBC или ADO.NET. V>Не жужжи. Беспричинного отваливания второго звена трехзвенки от первого звена, при том, что географически они обычно связаны по локалке, а то и вовсе на одном железе... кароч, до дотнета я такого вообще никогда не наблюдал. )))
При чем тут дотнет? Тупо ставятся обновления, сервер перегружается, срабатывает failover, 5-30 секунд даунтайма. Независимо от того какая субд.
Ты не наблюдал потому что с отказоустойчивыми системами, которые 24\7.
V>Фишка в том, что база не держит ненужное соединение долго. Не любит плохого клиента. А дотнетному парсеру на другой стороне порой потормозить. Ума же нет залить сначала нужные данные (или разумный их объем), потом парсить. Так тупо и парсит "по-живому" из сетки. OLEDB-драйвер работал через overlapped, т.е. фактически был многозадачен при одном прикладном потоке. А этот, убогий дотнетный, использует блокирующее чтение. Я бы его тоже периодически отваливал бы за его убогость.
С .NET 2.0 SqlConnection поддерживает аснхронное чтение. Ты с 2005 года .NET то видел вообще?
G>>Но даже если база не падает, то твой запрос, даже самый безобидный, может отвалиться по куче причин. Начиная от банального дедлока, заканчивая происками resource governor. V>Дедлок в базе? )))
Да легко
V>Тут кто-то пишет на курсорах пошагово? Не распланировав уровни блокировки данных? А, не! Тут же все крутые Linq-программисты, всё делается одним запросом, откуда дедлок-то?
Дедлок можно схватить с обычным select в одной сессии и insert в другой, даже на read commited. .NET не при чем.
Но я понимаю что ты не в курсе.
V>>>Это же БАЗА, ёптить! ))) G>>Ты слишком мало работал с промышленными СУБД, если так говоришь.
V>Мне просто есть с чем сравнить. У меня тоже постоянно глючило с базой на дотнете. И не только у меня. Да у всех. Нет-нет, да глюканёт. А до дотнета — вообще никогда. Это же БАЗА, ёптить! ))
Судя по сообщениям только у тебя и глючило. Учитывая твой уровень знаний СУБД, мне кажется что проблема вовсе не в .NET.
V>>>Запросы на много страниц как раз неплохо сокращаются вьюхами и табличными ф-ями, содержащими самые популярные для базы наборы джоинов. Они почти всегда одни и те же, эти основные джоины.
G>>Дело не во вьюхах и джоинах, а в предикатах и проекциях. Это две самые изменяемые части запросов.
V>Ох, как же с тобой сложно общаться. )) V>Ну конечно же! Предикаты и проекции — самые изменяемый части!!! Методом несложной дедукции выводим, что джоины — это самые устойчивые конструкции в разных запросах. А что я предлагал запихивать во вьюхи? Ах, блин! Неужели их же?
И что ты собираешься выйграть от этого? Сокращение запросов на 3 строки? В чем смысл? Все равно придется генерить предикаты и проекции
G>>Для примера тот же интернет-магазин средней руки, в нем есть таблица товаров из котром можно выбирать: G>>1) По бренду G>>2) По наличию G>>3) По гарантии
G>>А еще можно сортировать по: G>>1) Цене G>>2) Названию
G>>И еще надо постраничное разбиение не забыть.
G>>Даже если ты сделаешь вьюху, то все равно надо поверх нее сгенерировать около 15 запросов. И это мы еще проекции не считали.
V>Если для полной инфы по товару надо сделать джоин по примерно 5-ти таблицам (и это еще скромно), то я обязательно сделаю такую вьюху, где будет описан этот джоин. И буду пользовать её в сотнях разных запросов. Примаешь, вьюха для сервака "прозрачна". Т.е. это как текстовый макрос. Не бойся, что вьюха "выбирает" все поля, а тебе нужно в проекции всего пяток, нифига лишнего на самом деле не выбирается. Это просто уже предкомпиллированный приличный кусок SQL-конструкции.
Я тоже вьюху сделаю, но как она поможет уменьшить количество работы по генерации кучи запросов?
V>>>Вот я делаю выборку с итогом по некоему товару, скажем, из довольно большой таблицы движений, и каждый раз запрашиваю итоги по другому товару, будет ли тут кеширование запроса, если это не хранимка с параметром или табличная ф-ия, а прямо в тексте подаваемого запроса фигурирует новое числовое некое ID товара? G>>Что такое кеширование запроса? SQL Server кеширует планы, чтобы не перекомпилировать.
G>>Планы запросов кешируются всегда. Но по умолчанию для каждого запроса будет отдельный план (любой более-менее сложный запрос не параметризуется автомачтически). Для запросов с параметрами или для хранимок будет один план для любых параметров.
V>В том-то и дело, что не существует в природе "запросов с параметрами". Есть просто запросы и есть хранимки с параметрами. ))
Существуют, эдак с 2000 года. Просто ты о них не знаешь. Более того в .NET используются с самой первой версии.
V>Существует драйвер базы и временная хранимка уровня соединения на той стороне. Просто драйвер базы даёт такой синтаксис, что как бы просто запрос с как бы параметрами. Поэтому всё, что верно для хранимок, верно и для т.н. "запросов с параметрами".
Опять бессвязный набор слов... Временная хранимка, драйвер базы, как-бы запрос... чушь полнейшая, уж прости.
G>>Это может быть как хорошо, так и плохо. Если план стабилен (одинаково хорош для любых параметров), то кеширование планов улучшает работу. Если план нестабилен (как в большинстве нетривиальных хранимок), то кеширование планов мешает и надо вызывать перекомпиляцию.
V>Характерно, что именно подобные рассуждения я и имел ввиду, когда писал оставленный процитированный свой же абзац.
Ну что ты имел ввиду я не знаю, но написал ты совсем другое.
V>Потому что параметры в запросы могут подставляться разным способом. В случае твоего Linq на каждое новое значение ID может генериться тупо другой итоговый текст с другим числовым ID, а не параметром.
Может, но не генерируется. Провайдеры не идиоты пишут к счастью.
V>И как ты предлагаешь держать это всё под контролем сквозь всё приложение, где у нас будет запрос с параметром, а где тупо другой текст с другим числовым ID?
Ты никогда не сможешь все держать под контролем. Ты всегда отдаешь часть контроля в обен на скорость разработки. В языке C отдали контроль над регистрами и над стеком. В C++ отдали контроль над способом передачи структур и генерацией кода, итд. Linq отдает контроль над гененрацией запроса, а авторы провайдеров берут на себя обязательства генерировать хорошие запросы. И как обычно у автоматического генератора получается лучше, чем у среднего программиста.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Т.е. ты не понял, почему сайты пишут на дотнете и php/ruby, а движки, типа Asterisk или виндовый или самсунговый медиа-сервера на сях? G>>Я думаю искоючительно по историческим причинам. В 2004 году, когда Asterisk только начинался не было быстрой реализации java и .NET, поэтому написали на C, переписывать сегодня никто не станет.
V>Не, ну вы дотнетчики упоротые до невменяемости. Я тебе русским языком говорю, что дотнетных ПРОМЫШЛЕННЫХ проектов уровня Asterisk было минимум дофига. Ни один не взлетел. Не потому что был плохо написан. Наоборот!!! Asterisk был плохо написан и вот только лет 5 как почти переписан более-менее. Просто замечательнейшие проекты с замечательным кодом не взлетели, потому что на дотнет. Потому что разница throughput в 3-5 раз на том же железе, а уж относительно стабильности latency — так вообще жопа, разброс более чем на порядок отличается от разброса той же величины на нейтиве.
Приведи хоть пару ссылок, а то слова пустые, доверие к ним нулевое.
V>Еще раз медленно. V>8 лет дотнетных попыток для реализации самого масштабного изменения виндов за всю её историю — фейл. Потеря времени и миллиардов денег. V>2 года той же самой разработки на нейтиве — мега-успех. Задешево.
V>Вопросы?
Я вот смотрю на Visual Studio, которая на WPF, и не понимаю о чем ты говоришь. А если учесть что из WPF родился UI для Windows 8 и Windows Phone, то не понимаю вдвойне.
V>>>Да почему же фантазии-то??? Есть дотнетные аналоги Asterisk-у и даже дотнетные медиа-сервера есть, и даже куча алгоритмов кодеков на дотнет переведена. Даже офисы какие-то на дотнете есть и даже просмотрщики PDF. Кароч, почти всё, что сделано на нейтиве уже давным-давно опробовано на дотнете и вряд ли по одному разу только. Какие проблемы-то? Просто не нужны никому, бо сливают нейтиву безбожно. От того и не востребованы.
G>>Опять твои фантазии. Сейчас никому не надо переписывать существующие приложения и библиотеки с C на .NET. Исследовательские проекты — могут быть, а промышленные — тупо не за чем. Не потому что .NET плох, а потому что нативное приложение уже написано. Даже самые глючные неохотно переписывают, ибо экономически не оправдано.
V>Тебя в гугле видимо забанили. )))
Видимо да, ибо гугл не находит IP телефонию на .NET, которая должна была переплюнуть Asterisk, никаких свидетельств что такие проекты вообще были.
Хоть пару ссылок приведи для подтверждения своих слов.
V>Существовала одно время потребность в полностью байткодных приложениях. Тогда еще по наивности носились с "бинарной" переносимостью. Оч многие проекты были сделаны на дотнете. Сосредоточься. Не обязательно переписаны существующие, как бедняга EverNote или яховский мессенджер.
Какие например? Paint.NET до сих пор живет и развивается.
EverNote написали на .NET, получили инвестиции, пошли переписывать на C++. С таким баблом можно было и на ассемблере написать. А бекенд то на .NET и остался. Если бы начали на C++, то не то что инвестиций, даже релиза не было бы.
V>А именно другие конторы, то бишь конкуренты, вложились в версии аналогичного, но дотнетного. Поверь, список ниш, где был опробован дотнет в коммерческих проектах — невероятно огромен. И пролетели все как один. Кроме ниш сайты/магазины/склад/бухучет/морда_лица_формочки.
Я видел пару таких проектов. Пролетели чисто по экономическим причинам. Для вытеснения конкурентов надо было 50+ человеко-лет работы вложить, а никто столько кормить не будет. Это сейчас, с развитием персональных устройств, можно создавать нишевые продукты и продавать их достаточно массово чтобы окупить затраты, а 10 лет назад такой возможности не было. Рынок уже был насыщен приложениями, а ниши были слишком узкими, чтобы на них реально зарабатывать.
V>Ты не в курсе, ты просто даже не представляешь масштабы этого эпик-фейла. Ты сразу влез в ту нишу, где дотнету место, поэтому не матерился на него мильон раз за эти годы. А люди матерились столько, что тебе лучше не слышать. Как оправдание сложившейся ситуации ты приводишь аргумент "legacy aplication", что, мол, нет смысла переписывать. Дудки и еще раз дудки. Да! Именно! На дотнете, действительно, дешевле зачастую переписать с 0-ля, чем поддерживать старое нейтивное приложение. И где это имеет смысл — так и делают. Жаль, что ниш этих кот наплакал. Вокруг всё нейтивное.
Очень даже представляю, если понабрать таких грамотных посонов как ты и отправить писать .NET приложение, то его ждет эпик фейл. Постоянные баги и борьба с ветрянными мельницами. А еще потом полученное убожество надо продать.
V>Даже SQL-сервак и IIS. )))
SQL Server в таком виде как мы его знаем был создан в 2000 году, дальше были только доработки. Но вот что странно, новые фичи SQL часто реализуются через .NETтипы. Ибо быстродействие зависит от скорости работы с диском, а не от того нативный там код или нет.
IIS более чем наполовину на .NET написан, но основная часть IIS — драйвер ядра HTTP.SYS, он ессесно нативный.
Так что оба примера мимо кассы
V>Даже браузер, в котором отображается твоя веб-морда.
Рассказать когда появился IE? Думаешь его кто-то будет переписывать?
G>>Основная характеристика нужности языков и платформ не в количестве приложений, для старых языков их всегда будет больше, а в количестве вакансий. Вот зайди прямо сейчас на HH и сравни C++ с .NET\С# или Java.
V>Ну так сайты и прочая заказуха как у тебя, фиг ли. А ты бы считал не вакансии, а реальные кол-ва инсталляций продуктов.
"Реальное количество продуктов" ни о чем, ибо старые всегда будут иметь больше. Кроме того сейчас эпоха сервисов, а не продуктов. Сегодня никто не хочет ставить себе лишний софт, если тоже самое есть в браузере.
V>Для объективности зайди на вакансии той же MS/Intel/Samsung и вообще любых серьезных контор, делающих коробочные продукты и увидишь реальное положение дел в промышленной разработке, а не в заказухе под конкретного клиента некоего единичного экземпляра системы.
Смотрю вакансии MS в России и вижу что ищут девелоперов в свой центр разработки пилить расширения для Axapta, на .NET ессесно. Хотя все таки рынок у 1С отжать.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Именно поэтому на сегодня дотнет популярен как клиент к БД, где не надо торопиться. Именно в этой нише ты и существуешь, как и практически все популярные местные дотнетчики... кроме пары, занимающихся исключительно ср-вами для девелоперов. )) G>>Именно поэтому наверное сайты олимпиад сделали на .NET. Вот только там торопиться надо еще как, ибо клиентов миллионы, а серваков от силы десятки. G>>Ну и самое главное, что написать эти сайты на C++ не хватило бы времени между олимпиадами.
V>Эти сайты написаны на конструкторах сайтов. Там писать нечего. Новостной сайт ВООБЩЕ ничего не делает. Только накладывает инфу из базы на шаблон. Причем, торопиться там не надо, странички достаточно перегенерить со скоростью поступления этих новостей. А это даже не каждую минуту, амиго.
V>А на мильон юзверей для чтения выдаёт уже нейтивный IIS, конечно... даже не выходя из ядра. V>Основной-то трафик — картинки и видео.
Это твои фантазии. Посмотри на Channel9, там с каждой олимпиады рассказывают что и как было сделано.
G>>Да не мифическим, а вполне конкретным. А в СУБД основная проблема — чтение\запись на диск, к тому на чем оно написано имеет весьма отдаленное отношение. Вот например storage-движок для Excheange таки переписали на .NET, чтобы быстрее работал. V>А чего же MS SQL на .NET не переписали, чтобы быстрее работал?
MS SQL и так с диском хорошо работает, переписывание вряд ли бы дало ченить. Зато для новых фич .NET не стесняются использовать.
G>>Кстати, если весь процессинг выполняется сервером БД, то почему все остальное на C++ не написали? Ты ведь утверждаешь что было бы надежнее. V>Дык, а сервер БД, по твоему, на чем написан?
Да при чем тут сервер, я про приложение. Оно же общается с кучей банкоматов, и фронтовых систем. В самой базе основная проблема — работа с диском, а не скорость исполнения кода.
Здравствуйте, gandjustas, Вы писали:
V>>>>Т.е. ты сам себе ПМ, аналитик, архитектор и тот самый Вася, если тебе через 10 мин (!!!) потребовалось третье поле. )) G>>>Как это связано? Чтобы добавить поле нужен аналитик, архитектор и еще кто-то?
V>>Ха-ха три раза. V>>Сначала код, так? V>>Например, для среднеразмерной складской программы?
G>Почему бы и нет? У тебя с этим проблемы?
А бизнес-процессы из головы? )))
Сколько складских программ написал уже? Сильно отличались? А вообще хоть что-то похожее было? )))
G>При чем тут внешние ностели? В большинстве NoSQL баз производительность падает до неприличных значений когда БД перестает влезать в ОП. G>А SQL умудряется вполне достойно работать на базах объемами в сотни раз превышающими ОП на том же железе.
Во-во, ты невнимательно меня читаешь. Еще раз перечитай те места, где я говорю, для каких сценариев нужны реляционки. Ты же только опять и снова подставился на весь мир. )))
G>Но для большинства программистов разница SQL или NoSQL как раз в том как с базой работать. NoSQL предлагает самый прямолинейный подход — сериализация объектов целиком, даже думать не надо, просто вызвал Save и все. Проблемы начинаются когда данные оказываются сильно связанными, присутствуют циклы в связях. Тогда NoSQL предлагает такой же прямолинейный подход — тяни все объекты и делай join руками или делай индекс и напрямую к индексу обращайся. SQL все это делает внутри, далеко не очевидным образом, что и вызывает проблемы у программистов.
)))
Давно хотел спросить, сколько тебе лет... Можно не отвечать, это я так... )))
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>>>Т.е. ты сам себе ПМ, аналитик, архитектор и тот самый Вася, если тебе через 10 мин (!!!) потребовалось третье поле. )) G>>>>Как это связано? Чтобы добавить поле нужен аналитик, архитектор и еще кто-то?
V>>>Ха-ха три раза. V>>>Сначала код, так? V>>>Например, для среднеразмерной складской программы?
G>>Почему бы и нет? У тебя с этим проблемы?
V>А бизнес-процессы из головы? ))) V>Сколько складских программ написал уже? Сильно отличались? А вообще хоть что-то похожее было? )))
Учетная часть везде одинаковая (двойная запись)+темпоральная часть, которая историю изменнеий хранит. Это как-бы и самая проблемная часть. А сверху уже операции относительно несложно делаются.
А в целом проще готовую платформу взять, типа 1с.
G>>Но для большинства программистов разница SQL или NoSQL как раз в том как с базой работать. NoSQL предлагает самый прямолинейный подход — сериализация объектов целиком, даже думать не надо, просто вызвал Save и все. Проблемы начинаются когда данные оказываются сильно связанными, присутствуют циклы в связях. Тогда NoSQL предлагает такой же прямолинейный подход — тяни все объекты и делай join руками или делай индекс и напрямую к индексу обращайся. SQL все это делает внутри, далеко не очевидным образом, что и вызывает проблемы у программистов.
V>))) V>Давно хотел спросить, сколько тебе лет... Можно не отвечать, это я так... )))
Мне 29. Но я и без этого вижу, что ответить тебе нечего.
Здравствуйте, Ночной Смотрящий, Вы писали:
V>>Ну а этот сайт чего периодически выдаёт ошибку подключения к базе? Тоже Sybase? НС>Не, MSSQL. Но тоже на С++ писано.
Но пока был на обычном ASP в прошлом, ни разу такой ошибки не было. Любопытно, у вас там было ADO, DAO или нейтивная либа доступа к MS SQL?
Я наблюдаю периодические вылеты ADO.Net не только здесь. И рядом указал одну из причин. Еще возможная причина — недетерминированное освобождение ресурсов. При хорошей нагрузке можно упереться в превышение максимального кол-ва открытых хендлов ОС. При детерминированном освобождении такое встречается всяко реже.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, Ночной Смотрящий, Вы писали:
V>>>Ну а этот сайт чего периодически выдаёт ошибку подключения к базе? Тоже Sybase? НС>>Не, MSSQL. Но тоже на С++ писано.
V>Но пока был на обычном ASP в прошлом, ни разу такой ошибки не было. Любопытно, у вас там было ADO, DAO или нейтивная либа доступа к MS SQL?
V>Я наблюдаю периодические вылеты ADO.Net не только здесь. И рядом указал одну из причин. Еще возможная причина — недетерминированное освобождение ресурсов. При хорошей нагрузке можно упереться в превышение максимального кол-ва открытых хендлов ОС. При детерминированном освобождении такое встречается всяко реже.
Снова твои фантазии. В .NET с весрии 2.0 используется пул соедиений. По умолчанию до 100 соединений в пуле. Учитывая 50 рабочих потоков в пуле asp.net, а более одного соединения на поток не нужно, то даже 100 это много.
При применении асинхронных обработчиков HTTP может быть понадобится увеличить до 1000. Лимит на количество дескрипторов — около 16 тысяч в очень древних версиях windows. В нынешних версиях упереться в лимит крайне сложно.
Будь добр укажи текст ошибки при "вылете ADO.NET", или приведи ссылку с описанием проблемы. А то ты сказки рассказываешь. Я 8 лет с .NET работаю (гораздо больше тебя судя по всему) и видел ошибок ADO.NET на порядок меньше, чем ты пишешь.
Здравствуйте, gandjustas, Вы писали:
V>>Основной-то трафик — картинки и видео. G>Это твои фантазии. Посмотри на Channel9, там с каждой олимпиады рассказывают что и как было сделано.
Пытаться оспорить процитированное — это жесть.
Ну и про предрендерённые странички ты тоже вежливо не откомментировал. Так же как и про наиболее вероятную скорость поступления событий.
V>>А чего же MS SQL на .NET не переписали, чтобы быстрее работал? G>MS SQL и так с диском хорошо работает, переписывание вряд ли бы дало ченить.
Ты всерьёз в это веришь, что перепсывание MS SQL на дотнете ничего не изменит? )))))
G>Да при чем тут сервер, я про приложение. Оно же общается с кучей банкоматов, и фронтовых систем. В самой базе основная проблема — работа с диском, а не скорость исполнения кода.
Уже это не так для современных рейдов SSD. И скорость оч важна, ес-но.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Основной-то трафик — картинки и видео. G>>Это твои фантазии. Посмотри на Channel9, там с каждой олимпиады рассказывают что и как было сделано.
V>Пытаться оспорить процитированное — это жесть. V>Ну и про предрендерённые странички ты тоже вежливо не откомментировал. Так же как и про наиболее вероятную скорость поступления событий.
Зачем мне твои домыслы комментировать. Вот из первых уст что реально работало — http://channel9.msdn.com/Search?term=olympic%20games#ch9Search&type-session=true
V>>>А чего же MS SQL на .NET не переписали, чтобы быстрее работал? G>>MS SQL и так с диском хорошо работает, переписывание вряд ли бы дало ченить.
V>Ты всерьёз в это веришь, что перепсывание MS SQL на дотнете ничего не изменит? )))))
Кроме того что MS угрохает на это 4-6 лет или больше, то практически ничего.
G>>Да при чем тут сервер, я про приложение. Оно же общается с кучей банкоматов, и фронтовых систем. В самой базе основная проблема — работа с диском, а не скорость исполнения кода. V>Уже это не так для современных рейдов SSD. И скорость оч важна, ес-но.
И ты пропустил собственно вопрос. Если скорость важна, а надежность C++ кода выше, то почему процессинг на java?
Здравствуйте, vdimas, Вы писали:
V>Но пока был на обычном ASP в прошлом, ни разу такой ошибки не было.
Обычный ASP, насколько я знаю, был в те времена когда нагрузка на сервер была на пару порядков меньше. Но мне все же интересно послушать, как обычный ASP избавляет от дедлоков.
V>Я наблюдаю периодические вылеты ADO.Net не только здесь.
Дедлок это никоим образом не вылет ADO.Net, дедлоки детектирует mssql.
V>Еще возможная причина — недетерминированное освобождение ресурсов.
Ресурсы mssql освобождаются детерминированно.
V> При хорошей нагрузке можно упереться в превышение максимального кол-ва открытых хендлов ОС.
НС>Это инициатива SQL Server Team. И ломать там ничего не надо, надо просто красиво оформить доступ к телу минуя парсер SQL.
А кэш планов как будет работать? Сейчас же строка SQL является ключом для кэша.
Интересно как это будет, сейчас я могу посмотреть состояние кэша, посмотреть тексты запросов, которые находятся в кэше. А что я увижу для linq запросов, linq запросы будут показаны мне в виде как-то строки?
НС>Текста — может быть. А декомпозированный SQL запрос, на практике, в 99% случаев собирается склеиваиванием датасетов и дописыванием в предикаты по AND. Для всего этого возможностей выражений в C# за глаза. НС>Ты же пытаешься вытащить какие то экзотические случаи, которые не в кажом проекте вообще бывают, и на основании этого заявить, что это все хуже чем фатальнейший прощелк с девэкспириенсом в твоей библиотечке, вылазящий строго на каждом запросе строго при каждой его модификации.
Видимо, твои и мои практики сильно отличаются, если для тебя склейка по AND это 99% динамического SQL-я. Вообще, мне неоднократно встречались люди, практика которых укладывалась в не динамический SQL. Не динамический SQL можно даже на хранимых процедурах оставить. Делаем кодогенерацию по хранимым процедурам и всё (это даже EF умеет). Люди разные, практики у них тоже разные, ты вот отошел от не динамического SQL, но не сильно далеко.
Но зачем себя ограничивать, если ранее известные для этого причины теперь устранены.
НС>А обоснование я увидел ровно одно — личне тебе некомфортно не видеть SQL. Браво, чо.
Не правильно делаешь акцент на мне и на SQL. Акцент надо делать вот на чем. При разработке приложения с использованием реляционной СУБД важно понимать, какой фрагмент кода является декларативным описанием запроса и обрабатывается СУБД, а какой фрагмент кода компилируется в IL и исполняется .NET рантаймом. Такое понимание необходимо, поскольку СУБД и .NET рантайм вещи совсем разные по своей природе. Абстрагирование от такого разделения ни к чему хорошему не приведет. Поэтому, да, я хочу видеть границы фрагментов кода, где декларативный запрос для СУБД, а где код, переходящий в IL. linq же всё смешивает, часть linq выражения преобразуется в SQL строку, а часть в IL.
Причем реляционные СУБД предлагают очень простой интерфейс в виде набора: колонка+значение примитивного типа. Проблема крайне прозрачна -- сделать этот набор типизированным. Зачем что-то еще делать? Это и отражено в примере интерфейсом IMessageInfo.
Практика, когда типы возникают из потребностей, является распространённой. Например, ASP.NET MVC, там model это View Model, т.е. типы, которые возникают из потребностей View.
AP>>Получается задача сложнее, чем просто обойти парсер SQL, как ты писал выше. НС>Не сильно.
Тем не менее, изменения в ядре СУБД потребуется сделать довольно глубоко. Для изменений глубоко в СУБД нужны веские причины. А тут мотивация совершенно непонятная, зачем вообще это делать? Зачем в ядре СУБД поддерживать ветвление LINQ/SQL?
А в SQL Management Studio можно будет писать LINQ запросы?
Если LINQ самодостаточная технология, то делайте полноценную СУБД с нуля. Если же LINQ не самодостаточен, тогда пусть не лезет куда не следует, а принимает правила базовой технологии. Правда, если честно принять правила базовой технологии, то от LINQ почти ничего не останется. Короче, как промежуточное звено LINQ неудобен, и поэтому не нужен, а полноценную СУБД никто разрабатывать не собирается, более того, там даже теория еще не до конца продумана, в отличии от того, что Кодд сделал еще в 1969 году.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>А тут мотивация совершенно непонятная, зачем вообще это делать?
1) Устранить лишний парсинг
2) Упростить создание ORM с собственными способами построения запросов.
AP> Зачем в ядре СУБД поддерживать ветвление LINQ/SQL?
Почему обязательно LINQ? Просто нетекстовый API для тех ситуаций, где сейчас SQL синтезируется. А что там на входе — LINQ, Query Builder или собственный язык запросов — неважно.
AP>А в SQL Management Studio можно будет писать LINQ запросы?
Зачем?
AP>Если LINQ самодостаточная технология, то делайте полноценную СУБД с нуля.
Зачем?
AP> Если же LINQ не самодостаточен, тогда пусть не лезет куда не следует
НС>1) Устранить лишний парсинг
Какой видимый результат от этого будет? Генерация плана на порядки больше времени занимает, чем парсинг.
НС>2) Упростить создание ORM с собственными способами построения запросов.
Еще не известно что такое ORM, нужен ли он, а тут уже собираются для этого вносить изменения в ядро реляционной СУБД. Причина совсем не убедительная.
НС>Почему обязательно LINQ? Просто нетекстовый API для тех ситуаций, где сейчас SQL синтезируется. А что там на входе — LINQ, Query Builder или собственный язык запросов — неважно.
А чем текстовый запрос плох, только лишний парсинг? См. выше.
AP>>Если LINQ самодостаточная технология, то делайте полноценную СУБД с нуля. НС>Зачем?
Затем, что для наборов кортежей (отношений) SQL хороший domain-specific language. LINQ для этого не лучше. Возможно, LINQ проявит себя лучше на специально разработанном domain-е, т.е. СУБД, написанной с нуля.
Здравствуйте, vdimas, Вы писали:
V>Нет. Это итог попыток использования дотнета за последние лет 10. Везде идёт отказ от него в чем-то более-менее требующем надежности и предсказуемости.
Дружище, ты меня в очередной раз поразил в самое не могу. Если ты под "везде" понимаешь те жалкие два процента задач, где вместо .net можно найти более достойную альтернативу, то таки да, там "везде идёт отказ от него в чем-то более-менее требующем надежности и предсказуемости". Я это сказал ещё в самом начале, и грамотные парни не стали терять 10 лет, чтобы это понять.
V>Серьезно. Вот огромная система, целый конгломерат приложений, всё вместе составляющих биржу, входящую в 5-ку крупнейших, уже 3 года как полностью отказалась от дотнета для чего-то более-менее серьезного, кроме неспешных задач или сайтостроения. Потратила на "игры" с этой технологией астрономические суммы. А ты с таким невинным толкаешь такие фразы. Не стыдно?
Только не надо становиться в позу грозного родителя и стыдить меня как нерадивого школьника. Про альтернативную реальность тебе уже здесь не высказался только ленивый. Так что про серьёзность, неспешность и т.п. это всё не более чем твои фантазии. Подавляющее большинство бизнес софта в мире пишется на технологиях вроде .net и java. То, о чём ты говоришь либо ваша ошибка и неумение готовить, либо имеет отношение к мизерному количеству задач, которые нет смысла делать на .net. Ты же пытаешься раздуть свою собственную реальность до вселенского масштаба, хотя пока убедить в этом у тебя получается только себя самого.
Разговоры про сырость технологии — это всё разговоры в пользу бедных. Проблемы были, как же без них, но за 12 лет их так или иначе порешали. Сегодня проблемы .net, если их можно назвать проблемами, давно перенесены в совершенно другую область — идёт процесс отбраковки и шлифовки архитектурных решений, парадигм, фреймворков и прочих инструментов. То, что EF7 будет переписан с нуля как раз часть такого процесса. И дело не в его внутренних багах и кривом коде, дело в неверно взятой за основу концепции.
Ты же здесь пытаешься нас убедить в том, что проблемы .net — это проблема парсинга блоба в драйвере sql провайдера. И хотя у меня в моей реальности пока никаких таких проблем не было, хотя с блобами работать приходится, ну допустим это так. Есть/была такая проблема. И что? Конец дотнету? Это же просто смешно, судить о всей технологии по одному глюку. Я ожидал всё-таки чего-то более серьёзного и привычного, вроде производительности, реалтаймности и т.п. Оказывается .net в целом проигрывает плюсам потому что в ADO.NET криво написан парсинг блобов. Вот оно оказывается в чём дело! Нужно скорее переписать этот код и всё сразу станет зашибцом и круче C++! Самому не смешно?
Что же касается плюсов, то тут вот какое дело. Я пишу на .net ещё с бета версий, т.е. довольно давно, тем не менее на C/C++ я писал всё же немного дольше и могу сказать, что более глюко-благоприятной технологии, чем C/C++ в сегодняшнем мейнстриме не существует.
Небольшое гипотетическое отставание .net в производительности легко нивелируется дешевым железом, но даже здесь не всё так просто и однозначно. Максимальная производительность сегодня в первую очередь достигается алгоритмами и архитектурными решениями. Буквально пару дней назад обсуждали требования к железу для нашей системы, и мы как разработчики затруднились ответить на вопрос каковы наши минимальные и максимальные требования к железу. Мы может спокойно израсходовать от 1 до 1000 ядер, при этом они не обязательно должны быть на одном компьютере. Соответственно, наш заказчик может получить производительность от X до X*1000, поэтому спрашивать сколько и за что он готов заплатить нужно у него. У нас только одно дополнительное требование — из-за объёма обрабатываемых данных для максимальной производительности каждое дополниетлное ядро требует дополнительно около гигабайта памяти. Остальное пусть решает заказчик.
Можно было бы сделать чуть более быструю систему на плюсах? Возможно. Только это либо вылилось бы в феерические затраты, либо в очередной феерический провал. Что в общем-то почти и произошло. Только не на плюсах, а на твоих любимых сохранённых процедурах.
Думаю, что с плюсами всё было бы гораздо хуже. Как я уже сказал, более глюко-благоприятной технологии не существует. Но сегодня к этому ещё добавляется и доминирование в этой технологии личностей с весьма негибким мышлением. У меня не так много знакомых плюсовиков, но за редчайшим исключением глядя на них, образ успешного C++ программиста — это лысеющий дядька, просидевший на жопе в одной конторе 15 лет, занимающийся парсингом какого-нибудь фида для того, чтобы платить по счетам и безумно увлечённый кто рыбалкой, кто охотой, кто оружием, машинами или музыкой. Про последнюю версию стандарта C++ не все из них знают, что она вообще есть и большинство затрудняются сказать в каком году она вышла.
V>Не боись. На многих обслуживающих нишах дотнет остался. Я бы даже сказал — его достаточно много.
Ну да. Продолжу про лысеющих дядек. В моей реальности мне дотнета бояться не надо. Как раз наоборот. Ко мне периодически обращается народ с вопросами о работе, в том числе иногда и лысеющие дядьки. При этом они понимают, что обращаются к дотнетчику и делают это исключительно от отчаяния. Их душераздирающие истории стоит послушать. Если сегодня в Нью-Йорке опытный программист несколько месяцев не может найти работу, то это можно объяснить только его специализацией — плюсами. Дотнетчики разлетаются как пирожки в базарный день. Кстати, речь идёт если что о финансовой столице мира, где в твоей реальности дотнетчикам отведена лишь участь подметать дворы банков и чистить мусорные ящики бирж.
V>Технология всё-равно сырая. В 2009-м я потратил более недели на поиски причин периодических глюков подключения к майкрософтному SQL-серваку и обнаружил рефлектором прикольный баг парсера потока от SQL-сервака, когда идёт нарезка блоб-полей... Ну что тут говорить??? В святая-святых, в драйвере общения с базой(!!!) кривой индусский код.
Это мы уже обсудили.
V>Причем, кривизна не только в том месте, где был баг. Сам код кривой до невероятности. В сравнении с нейтивными опенсорсными дровами под какую-нить БД для Линухов — это же просто детский лепет, а не драйвер клиента БД!!!
А ты уверен, что в Линухе вообще есть код, который парсит поток нарезки блоба SQL-сервера?
V>Смирись. Технология еще сырая. И я не говорю, что ты в этом виноват или любой другой программист на дотнете. Но таковы дела. Очень много функционала. Действительно много. Он бесплатен. Т.е. совершенно эта прорва функционала бесплатна. Качество не может быть хорошим в короткие сроки при таких раскладах. Просто руки не будут успевать делать всю эту прорву функционала качественно.
Хорошо, что ты об этом сам заговорил. Про глюко-благоприятность я уже говорил? Кажется, говорил. Так вот, там, где дотнетчик сделает один баг, плюсовик того же уровня сделает на порядок больше. Это не я придумал, это медицинский факт, обоснованный природой самих технологий. Соответственно качество кода на .net и производительность программистов растёт примерно в той же прогрессии. Кажущиеся проблемы .net вызваны тем, что таки да, уровень девелоперов в целом ниже, чем у лысеющих дядек, пилящих один и тот же фид 15 лет, а также тем, что пока они всё ещё пилят свой фид, дотнетчики успевают наклепать на два порядка больше всяких полезных приложений.
V>Морда на нете уже много лет где. А насчет "процессонговой" части любопытно. Бо самый рантайм-процессинг все-равно выполняется серверами БД, а не внешними приложениями. А внешняя аналитика или неспешный пересчет всего и вся по закрытию банковского дня может запросто быть написан на чем-то управляемом. Собсно, это уже десяток лет так и есть.
Ёлы-палы, так вы всё процесите серверами БД? А я тут C++ по ходу поласкаю. Как не хорошо получилось. Ну да ладно. Перейдём тогда к лысеющим датабазным админам, которые похоже понятия не имеют о том, что такое расширяемые системы. Или всё таки имеют? Или вы всё же умудрились запихнуть всю вашу биржу в одну единственную базу данных вместе с процессингом! Крутые всё-таки в твоей реальности сервера баз данных. У нас таких ещё не придумали.
V>Ты сидишь в крайне узкой нише разработок и считаешь, что на этом всё! )) V>А что за пределами этой узенькой ниши — так сразу "альтернативная реальность".
Пять балов с жирным плюсом! Всё-таки я снимаю шляпу перед твоим умением выдавать желаемое за действительное. Молодец!
V>Не ты первый, кто развел крупные компании на серьезные инвестиции в никуда.
Как-то так получилось, что с моего первого проекта в штатах моя вторая профессиональная специализация — это вытаскивание провальных проектов из задницы (включая, кстати, в своё время этот сайт). На мой текущий проект меня пригласили как раз по этой причине. Кокое совпаданеи, что основная логика в этом проекте была реализована в виде сохранённых процедур. В новом проекте ни одной процедуры нет. Вместо них расширяемое на сотни ядер решение на .net. Уже сейчас видно, что по всем параметрам производительности мы впереди настолько, что этот вопрос снят с повестки дня. Но самое главное, текущая система уверенно деградирует по такому параметру как наращивание функциональности и простейшие фичи делаются неделями и с большой кровью. Мы эту проблему не то что сняли, а просто занулили.
Так ли у нас всё хорошо, потому что .net? Вовсе нет. Дурь в башке и кривые руки всё же большая причина неуспеха предыдущего проекта. Те, кто его начинал, кстати, рассматривали .net в качестве одной из альтернатив, но чего-то там у них не смоглось. .net — это в–ё же просто инструмент. Нормальный такой инструмент, который в нормальных руках позволяет делать нормальные проекты. А в тех двух процентах, где лучше использовать что-то другое, можно запросто использовать что-то другое.
Хотя в твоей реальности видимо всё по-другому.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, vdimas, Вы писали:
V>Ну а этот сайт чего периодически выдаёт ошибку подключения к базе? Тоже Sybase?
Этот сайт месяцами работает не то что бы в отсутствии обслуживающего персонала, а вообще без присмотра. Ваша биржа так может? Хотя бы день продержаться без полчишь следящих за ней админов? Нет? А у нас легко!
Было время когда глюки возникали по вине железа. Бывали проблемы из-за провайдера. Но чаще всего просто кто-то вдруг решает что-то подкрутить, немного косячит, QA у нас нет, так что приходится отлаживаться на пользователях. Когда фиче-бага стабилизируется, то глюки проходят и к сайту опять месяцами никто не подходит.
V>Если ты называешь глюком вылет всего рантайма нафик, то у нас разные представления о глюках. Поэтому, твоё "итого" не считается.
Испорченная память в нативном приложении — это проблема того же порядка.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, vdimas, Вы писали:
V>А для чего в банках используется дотнет прямо на сейчас — все хорошо знают: клиентское ПО (рабочие места), отчетность, неспешная аналитика, пересчет итогов, бухгалтерия и т.д. Кароч, примерно так же, как в складских программах.
Чья бы корова мукала. Запихнуть процессинг целой биржы в сохранённые процедуры базы данных — это офигительно спешное и главное супер расширяемое решение.
Если нам не помогут, то мы тоже никого не пощадим.
IT>Подавляющее большинство бизнес софта в мире пишется на технологиях вроде .net и java.
А как вот это понимать: Windows and Line of Business Applications: No Good Options?
На java ситуация точно такая же.
Получается что ни .net ни java не смогли предложить лучший UI, чем HTML/CSS/JS. А попытки были в течении нескольких лет. WPF, Silverlight в Maintenance Mode, WinRT что-то не особо взлетает. К слову, HTML/CSS/JS совсем не типизированный.
Это можно понимать как частное мнение какого-то чувака.
AP>Получается что ни .net ни java не смогли предложить лучший UI, чем HTML/CSS/JS. А попытки были в течении нескольких лет.
Чем HTML лучше того же WPF и что вообще подразумевается под "лучший UI"?
AP>WPF,
Ну не знаю. По мне так вроде нормально работает. Есть, конечно, косяки, в том числе касающиеся не только производительности. Например, сама по себе вполне качественная идея обезображена местами кривой имплементацией. Что касается производительности, то с ней всё впорядке, если не увлекаться кривыми левыми контролами и самому не злоупотреблять вложенностью контролов.
XAML — это по сути один большой костыль. Парни из MS вроде как сообразили, что для разметки UI пора делать свой собственный DSL, но не решились его сделать по человечески как тот же Razor, например. Вот и получился редкосный уродец на XML, который у нас в таких случаях выступает как универсальный всемогутор-языкозаменитель.
Всё это по сути лишь подтверждение моих слов о том, что идёт отбраковка и шлифовка.
AP>Silverlight в Maintenance Mode,
MS убила Silverlight по причине того, что оно как бы не пошло в вебе. При этом они совершенно не разглядели бизнес применения Silverlight. Идиоты, что тут можно сказать. В моей предыдущей конторе в MorganStanley Silverlight приложения начали расти как грибы. Очень удобно. C одной стороны C# и все прелести полноценного UI, с другой веб и zero deployment. И тут вдруг нате вам, технология перестаёт развиваться. Козлы, блин.
AP>WinRT что-то не особо взлетает.
Если ты про бизнес задачи, то он никогда и не взлетит. Для бизнес задач, функциональность которых сводится к размазыванию грязи пальцем по экрану вполне приспособлен и веб интерфейс. А что-то более серьёзное в концепцию тачскрина не вписывается.
AP>К слову, HTML/CSS/JS совсем не типизированный.
И в этом его главная проблема.
ЗЫ. А какие у нас имеются альтернативы UI на C++?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, SleepyDrago, Вы писали:
SD>я скажу за игропром — все инструменты по созданию/редактированию внутриигрового контента на дотнете (те самые гуи). https://github.com/SonyWWS/ATF как паблик линк. Про контору где я, ничего писать не могу. Могу только молчать как рыба и глазами сигналить что ты в альтернативно-реальном бреду. Так что в рантайм игры ничего дотнетного не попадает, но кода на дотнете не меньше чем.
Ты невнимательно меня читал, похоже. У нас тоже 99% утилит на дотнете.
Раньше GUI вообще на VB или Delphi писали. А в AutoCAD даже на своём диалекте Лиспа. Что как бы заранее показывает вычислительные требования к GUI продуктов-утилит.
Физический/графический игровой движок у вас на дотнете или как?
А если не на дотнете, то можно узнать — почему?
Здравствуйте, gandjustas, Вы писали:
G>Я вот смотрю на Visual Studio, которая на WPF, и не понимаю о чем ты говоришь.
А я говорил, что ты не понимаешь нифига. Visual Studio вышла до выхода WinRT. Более того, она должна работать даже на тех версиях виндов, где WinRT не поддерживается. Более того, запуск студии в 5-15 секунд никого не волнует. Это же утилитное приложение. Вот если бы виндовый калькулятор запускался 5-15 секунд, то никто бы его не использовал. Вот почему в коробочных продуктах фактически нет WPF.
G>А если учесть что из WPF родился UI для Windows 8 и Windows Phone, то не понимаю вдвойне.
А я говорил, что ты не понимаешь нифига. Этим UI должен был стать дотнетный "Авалон". Поищи по "Avalon Longhorn".
Avalon offers a fundamental change in how you interact with your computer, and is probably the most significant UI change since Windows 1.0. It promises fundamental changes in technology, such as the way graphics are buffered internally. These features will include more efficient integration with sound and video, complex graphics displays, and sophisticated use of transparency. Microsoft believes the real advances here will come when experts in human computer interactions are free from the limitations of Win32 and can develop new controls and techniques that offer more of an immersive experience.
Так вот. Эпик фейл WPF в том, что он так и не стал Авалоном. Заодно ЗАДЕРЖАЛ выход новых виндов более чем на 5 лет. Windows Vista должна была быть последним фейс-лифтом старых виндов, типа как Windows 98 перед Windows XP. А по-факту Windows Vista задержалась на 8 лет как основная операционка в виде "ребрендинга" Windows 7. И эта задержка могла бы продолжаться вечно, если бы не волевое решение переписать нафик Авалон на нейтиве.
Microsoft officials earlier this month announced the company is cutting some key features, such as the WinFS file system, from Longhorn, the next major version of Windows, to meet its late-2006 deadline.
Из Вики:
Windows 8 — операционная система, принадлежащая к семейству ОС Microsoft Windows, в линейке следующая за Windows 7 и разработанная транснациональной корпорацией Microsoft. Номер версии в линейке NT — 6.2. Поступила в продажу 26 октября 2012 года.
6 лет задержки из-за того, что дотнет так и не стал обладать необходимыми потребительскими характеристиками.
Масштаб этого эпик фейла не поддаётся осмыслению. Собсно, именно с конца 2006-го года начался обратный отсчет уровню доверия дотнету, как универсальной платформе. Прямо на сегодня этот уровень нулевой. Дотнет нифига не универсален, а занял лишь те ниши, в которых неплоха была и Джава. На этом всё.
V>>Тебя в гугле видимо забанили. ))) G>Видимо да, ибо гугл не находит IP телефонию на .NET, которая должна была переплюнуть Asterisk, никаких свидетельств что такие проекты вообще были.
G>Хоть пару ссылок приведи для подтверждения своих слов.
В 2005-2006 годах я занимался этим вопросом много и видел много таких проектов. На сегодня они не актуальны, ес-но, т.к. вопрос можно считать закрытым. Можешь поискать еще кодеки, например по speex dotnet. Я сходу нашел NAudio, например. Но более детальное знакомство показало, что для того же speex используется нейтивный кодек, хотя в проекте NSpeex были планы по релизу "родного" дотнетного кодека. Собсно, перевести открытый исходник на дотнет — это 2-3 дня работы разработчику средней руки. Я видел в те времена несколько "родных" дотнетных реализаций кодеков. Один из кодеков на дотнете как-то публиковал здесь я, для G.711. Портирование его из нейтива заняло меньше часа. Пользовали это в своих проектах. Характеристики производительности ни к черту. Поэтому, дотнет остался только для макетирования всех этих вещей, для боевого применения более половины движка переписали на нейтив, оставив дотнету только сигналинг.
Если сможешь заставить работать быстрее — велкам. )) При том, что этот кодек до невозможности примитивен, в сравнении с тем же speex.
V>>Существовала одно время потребность в полностью байткодных приложениях. Тогда еще по наивности носились с "бинарной" переносимостью. Оч многие проекты были сделаны на дотнете. Сосредоточься. Не обязательно переписаны существующие, как бедняга EverNote или яховский мессенджер. G>Какие например? Paint.NET до сих пор живет и развивается.
Paint.Net не требует быстродействия. Вообще. Я разработал графический редактор для конференций на дотнете в 2006-м, где участники конференций могут рисовать на одной доске совместно. Никакой скорости не требуется. Вообще. Потому что основные тормоза от самой сетки. Потому что события даже от самых крутых мышек поступали не чаще 100 раз в секунду. Более того, мой редактор векторный, участники конференций могут изменять объекты, нарисованные другими участниками. Это намного сложнее растровой графики.
В плане требований к производительности сравни с теми же нейтивными фильтрами для фотошлёпа, где даже на современных рабочих станциях хочется добавить мощщи. На дотнете это просто не влетит. От слова вообще. Се ля ви.
G>EverNote написали на .NET, получили инвестиции, пошли переписывать на C++. С таким баблом можно было и на ассемблере написать. А бекенд то на .NET и остался. Если бы начали на C++, то не то что инвестиций, даже релиза не было бы.
Не юли. ЗАЧЕМ они переписали клиента под нейтив? Причем, он переписан под нейтив на кучи мобильных платформ в т.ч.
Вот нафига было переписывать со сверхудобного дотнета на страшный и ужасный нейтив? Твои варианты?
G>Я видел пару таких проектов. Пролетели чисто по экономическим причинам. Для вытеснения конкурентов надо было 50+ человеко-лет работы вложить, а никто столько кормить не будет. Это сейчас, с развитием персональных устройств, можно создавать нишевые продукты и продавать их достаточно массово чтобы окупить затраты, а 10 лет назад такой возможности не было. Рынок уже был насыщен приложениями, а ниши были слишком узкими, чтобы на них реально зарабатывать.
А я видел кучу влетевших нейтивных продуктов в то же самое время, хотя, нейтивные, как ты понимаешь, требуют больше человеко-лет, так?
Так вот, по опыту серьезной разработки на дотнете и нейтиве одновременно я уже делился с тобой своими собственными наблюдениями еще пару лет назад (или даже больше). На дотнете можно оч быстро накидать "макет". Можно даже заставить его работать при полной функциональности. Затем, при попытке выжать эффективность с этого "макета" мы обнаруживаем, что вложения трудоёмкости оч быстро переплёвывают вложения трудоёмкости в сравнении с нейтивным вариантом. Ну т.е., когда такое же кол-во усилий по вылизыванию тратишь на нейтив, то результат просто несравнимый не в пользу дотнета. Поэтому, дотнет хорош там, где никакую эффективность ни от куда выжимать не надо, а надо чтобы написал — и оно работает и этого было уже достаточно.
G>Очень даже представляю, если понабрать таких грамотных посонов как ты и отправить писать .NET приложение, то его ждет эпик фейл. Постоянные баги и борьба с ветрянными мельницами. А еще потом полученное убожество надо продать.
Ну так в дотнет "планка вхождения" ниже или как? Или дотнет требует сверх-мега спецов, чтобы написать продаваемый коробочный продукт? Зря ты перешел на личности, кста. По опыту разбора с тобой технических моментов за последние года 4 я бы оценил твоё владение платформой .Net как очень посредственное и очень поверхностное. Ничего более-менее серьезного, чем то, что можно сделать, пользуя лишь готовые библиотеки и инструменты, тебе поручать нельзя. Т.е. ты типичный пользователь технологий, а не их разработчик.
V>>Даже SQL-сервак и IIS. ))) G>SQL Server в таком виде как мы его знаем был создан в 2000 году, дальше были только доработки. Но вот что странно, новые фичи SQL часто реализуются через .NETтипы.
Новые фичи самого сервака там реализуются в нейтиве, ес-но. Ты, наверно, хотел сказать, про поддержку хранимок на дотнете? Дык, Оракл это давно делает. Еще один дык от тебя и таких как ты говорит, что хранимки — это зло. Я уже запутался. Не поможешь распутать?
G>Ибо быстродействие зависит от скорости работы с диском, а не от того нативный там код или нет.
Та нифига. В "разогретой" базе индексы и статистика в основном сидят в ОП, а значит, скорость обработки их влияет существенно. Разница в скорости работы разогретой базы и не разогретой на порядки.
G>IIS более чем наполовину на .NET написан, но основная часть IIS — драйвер ядра HTTP.SYS, он ессесно нативный.
IIS нетивный полностью. Это тулзины для него на дотнете написаны и то, далеко не все. MMX-консоль нейтивная. А дотнетный ASPX — это обычный плагин, не хуже и не лучше остальных плагинов, таких как Jetty для хостинга джавовских сервлетов.
G>Так что оба примера мимо кассы
Возвращая тебе твои же собственные манеры: у вас дотнет головного мозга, коллега.
V>>Даже браузер, в котором отображается твоя веб-морда. G>Рассказать когда появился IE? Думаешь его кто-то будет переписывать?
Думаю, что с момента выхода дотнета прошло дохрена времени. Думаю, что существует просто море альтернативных HTML-движков, в т.ч. есть пара и на дотнете. Не взлетели на дотнете, увы. А на нейтиве — взлетели. Даже на этом сайте есть форум, посвящённый одному из них.
Более того, движок IE был фактически полностью переписан с выходом 8-го IE. Расскажи нам, когда же вышел IE 8. ))
V>>Ну так сайты и прочая заказуха как у тебя, фиг ли. А ты бы считал не вакансии, а реальные кол-ва инсталляций продуктов. G>"Реальное количество продуктов" ни о чем, ибо старые всегда будут иметь больше.
Дотнету уже 12 лет. А продуктов, моложе 12 лет — полно.
G>Кроме того сейчас эпоха сервисов, а не продуктов. Сегодня никто не хочет ставить себе лишний софт, если тоже самое есть в браузере.
На планшетах и мобилках полно софта. Но тот софт, который не свистелка и перделка — всегда нейтивный. Даже под Андроид. Виберы и его многочисленные клоны, например. Не хочу повторяться, я уже перечислял тебе много всего. Все эти продукты намного моложе дотнета.
V>>Для объективности зайди на вакансии той же MS/Intel/Samsung и вообще любых серьезных контор, делающих коробочные продукты и увидишь реальное положение дел в промышленной разработке, а не в заказухе под конкретного клиента некоего единичного экземпляра системы.
G>Смотрю вакансии MS в России и вижу что ищут девелоперов в свой центр разработки пилить расширения для Axapta, на .NET ессесно.
Во-во. Вот для чего дотнет в нише самой MS. Примерно та же ниша, что и у тебя. ))
А те программисты, которые не на Аксапте, там на что требуется, ы?
G>Хотя все таки рынок у 1С отжать.
Не отожмут. Философия Аксапты примерно такая же, как у Паруса. Поэтому — не отожмут никогда. Парусы/Аксапты хороши в крупном секторе с большими инвестициями. А для средних и мелких предприятий они пролетают из-за своей бизнес-модели. А эта модель, в свою очередь, целиком и полностью зависит от технологии платформы. Кароч, для программирования под Парус и Аксапту нужны спецы в программировании, в отличие от спецов сугубо в прикладной области, которые могут "настраивать" 1С. Не зря же огромное программистов 1С — девушки. Но их почти нет в разработке под Парус и Аксапту. Поэтому рынок 1С и не отожмут — это другой совсем рынок.
Здравствуйте, IT, Вы писали:
IT>Что же касается плюсов, то тут вот какое дело. Я пишу на .net ещё с бета версий, т.е. довольно давно, тем не менее на C/C++ я писал всё же немного дольше и могу сказать, что более глюко-благоприятной технологии, чем C/C++ в сегодняшнем мейнстриме не существует.
Твои данные устарели на 12 лет. Качество компиляторов, а так же тулзов поддержки разработки совсем не то. Про кач-во библиотек я вообще молчу. Их покрытие задач и их кач-во не сравнимо выросли за те же 12 лет.
Странный ты в своих аргументах, кароч. Дотнет, знач, равивался все эти годы, а нейтив стоял на месте. ))
IT>Небольшое гипотетическое отставание .net в производительности легко нивелируется дешевым железом, но даже здесь не всё так просто и однозначно.
К сожалению, всё просто и однозначно. Дотнет, действительно, пробовали на все подряд ниши. Вообще на все мыслимые ниши. Но в промышленном масштабе остался он только как клиент к БД или для написания утилит.
IT>Максимальная производительность сегодня в первую очередь достигается алгоритмами и архитектурными решениями.
Эта мантру я знаю наизусть. Предел сложности сверху О и прочее бла-бла-бла. Это всё оценочные пределы. Есть еще предел сложности снизу. Есть еще коэф К при переходе от оценочной стоимости алгоритма к реальной. Так вот, для дотнета этот К равен примерно 3-м. Т.е. для реальных задач, где требуется производительность, при прочих равных на нейтиве можно добиться в 3 раза быстрее. Но частенько бывает и в 10 раз.
IT>Буквально пару дней назад обсуждали требования к железу для нашей системы, и мы как разработчики затруднились ответить на вопрос каковы наши минимальные и максимальные требования к железу. Мы может спокойно израсходовать от 1 до 1000 ядер, при этом они не обязательно должны быть на одном компьютере. Соответственно, наш заказчик может получить производительность от X до X*1000, поэтому спрашивать сколько и за что он готов заплатить нужно у него. У нас только одно дополнительное требование — из-за объёма обрабатываемых данных для максимальной производительности каждое дополниетлное ядро требует дополнительно около гигабайта памяти. Остальное пусть решает заказчик.
Я же говорю — я не против посмотреть на первый успешный проект некоей реалтайм-системы на дотнете. Но ты же понимаешь, что прямо на сегодня этих прецендентов нет ВООБЩЕ. И если ты его создашь — то этим исключением лишь подтвердишь правило.
IT>Можно было бы сделать чуть более быструю систему на плюсах? Возможно. Только это либо вылилось бы в феерические затраты, либо в очередной феерический провал. Что в общем-то почти и произошло. Только не на плюсах, а на твоих любимых сохранённых процедурах.
Сравнил, блин, теплое с мягким.
Оставлю на твоей совести выделенную демагогию. Ты и сам знал, что демагогия, пока писал, но, видать, самоконтроль не справился. ))
Возьми ЛЮБОЕ приложение на плюсах возрастом 15+ лет, перепиши его, используя современный С++ и современные же библиотеки. Объем кода уменьшится раз в 10. Надежность увеличиться раз в бесконечно.
Все-таки вы не понимаете, что основной профит от дотнета вовсе не в ГЦ, а огромном кол-ве отлаженных библиотек. Но это было актуально на момент выхода первых джавы и немного актуально на момент выхода первых версий дотнета. Сейчас сложно не найти готовую и надежную нейтивную либу под какую-либо задачу.
А вот библиотек для хранимок я не видел. Там каждый велосипедик с 0-ля, ручками.
Понимаешь... Меня уже начинают раздражать ваши подобные спекуляции. Оставь тебе сейчас только базовые типы дотнета, компилятор, ГЦ, джит, кароч, только базовую платформу + интероп. И ты окажешься в положении разработчика хранимок и не факт, что на хранимках не выйдет получше.
IT>Думаю, что с плюсами всё было бы гораздо хуже.
Думаю, что на первом дотнете всё было бы еще хуже. А твой плюсовый опыт как раз тех времён.
IT>Как я уже сказал, более глюко-благоприятной технологии не существует. Но сегодня к этому ещё добавляется и доминирование в этой технологии личностей с весьма негибким мышлением. У меня не так много знакомых плюсовиков, но за редчайшим исключением глядя на них, образ успешного C++ программиста — это лысеющий дядька, просидевший на жопе в одной конторе 15 лет, занимающийся парсингом какого-нибудь фида для того, чтобы платить по счетам и безумно увлечённый кто рыбалкой, кто охотой, кто оружием, машинами или музыкой. Про последнюю версию стандарта C++ не все из них знают, что она вообще есть и большинство затрудняются сказать в каком году она вышла.
А у меня все знакомые плюсовики в курсе всех новых библиотек, всех изменений стандарта и всех новых парадигм.
Странный у тебя круг общения, кароч. То ДБА без профильного образования, то плюсовики, которые вовсе не плюсовики, а сишники, судя по описанию.
V>>Не боись. На многих обслуживающих нишах дотнет остался. Я бы даже сказал — его достаточно много.
IT>Ну да. Продолжу про лысеющих дядек. В моей реальности мне дотнета бояться не надо. Как раз наоборот. Ко мне периодически обращается народ с вопросами о работе, в том числе иногда и лысеющие дядьки. При этом они понимают, что обращаются к дотнетчику и делают это исключительно от отчаяния. Их душераздирающие истории стоит послушать. Если сегодня в Нью-Йорке опытный программист несколько месяцев не может найти работу, то это можно объяснить только его специализацией — плюсами. Дотнетчики разлетаются как пирожки в базарный день. Кстати, речь идёт если что о финансовой столице мира, где в твоей реальности дотнетчикам отведена лишь участь подметать дворы банков и чистить мусорные ящики бирж.
Странно. Это при том, что более-менее опытных плюсовиков вообще раздирают сегодня на части. В свободном рынке их просто нет — обычно их ПЕРЕМАНИВАЮТ с работы на работу, в отличие от сомна дотнетчиков. Я думаю, что те дядьки просто не могут пройти интервью. Ты поговори с ними по душам.
Я вот вижу на jobs.monster.com
C++ Software Developer for Ultra low-latency data delivery (NYC 150-250k+)
Прошелся по предложениям C#, для сеньоров в среднем 70-120К. Для сеньоров плюсовиков — 120-200к. Профит! ))
Более высокие ЗП для дотнетчиков — это уже не просто девелоперы, а еще много чего. Для плюсовика для той же ЗП достаточно быть просто девелопером. Вот тебе реальные расклады. А с твоими дядьками что-то не то. С тем же успехом они могли быть фортранщиками.
V>>Технология всё-равно сырая. В 2009-м я потратил более недели на поиски причин периодических глюков подключения к майкрософтному SQL-серваку и обнаружил рефлектором прикольный баг парсера потока от SQL-сервака, когда идёт нарезка блоб-полей... Ну что тут говорить??? В святая-святых, в драйвере общения с базой(!!!) кривой индусский код.
IT>Это мы уже обсудили.
Комментов про кривой код не было. Ты же должен был все эти 12 лет многократно лазить декомпиляторами в платформу (там же без рефлектора или аналога вообще было невозможно работать!!!). Качество кода ниже плинтуса. Весь мир это видит. А ты просто хвалишь своё болото, хотя прекрасно в курсе, что технологически это пока просто болото. И так будет еще долго, бо технология еще вовсю развивается и до устаканивания далеко.
V>>Причем, кривизна не только в том месте, где был баг. Сам код кривой до невероятности. В сравнении с нейтивными опенсорсными дровами под какую-нить БД для Линухов — это же просто детский лепет, а не драйвер клиента БД!!!
IT>А ты уверен, что в Линухе вообще есть код, который парсит поток нарезки блоба SQL-сервера?
Конечно. Дать ссылку?
Но можно посмотреть код других драйверов, зачем же именно под MS SQL? Мы же обсуждали сравнительное качество кода клиентских драйверов в опенсорсе и в дотнете. При том, что кач-во опенсорса обычно не на высоте.
V>>Смирись. Технология еще сырая. И я не говорю, что ты в этом виноват или любой другой программист на дотнете. Но таковы дела. Очень много функционала. Действительно много. Он бесплатен. Т.е. совершенно эта прорва функционала бесплатна. Качество не может быть хорошим в короткие сроки при таких раскладах. Просто руки не будут успевать делать всю эту прорву функционала качественно.
IT>Хорошо, что ты об этом сам заговорил. Про глюко-благоприятность я уже говорил? Кажется, говорил. Так вот, там, где дотнетчик сделает один баг, плюсовик того же уровня сделает на порядок больше.
А я 12 лет наблюдаю ровно обратное. Дотнет отучает думать. В нем баги делаются чаще. Просто их легче было ловить одно время, угу. Но уже лет 8 на нейтиве баги ловятся так же легко и непринужденно.
IT>Это не я придумал, это медицинский факт, обоснованный природой самих технологий.
Я хорошо знаю природу этих технологий. И ты хорошо знаешь, что я хорошо знаю. Нейтивная "ловушка" после дотнетного джита для отладки ничем не отличается от точно такой же ловушки в debug-версии бинарного образа. И да, сейчас не принято пользовать встроенные в С массивы, в С++ принято использовать контейнеры стандартных библиотек или буста. Так вот, там точно такие же все защиты в дебажном образе. И я не верю, что ты этого не знал. А нулевые указатели ловились отродясь. Просто еще дело в культуре разработки. В дотнете принято в начале методов проверять аргументы. Если этого не делать, то ошибку найти становилось сложновато, т.к. она может проявить себя не там, где возникла. Стоило в нейтиве укрепиться такой же точно культуре и оп-па!!! Такой же точно эффект в плане надежности и легкости отыскания багов.
IT>Соответственно качество кода на .net и производительность программистов растёт примерно в той же прогрессии.
Производительность программиста зависит от наличия готового библиотечного функционала. Я видел ситуации, когда этого готового функционала не было. И я бы не сказал, что разработка чего-нить с 0-ля на дотнете сильно дешевле. Дудки. Свои ограничения, свои причины увеличения трудоёмкости. Из-за особенностей шаблонов С++ полно задач, где именно библиотечный функционал на плюсах писать быстрее и приятнее.
IT>Кажущиеся проблемы .net вызваны тем, что таки да, уровень девелоперов в целом ниже, чем у лысеющих дядек, пилящих один и тот же фид 15 лет, а также тем, что пока они всё ещё пилят свой фид, дотнетчики успевают наклепать на два порядка больше всяких полезных приложений.
Это тоже устаревшая инфа. Посмотри, с какой скоростью сейчас разрабатываются всякие десктопы, свистелки и перделки под линуксоподобные оси. Когда ты заканчивал свою С++ карьеру, это было немыслимо. А сейчас эти приложухи клепаются быстрее дотнетных. Потому что уже ВСЁ ЕСТЬ.
Скажу так. Я все реже в последние годы пользую дотнет даже для макетирования или утилит. Чем больше доступного готового библиотечного функционала в нейтиве, тем меньше мне интересен дотнет для утилит и макетов. Смысла уже нет. Уже нет той потрясающей разницы в скорости разработки макета в дотнете vs нейтив, какая была еще буквально в 2005-м.
Вот только еще для ГУИ-утилит пользую исключительно дотнет, грешен. )) Если бы эти наглецы-подлецы из MS предоставили бы WinRT-слой и под предыдущие оси, хотя бы под Win7 (а технологически это ЭЛЕМЕНТАРНО), то писал бы уже ГУИ на XAML — WinRT — С++/CX.
Далее. Если пройтись по JIRA нашей конторы, то большинство багов — это "функциональные", то бишь касаются исключительно логики, а не "технологические", типа выхода за пределы массивов или нулевых указателей. Не пользуемся мы массивами. ))
V>>Морда на нете уже много лет где. А насчет "процессонговой" части любопытно. Бо самый рантайм-процессинг все-равно выполняется серверами БД, а не внешними приложениями. А внешняя аналитика или неспешный пересчет всего и вся по закрытию банковского дня может запросто быть написан на чем-то управляемом. Собсно, это уже десяток лет так и есть.
IT>Ёлы-палы, так вы всё процесите серверами БД? А я тут C++ по ходу поласкаю. Как не хорошо получилось. Ну да ладно. Перейдём тогда к лысеющим датабазным админам, которые похоже понятия не имеют о том, что такое расширяемые системы. Или всё таки имеют? Или вы всё же умудрились запихнуть всю вашу биржу в одну единственную базу данных вместе с процессингом! Крутые всё-таки в твоей реальности сервера баз данных. У нас таких ещё не придумали.
Ну так биржа не на MS SQL, господя. )))
Движок для транзакций бирж должен позволять работать в том же процессе. Опять же — биржа легко масштабируема из-за того, кто почти каждый продукт независим от других. Ну и запоминаемые транзакции в бирже тривиальны, таки, в отличие от транзакций распределённой складской системы, например. Для учета всех транзакций биржи достаточно всего одной изменяемой таблицы. И не всегда имеет смысл эту главную таблицу обслуживать именно через СУБД и тем более реляционную. Современные транзакционные/журналируемые файловые системы в мире unix заруливают любые мыслимые СУБД. В СУБД обычно хранят "развесистую" информацию справочного характера, которая подготавливается ДО открытия торгов.
V>>Ты сидишь в крайне узкой нише разработок и считаешь, что на этом всё! )) V>>А что за пределами этой узенькой ниши — так сразу "альтернативная реальность".
IT> Пять балов с жирным плюсом! Всё-таки я снимаю шляпу перед твоим умением выдавать желаемое за действительное. Молодец!
Парадокс блабла, однако. Я в твоей нише проработал с 96-го по 2002-й и потом регулярно приходилось по базам, сайтам, учёту и прочему. В курсе всего и вся. Вот там дотнет помог в полный рост. Но было много других ниш, где этот дотнет показал себя попросту вредителем, а не технологией.
Выпускаем и дотнетный движок для бирж в т.ч. Все сравнимые характеристики на уровне ведущих игроков (а мы и есть одни из ведущих). И у всех игроков решения под дотнет и джаву отстают по характеристикам примерно на порядок. Это нормально.
IT>На мой текущий проект меня пригласили как раз по этой причине. Кокое совпаданеи, что основная логика в этом проекте была реализована в виде сохранённых процедур. В новом проекте ни одной процедуры нет. Вместо них расширяемое на сотни ядер решение на .net. Уже сейчас видно, что по всем параметрам производительности мы впереди настолько, что этот вопрос снят с повестки дня. Но самое главное, текущая система уверенно деградирует по такому параметру как наращивание функциональности и простейшие фичи делаются неделями и с большой кровью. Мы эту проблему не то что сняли, а просто занулили.
Так я ж не против, чтобы клиентов к БД писали на дотнете. Не в дотнете тормоза для этого сценария, потому что. Но зато "бесплатный" маппинг затем в объекты — это прелэсть! Дуй да нижамай посильней! )) В нейтиве для подобного надо писать мапперы отдельно. Обычно, пишутся каким-нить кодогенератором, угу. Головняк, согласен. ))
IT>Так ли у нас всё хорошо, потому что .net? Вовсе нет. Дурь в башке и кривые руки всё же большая причина неуспеха предыдущего проекта.
Ага, проснулась совесть. Молодец! ))
IT>Те, кто его начинал, кстати, рассматривали .net в качестве одной из альтернатив, но чего-то там у них не смоглось. .net — это в–ё же просто инструмент. Нормальный такой инструмент, который в нормальных руках позволяет делать нормальные проекты. А в тех двух процентах, где лучше использовать что-то другое, можно запросто использовать что-то другое.
Если бы еще не спекуляция на процентах, вообще чудесная концовка вышла бы.
IT>Хотя в твоей реальности видимо всё по-другому.
Смешно в этой концовке лишь то, что именно это дословно я говорил аналогичное еще в 2005-м, когда всё для дотнета стало ясно. В моей реальности лишь другие проценты. Просто вы, дотнетчики, воспринимаете многое, с чем вы работаете, как "данное свыше", хотя это "данное" тоже было кем-то разработано, причем, на нейтиве. Ты пишешь на дотнете, пользуя нейтивную ОСь, под нейтивный сервак, с нейтивными фильтрами TCP, нейтивными дровами и сервисами, слушаешь музычку в найшниках, пользуя нейтивные кодеки, смотришь стримы через нейтивный AdobeFlash или нейивный же сервелат, пишешь под платформу, где основные её элементы — нейтивные, ес-но (ГЦ, джит, многие системные классы) и т.д. до бесконечности.
Твой дотнет — это ма-а-а-аленький такой островок под конкретно решаемую тобой задачу в океане нейтива вокруг этой задачи.
Здравствуйте, gandjustas, Вы писали:
V>>Пока не увижу в новостях, что где-то вышел движок биржи на Linq или банковский оп-день — это всё сказки про белого бычка. G>А ты видишь в новостях про биржи на ODBC или опердни на ADO?
Твой вопрос лишен смысла.
Биржи написаны на С/С++. ВСЕ единицы попыток переписать биржи на дотнет закончились отказом от этих попыток.
Наиболее часто вызываемые рантайм-транзакции в оперднях банков сделаны на хранимках.
G>Работа с данными не самая важная часть приложения, хотя зачастую и самая ресурсоемкая. А Linq вообще не более чем генератор запросов, от которого можно в будущем отказаться, если активная разработка уже не ведется (как сделали в StackOverflow).
Я ж говорю, что ты нифига не понимаешь. )))
Linq — это не просто генератор запросов, это еще мега-удобный маппер их результатов. В нейтиве такое на сегодня, увы, никак в подобном виде. В нейтиве код маппинга обычно генерируют отдельной тулзиной, типа http://www.qxorm.com/qxorm_en/home.html или http://www.codesynthesis.com/products/odb/, а то и просто ручками, см. boost::serialization. Только в следующем стандарте С++ ожидается, наконец, стандарт на ABI и на метаинформацию... только тогда можно будет делать сравнимые в плане удобства для разработчика мапперы на плюсах, без необходимости подключать и настраивать внешние утилиты для процесса разработки.
G>Но именно этот генератор запросов позволяет разрабатывать приложения с огромной скоростью, не нагружая DBA написанием селектов.
Ну вот AVK утверждает, что он не пользуется специфическим Linq-синтаксисом. А используемый им синтаксис был доступен мне еще хрен его знает когда через самописный генератор запросов + маппинг через BLT. Более того, в нейтивных генераторах запросов тоже примерно такой же синтаксис, как показывает AVK.
Вот ты используешь синтаксис запросов Linq или пишешь в "классическом" стиле?
Я ж чего с вами спорю. Мне же есть с чем сравнить. Я на дотнете периодически оч плотно, вижу что происходит и там и там.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>Я вот смотрю на Visual Studio, которая на WPF, и не понимаю о чем ты говоришь.
V>А я говорил, что ты не понимаешь нифига. Visual Studio вышла до выхода WinRT. Более того, она должна работать даже на тех версиях виндов, где WinRT не поддерживается. Более того, запуск студии в 5-15 секунд никого не волнует. Это же утилитное приложение. Вот если бы виндовый калькулятор запускался 5-15 секунд, то никто бы его не использовал. Вот почему в коробочных продуктах фактически нет WPF.
Действительно не понимаю как это связано. Похоже что связь у тебя в голове только существует.
G>>А если учесть что из WPF родился UI для Windows 8 и Windows Phone, то не понимаю вдвойне. V>А я говорил, что ты не понимаешь нифига. Этим UI должен был стать дотнетный "Авалон". Поищи по "Avalon Longhorn".
Кому должен? Может быть и стал бы, не будь у Синофски зуб на .NET. На WP таки сделали на .NET UI, только через несколько лет таки переписали на COM, чтобы единая платформа была.
V>
V>Avalon offers a fundamental change in how you interact with your computer, and is probably the most significant UI change since Windows 1.0. It promises fundamental changes in technology, such as the way graphics are buffered internally. These features will include more efficient integration with sound and video, complex graphics displays, and sophisticated use of transparency. Microsoft believes the real advances here will come when experts in human computer interactions are free from the limitations of Win32 and can develop new controls and techniques that offer more of an immersive experience.
V>Так вот. Эпик фейл WPF в том, что он так и не стал Авалоном. Заодно ЗАДЕРЖАЛ выход новых виндов более чем на 5 лет. Windows Vista должна была быть последним фейс-лифтом старых виндов, типа как Windows 98 перед Windows XP. А по-факту Windows Vista задержалась на 8 лет как основная операционка в виде "ребрендинга" Windows 7. И эта задержка могла бы продолжаться вечно, если бы не волевое решение переписать нафик Авалон на нейтиве.
Ты веришь в маркетинговый буллшит? Слишком много слов "должен\должна", тебе никто ничего не должен, успокойся.
V>6 лет задержки из-за того, что дотнет так и не стал обладать необходимыми потребительскими характеристиками.
При чем тут .NET? Почему это не помешало сделать UI для WP7 на .NET?
V>Масштаб этого эпик фейла не поддаётся осмыслению. Собсно, именно с конца 2006-го года начался обратный отсчет уровню доверия дотнету, как универсальной платформе. Прямо на сегодня этот уровень нулевой. Дотнет нифига не универсален, а занял лишь те ниши, в которых неплоха была и Джава. На этом всё.
Сильную роль сыграло развитие JS, которое по сути похоронило идею Rich Desktop UI, очень популярную в начале 20 века
V>>>Тебя в гугле видимо забанили. ))) G>>Видимо да, ибо гугл не находит IP телефонию на .NET, которая должна была переплюнуть Asterisk, никаких свидетельств что такие проекты вообще были.
G>>Хоть пару ссылок приведи для подтверждения своих слов.
V>В 2005-2006 годах я занимался этим вопросом много и видел много таких проектов. На сегодня они не актуальны, ес-но, т.к. вопрос можно считать закрытым. Можешь поискать еще кодеки, например по speex dotnet. Я сходу нашел NAudio, например. Но более детальное знакомство показало, что для того же speex используется нейтивный кодек, хотя в проекте NSpeex были планы по релизу "родного" дотнетного кодека. Собсно, перевести открытый исходник на дотнет — это 2-3 дня работы разработчику средней руки. Я видел в те времена несколько "родных" дотнетных реализаций кодеков. Один из кодеков на дотнете как-то публиковал здесь я, для G.711. Портирование его из нейтива заняло меньше часа. Пользовали это в своих проектах. Характеристики производительности ни к черту. Поэтому, дотнет остался только для макетирования всех этих вещей, для боевого применения более половины движка переписали на нейтив, оставив дотнету только сигналинг.
Я понял, про астериск были фантазии. Про кодеки — не ясно зачем их на .NET писать вообще, там же числомолотилка, .NET ничего не даст.
V>Специально нашел тот пост: http://www.rsdn.ru/forum/media/2926468
V>Если сможешь заставить работать быстрее — велкам. )) При том, что этот кодек до невозможности примитивен, в сравнении с тем же speex.
Пот посмотрел на код, его чуть ли не 1-в-1 можно на C заменить (даже не C++), только массивы надо извне передавать. А для .NET можно написать обертку, которая зовет эту либу.
V>>>Существовала одно время потребность в полностью байткодных приложениях. Тогда еще по наивности носились с "бинарной" переносимостью. Оч многие проекты были сделаны на дотнете. Сосредоточься. Не обязательно переписаны существующие, как бедняга EverNote или яховский мессенджер. G>>Какие например? Paint.NET до сих пор живет и развивается.
V>Paint.Net не требует быстродействия. Вообще. Я разработал графический редактор для конференций на дотнете в 2006-м, где участники конференций могут рисовать на одной доске совместно. Никакой скорости не требуется. Вообще. Потому что основные тормоза от самой сетки. Потому что события даже от самых крутых мышек поступали не чаще 100 раз в секунду. Более того, мой редактор векторный, участники конференций могут изменять объекты, нарисованные другими участниками. Это намного сложнее растровой графики.
Большинство десктопных приложений не требует быстродействия, вообще. Ни мессенджеры, ни заметки, ни какая-либо еще фигня. Быстродействия на десктопе требуют игры, в которых кстати игровая логика пишется на скриптовых языках, которые по твоему гораздо менее надежны и быстры А также кодеки, которые работают с непрерывными потоками информации.
V>В плане требований к производительности сравни с теми же нейтивными фильтрами для фотошлёпа, где даже на современных рабочих станциях хочется добавить мощщи. На дотнете это просто не влетит. От слова вообще. Се ля ви.
Хм... почему фотошопу требуется быстродействие, а paint.nt — нет? Разница только в тормозных фильтрах? Которые кстати тоже числомолотилки.
G>>EverNote написали на .NET, получили инвестиции, пошли переписывать на C++. С таким баблом можно было и на ассемблере написать. А бекенд то на .NET и остался. Если бы начали на C++, то не то что инвестиций, даже релиза не было бы.
V>Не юли. ЗАЧЕМ они переписали клиента под нейтив? Причем, он переписан под нейтив на кучи мобильных платформ в т.ч. V>Вот нафига было переписывать со сверхудобного дотнета на страшный и ужасный нейтив? Твои варианты?
Потому что они могли это сделать и у них была на это куча бабла. А альтернативы какие? Разогнать команду и положить бабло в карман? Увы на инвестиционные деньги так поступать нельзя.
Дали бы мне столько бабла, я бы тоже все переписал на C++, даже за 1% прироста быстродействия.
Но мне не дают столько, поэтому пишу на .NET и проблем из-за этого не испытываю.
G>>Я видел пару таких проектов. Пролетели чисто по экономическим причинам. Для вытеснения конкурентов надо было 50+ человеко-лет работы вложить, а никто столько кормить не будет. Это сейчас, с развитием персональных устройств, можно создавать нишевые продукты и продавать их достаточно массово чтобы окупить затраты, а 10 лет назад такой возможности не было. Рынок уже был насыщен приложениями, а ниши были слишком узкими, чтобы на них реально зарабатывать.
V>А я видел кучу влетевших нейтивных продуктов в то же самое время, хотя, нейтивные, как ты понимаешь, требуют больше человеко-лет, так?
Ну приведи хотябы маленький список из этой кучи. Особенно, которые стартанули за последние 5-10 лет.
V>Так вот, по опыту серьезной разработки на дотнете и нейтиве одновременно я уже делился с тобой своими собственными наблюдениями еще пару лет назад (или даже больше). На дотнете можно оч быстро накидать "макет". Можно даже заставить его работать при полной функциональности. Затем, при попытке выжать эффективность с этого "макета" мы обнаруживаем, что вложения трудоёмкости оч быстро переплёвывают вложения трудоёмкости в сравнении с нейтивным вариантом. Ну т.е., когда такое же кол-во усилий по вылизыванию тратишь на нейтив, то результат просто несравнимый не в пользу дотнета. Поэтому, дотнет хорош там, где никакую эффективность ни от куда выжимать не надо, а надо чтобы написал — и оно работает и этого было уже достаточно.
Ты опять про свой мир говоришь. Я никогда проблем с оптимизацией .NET коа до приемлемого уровня быстродействия не испытывал. Я конечно верю, что у тебя с этим проблемы, но .NET в этом не виноват.
G>>Очень даже представляю, если понабрать таких грамотных посонов как ты и отправить писать .NET приложение, то его ждет эпик фейл. Постоянные баги и борьба с ветрянными мельницами. А еще потом полученное убожество надо продать.
V>Ну так в дотнет "планка вхождения" ниже или как? Или дотнет требует сверх-мега спецов, чтобы написать продаваемый коробочный продукт?
Одно другому не мешает. Ты же сам писал что не везде требуется супер-быстродействие.
V>Зря ты перешел на личности, кста. По опыту разбора с тобой технических моментов за последние года 4 я бы оценил твоё владение платформой .Net как очень посредственное и очень поверхностное. Ничего более-менее серьезного, чем то, что можно сделать, пользуя лишь готовые библиотеки и инструменты, тебе поручать нельзя. Т.е. ты типичный пользователь технологий, а не их разработчик.
Ну верь в это, может легче станет.
V>>>Даже SQL-сервак и IIS. ))) G>>SQL Server в таком виде как мы его знаем был создан в 2000 году, дальше были только доработки. Но вот что странно, новые фичи SQL часто реализуются через .NETтипы.
V>Новые фичи самого сервака там реализуются в нейтиве, ес-но. Ты, наверно, хотел сказать, про поддержку хранимок на дотнете? Дык, Оракл это давно делает. Еще один дык от тебя и таких как ты говорит, что хранимки — это зло. Я уже запутался. Не поможешь распутать?
hierarchyid как ни странно — .NET тип, Geometry и Geography тоже реализованы через .NET обертки. Но это все фигня, ибо главное в быстродействии SQL Server — чтение с диска.
G>>Ибо быстродействие зависит от скорости работы с диском, а не от того нативный там код или нет. V>Та нифига. В "разогретой" базе индексы и статистика в основном сидят в ОП, а значит, скорость обработки их влияет существенно. Разница в скорости работы разогретой базы и не разогретой на порядки.
Ты же понимаешь что в любой серьезной задаче с БД рассчитывать на то, что все данные будут в памяти невозможно. Поэтому и пилят запросы, чтобы количество чтений страниц уменьшить.
V>>>Даже браузер, в котором отображается твоя веб-морда. G>>Рассказать когда появился IE? Думаешь его кто-то будет переписывать?
V>Думаю, что с момента выхода дотнета прошло дохрена времени. Думаю, что существует просто море альтернативных HTML-движков, в т.ч. есть пара и на дотнете. Не взлетели на дотнете, увы. А на нейтиве — взлетели. Даже на этом сайте есть форум, посвящённый одному из них.
Опять твои фантазии, какие движки на .NET? Ссылок хоть пару приведешь? Не исследовательские проекты, а реальные попытки сделать браузер на .NET? Какой смысл в этом когда есть WebKit?
V>Более того, движок IE был фактически полностью переписан с выходом 8-го IE. Расскажи нам, когда же вышел IE 8. ))
"Полностью переписан" это маркетинговый буллшит. От силы 30% перписали, остальное скопипастили. Как можно на несколько лет полностью переписать продукт, в который вложено несколько сотен человеко-лет труда и суммарно сотни лет тестирования, в том числе на реальных пользователях. IE 10 кстати тоже "полностью переписали" судя по маркетинговым заявлениями. Откуда у МС ресурсы раз в 3 года полностью переписывать браузер?
V>>>Ну так сайты и прочая заказуха как у тебя, фиг ли. А ты бы считал не вакансии, а реальные кол-ва инсталляций продуктов. G>>"Реальное количество продуктов" ни о чем, ибо старые всегда будут иметь больше. V>Дотнету уже 12 лет. А продуктов, моложе 12 лет — полно.
Приведи список.
G>>Кроме того сейчас эпоха сервисов, а не продуктов. Сегодня никто не хочет ставить себе лишний софт, если тоже самое есть в браузере.
V>На планшетах и мобилках полно софта. Но тот софт, который не свистелка и перделка — всегда нейтивный. Даже под Андроид. Виберы и его многочисленные клоны, например. Не хочу повторяться, я уже перечислял тебе много всего. Все эти продукты намного моложе дотнета.
Это опять кратина в твоей голове. Самый популярный софт на мобилках — клиенты соцсетей. Все, как ни странно, не на C++ написаны.
Яндекс карты, которыми постоянно пользуюсь, тоже не нативные. Мобильный банк — тоже не нативный.
Многие игры на Unity, который на .NET.
V>>>Для объективности зайди на вакансии той же MS/Intel/Samsung и вообще любых серьезных контор, делающих коробочные продукты и увидишь реальное положение дел в промышленной разработке, а не в заказухе под конкретного клиента некоего единичного экземпляра системы.
G>>Смотрю вакансии MS в России и вижу что ищут девелоперов в свой центр разработки пилить расширения для Axapta, на .NET ессесно.
V>Во-во. Вот для чего дотнет в нише самой MS. Примерно та же ниша, что и у тебя. )) V>А те программисты, которые не на Аксапте, там на что требуется, ы?
SharePoint, CRM, разработка под Windows Azure, все как-то на .NET и JS.
Что там в редмонде — я не в курсе. Но кто-то ведь должен писать драйверы ядра и поддерживать виндовый калькулятор
G>>Хотя все таки рынок у 1С отжать.
V>Не отожмут. Философия Аксапты примерно такая же, как у Паруса. Поэтому — не отожмут никогда. Парусы/Аксапты хороши в крупном секторе с большими инвестициями. А для средних и мелких предприятий они пролетают из-за своей бизнес-модели. А эта модель, в свою очередь, целиком и полностью зависит от технологии платформы. Кароч, для программирования под Парус и Аксапту нужны спецы в программировании, в отличие от спецов сугубо в прикладной области, которые могут "настраивать" 1С. Не зря же огромное программистов 1С — девушки. Но их почти нет в разработке под Парус и Аксапту. Поэтому рынок 1С и не отожмут — это другой совсем рынок.
А ты думаешь МС интересуют внедрения в конторах на 10 человек с одним бухгалтеорм?
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Пока не увижу в новостях, что где-то вышел движок биржи на Linq или банковский оп-день — это всё сказки про белого бычка. G>>А ты видишь в новостях про биржи на ODBC или опердни на ADO?
V>Твой вопрос лишен смысла.
Также как и твой.ODBC и ADO такие же технологии работы с данными, как и EF.
V>Биржи написаны на С/С++. ВСЕ единицы попыток переписать биржи на дотнет закончились отказом от этих попыток.
Я знаю только одну историю про LSE, у тебя еще есть?
V>Наиболее часто вызываемые рантайм-транзакции в оперднях банков сделаны на хранимках.
Не факт что это хорошо.
G>>Работа с данными не самая важная часть приложения, хотя зачастую и самая ресурсоемкая. А Linq вообще не более чем генератор запросов, от которого можно в будущем отказаться, если активная разработка уже не ведется (как сделали в StackOverflow). V>Я ж говорю, что ты нифига не понимаешь. )))
Уровень аргументации на высоте
V>Linq — это не просто генератор запросов, это еще мега-удобный маппер их результатов. В нейтиве такое на сегодня, увы, никак в подобном виде. В нейтиве код маппинга обычно генерируют отдельной тулзиной, типа http://www.qxorm.com/qxorm_en/home.html или http://www.codesynthesis.com/products/odb/, а то и просто ручками, см. boost::serialization. Только в следующем стандарте С++ ожидается, наконец, стандарт на ABI и на метаинформацию... только тогда можно будет делать сравнимые в плане удобства для разработчика мапперы на плюсах, без необходимости подключать и настраивать внешние утилиты для процесса разработки.
При чем тут маппер? Код на C++ уже научился запросы генерить из лямбд? Маппер это малекькая часть, которая при наличии прямых рук пишется за неделю.
G>>Но именно этот генератор запросов позволяет разрабатывать приложения с огромной скоростью, не нагружая DBA написанием селектов. V>Ну вот AVK утверждает, что он не пользуется специфическим Linq-синтаксисом. А используемый им синтаксис был доступен мне еще хрен его знает когда через самописный генератор запросов + маппинг через BLT. Более того, в нейтивных генераторах запросов тоже примерно такой же синтаксис, как показывает AVK.
Ну и пусть утверждает. Но AVK один, а Linq используют десятки или сотни тысяч.
V>Вот ты используешь синтаксис запросов Linq или пишешь в "классическом" стиле?
Конечно пишу Linq когда возможно. Более того, даже оптимизировал некоторые приложения переписывая с хранимок на Linq.
Здравствуйте, gandjustas, Вы писали:
G>С .NET 2.0 SqlConnection поддерживает аснхронное чтение. Ты с 2005 года .NET то видел вообще?
Вот, опять ты подставился. Это "асинхронное" чтение в дотнете сделано по технологии Completion Routines. Это предъявляет определённые требования к потоку, в котором это происходит. В результате, твоя асинхронщина подключается только тогда, когда ты вызываешь асинхронное же АПИ, иначе событие Completion Routines никогда не получит шанса на обработку. Более того, для тех же злополучных блобов, когда ты открывал к нему Stream и читал из него асинхронно, то там асинхронность эмулировалась на стороне дотнета, реально её не было. И именно там я обнаружил ошибку.
И да. Упомянутый мною баг я обнаружил на 2-м дотнете, ес-но. И мне пришлось изучить код дотнетного клиентского драйвера под MS SQL фактически наизусть. А твоя распальцовка попросту смешна, бо ты в глаза не его видел и понятие не имеешь, как он работает.
Далее. В Windows есть минимум 4 способа организации асинхронщины. Так вот, OLEDB давал "правильную" работу с TCP-соединением, даже при обычном, т.е. блокирующем чтении из него. Потому что overlapped API позволяет не только ожидать готовности данных, но может "само" заливать данные в заранее подготовленные буфера.
Ты ведь совсем не в курсе, что в дотнете до сих пор НЕТ нормального асинхронного ввода-вывода, в т.ч. у дров БД. (Вернее — в первую очередь у дров БД, бо самые большие бока с асинхронщиной в дотнете — это сетка). Ты ведь не в курсе, что типичная дотнетная асинхронщина сидит на простом сигналинге готовности, но не использует ср-ва ОС по фоновому заливу или чтению данных, которое происходит прямо по прерываниям устройств прямо из ядра, не заходя в юзверское кольцо?
Это реализация асинхронщины через Completion Ports. Ох мы и погоняли эту реализацию. Потом сравнили со своей, нейтивной. Скажем так, более неэффективной и тормозной реализации, чем по ссылке, свет еще не видел. Я тебе ОЧЕНЬ рекомендую изучить все то, что связано с SocketAsyncEventArgs, пройдись декомпилятором и посмотри, что и как там происходит... потому что на прямо сейчас ты настолько не в теме, насколько может быть не в теме человек, который вообще никогда не видел дотнета. Ужаснись тому коду, который составляет "самый эффективный способ асинхронных сокетов для дотнет". Это ужас и бред одновременно. Начиная с того, что SocketAsyncEventArgs используется вовсе не как привычный EventArgs, а как обычный объект, который надо создавать на стороне клиента библиотеки, а не получать его в событиях готовым, как это принято в XxxEventArgs. Кароч, криво всё, что можно. Всё тормозит, производительность никакая. Хотя, намного лучше, чем обычные дотнетные BeginRead/EndRead и прочий мусор, который чаще всего используется в расширениях async/await дотнета, хотя является самым неэффективным вариантом асинхронщины как таковой.
Кароч, я подробно знаю, в отличие от вас всех, внутренние механизмы библиотек ввода/вывода дотнета. Прекрасно, в отличие от вас, понимаю их ограничения. Прекрасно понимаю, почему ты, как клиент библиотеки, не имеешь возможности настраивать способ использования IO/CP или параметров overlapped в АПИ виндов. Прекрасно понимаю, почему самый эффективный сценарий асинхронности на дотнете (чтение/запись, не выходя из ядра) из дотнета недоступны. Вернее, доступны, через пины буферов, но когда кол-во пинов ужасащее (а для сервака это ВСЕГДА так, бо есть куча буферов на одно соединение, помноженное на кучу соединений), то сам дотнет начинает безбожно тормозить.
G>>>Но даже если база не падает, то твой запрос, даже самый безобидный, может отвалиться по куче причин. Начиная от банального дедлока, заканчивая происками resource governor. V>>Дедлок в базе? ))) G>Да легко
Как? "Длинные транзакции"? )))
V>>Тут кто-то пишет на курсорах пошагово? Не распланировав уровни блокировки данных? А, не! Тут же все крутые Linq-программисты, всё делается одним запросом, откуда дедлок-то? G>Дедлок можно схватить с обычным select в одной сессии и insert в другой, даже на read commited. .NET не при чем.
Это ПРИНЦИПИАЛЬНО НЕВОЗМОЖНО при одном и том же уровне блокирования. Вот просто математически не существует такого способа, хоть ты убейся. А если у тебя разные уровни блокирования к одним и тем же таблицам... гы-гы-гы... я тут даже не знаю, что сказать. Это похлеще выхода за пределы массива в С++.
G>Но я понимаю что ты не в курсе.
Я тоже кое-чего уже понимаю. Хотя, относительно конкретно тебя мне всё понятно уже слишком давно. Ты подставляешься примерно каждый второй свой пост. Ты о гранулярности блокировок слышал хоть что-нить хоть когда-нить? Я уже не о СУБД спрашиваю, а об обычной разработке. Опиши, плиз, простейший алгоритм избегать дедлока при обычной твоей разработке? Вот у тебя пара ресурсов. Процесс 1 лочит ресурс 1 и лезет в ресурс 2, в то же самое время процесс 2 уже залочил ресурс 2 и лезет в ресурс 1. Какой алгоритм недопущений дедлока в этой ситуации?
G>Судя по сообщениям только у тебя и глючило. Учитывая твой уровень знаний СУБД, мне кажется что проблема вовсе не в .NET.
Судя по экранам с ошибкой на этом сайте и не только на этом — на дотнете глючит постоянно.
V>>Ну конечно же! Предикаты и проекции — самые изменяемый части!!! Методом несложной дедукции выводим, что джоины — это самые устойчивые конструкции в разных запросах. А что я предлагал запихивать во вьюхи? Ах, блин! Неужели их же? G>И что ты собираешься выйграть от этого? Сокращение запросов на 3 строки? В чем смысл? Все равно придется генерить предикаты и проекции
Для 5 таблиц, связанных не только суррогатными атомарными ключами, а иногда и составными, это порядка 200-400 символов исходника сэкономленной копипасты. Причем, именно той копипасты, в которой чаще всего ошибаются.
V>>Если для полной инфы по товару надо сделать джоин по примерно 5-ти таблицам (и это еще скромно), то я обязательно сделаю такую вьюху, где будет описан этот джоин. И буду пользовать её в сотнях разных запросов. Примаешь, вьюха для сервака "прозрачна". Т.е. это как текстовый макрос. Не бойся, что вьюха "выбирает" все поля, а тебе нужно в проекции всего пяток, нифига лишнего на самом деле не выбирается. Это просто уже предкомпиллированный приличный кусок SQL-конструкции. G>Я тоже вьюху сделаю, но как она поможет уменьшить количество работы по генерации кучи запросов?
Избежишь копипасты.
V>>В том-то и дело, что не существует в природе "запросов с параметрами". Есть просто запросы и есть хранимки с параметрами. )) G> G>Существуют, эдак с 2000 года. Просто ты о них не знаешь. Более того в .NET используются с самой первой версии.
Нет. Это заморочки драйвера. Просто ты об этом не знаешь.
V>>Существует драйвер базы и временная хранимка уровня соединения на той стороне. Просто драйвер базы даёт такой синтаксис, что как бы просто запрос с как бы параметрами. Поэтому всё, что верно для хранимок, верно и для т.н. "запросов с параметрами". G>Опять бессвязный набор слов... Временная хранимка, драйвер базы, как-бы запрос... чушь полнейшая, уж прости.
Просто ты об этом не знаешь.
V>>Потому что параметры в запросы могут подставляться разным способом. В случае твоего Linq на каждое новое значение ID может генериться тупо другой итоговый текст с другим числовым ID, а не параметром. G>Может, но не генерируется. Провайдеры не идиоты пишут к счастью.
По-факту, кста, идиоты. Потому что зачастую новое числовое значение прямо в тексте эффективнее подставляемого параметра. И ты сам же верно говорил — почему.
V>>И как ты предлагаешь держать это всё под контролем сквозь всё приложение, где у нас будет запрос с параметром, а где тупо другой текст с другим числовым ID? G>Ты никогда не сможешь все держать под контролем.
Вообще-то смогу. Я тебя проверял.
G>Ты всегда отдаешь часть контроля в обен на скорость разработки. В языке C отдали контроль над регистрами и над стеком. В C++ отдали контроль над способом передачи структур и генерацией кода, итд. Linq отдает контроль над гененрацией запроса, а авторы провайдеров берут на себя обязательства генерировать хорошие запросы. И как обычно у автоматического генератора получается лучше, чем у среднего программиста.
Еще раз. КАК мне отделить места в выражении Linq, использующем переменные и генерящем для них параметры от мест, где вместо параметров непосредственно подставляются значения переменных? Это тебе домашнее задание, разработчик ты наш.
Здравствуйте, Ночной Смотрящий, Вы писали:
V>> При хорошей нагрузке можно упереться в превышение максимального кол-ва открытых хендлов ОС. НС>Это не приведет к сообщению о дедлоке.
С чего ты решил, что ошибка была именно из-за дедлока?
И почему, если ошибка в дедлоке, то просто-напросто не переспросить запрос заново?
Здравствуйте, gandjustas, Вы писали:
V>>Я наблюдаю периодические вылеты ADO.Net не только здесь. И рядом указал одну из причин. Еще возможная причина — недетерминированное освобождение ресурсов. При хорошей нагрузке можно упереться в превышение максимального кол-ва открытых хендлов ОС. При детерминированном освобождении такое встречается всяко реже.
G>Снова твои фантазии. В .NET с весрии 2.0 используется пул соедиений. По умолчанию до 100 соединений в пуле. Учитывая 50 рабочих потоков в пуле asp.net, а более одного соединения на поток не нужно, то даже 100 это много.
Как же ты забодал уже своей... назовём это "неосведомлённостью". И ведь спешишь отвечать первый!
Кол-во одновременно открытых соединений/сессий может на порядки превышать кол-во потоков. Потоки обрабатывают запросы, а не соединения.
Я выделил место, в котором ты подставился (опять) так, что мне хочется с тобой не общаться еще несколько лет. Нарисуй себе, что ле, на листике, как соотносятся сетевые TCP-сессии с потоками из пула. ))) А теперь, если асинхронно? ))
G>При применении асинхронных обработчиков HTTP может быть понадобится увеличить до 1000. Лимит на количество дескрипторов — около 16 тысяч в очень древних версиях windows. В нынешних версиях упереться в лимит крайне сложно.
Упереться очень просто. Без специальных настроек виндов под системную память будет выделено ограниченное пространство верхних адресов. Адресов, а не памяти, соображаешь? Т.е. даже при наличии дохрена свободной обычной памяти — ничего уже не поделать.
G>Будь добр укажи текст ошибки при "вылете ADO.NET", или приведи ссылку с описанием проблемы. А то ты сказки рассказываешь. Я 8 лет с .NET работаю (гораздо больше тебя судя по всему) и видел ошибок ADO.NET на порядок меньше, чем ты пишешь.
Считаю года я плохо, поэтому соглашусь, что ты длиннее. )))
Я работаю на дотнет с конца 2000-го года. С тех самых его бет. Особенно плотно я работал до выхода версии 3.5... От неё ожидал кое-какие обещанные ранее вещи, так и не дождался, разозлился и фактически свалил с него. Разозлился, потому что в своём хобби накатал оч большой фрйемворк в расчете на те будущие улучшения, которые нам обещали. Так же по работе нам надо было решить, спасет ли нас 3.5 или мы уходим на нейтив. Не спас. На нейтив перешли относительно безболезненно, кста. Т.е. пропали даром те самые "инвестиции трудозатрат" в дотнет, к которым нас призывали. Без ожидаемых улучшений мой фреймворк не имел смысла. Еще раз я внимательно посмотрел уже на дотнет 4.5 и разачаровался уже окончательно. В нужной мне области никаких подвижек. Это был пипец, товарищи. Это 10 лет выкинутых нафик. Юбилей, однако.
Ну тут плюсы за эти годы подтянулись до адекватного уровня... библиотеки разные, в т.ч. свои собственные... в общем, по мере развития инструментария и библиотек в нейтиве, для меня значимость дотнета с годами всё более падает.
Как только опять увижу сию ошибку этого сайта, то обязательно отпишусь. Правда, я уже сообщил о ней лично IT на форуме, а так же предложил простейший workaround как её избежать. Так что, если он внес предложенное исправление, то вряд ли дождусь именно экрана с ошибкой. Думаю, тебе лучше обратиться лично к IT и спросить, что там показывают логи (и логируются ли такие ситуации?)
Здравствуйте, IT, Вы писали:
IT>Испорченная память в нативном приложении — это проблема того же порядка.
По моему опыту, испорченная память в нейтиве на сегодня возникает только при гонках. Вот можешь себе представить вероятность такого события в нейтиве? ))
Но в дотнете по причине гонок наблюдал багов всяко больше, от дотнетных же разработчиков. У них же порог вхождения как бэ другой, что способствует. По кол-ву виденных приложений на дотнете я бы никогда не сказал, что в дотнетных программах меньше багов. Наоборот! Дотнет даёт преимущество только ОЧЕНЬ хорошему разработчику. ))) Но повальный уход в дотнет самой неграмотной части разработчиков (се ля ви!) нивелирует любые преимущества дотнета в плане статистики багов.
Я понимаю, что в своём лице ты пытаешься представлять весь дотнет. Но это не так. Ты достаточно опытен, у тебя был нейтивный опыт, ты прекрасно понимаешь ПОЧЕМУ местами именно так, а не иначе. ТЫ понимаешь мотивы, поэтому понимаешь решения и представляешь как всё работает. В реальной же дотнетной реальности всё оч печально. Половину дотнетчиков к многопоточности даже не подпускают. Лок-фри — ругательство. Чтобы хоть как-то привлечь эти массы к прекрасному, им дают async/await. Но и там, судя по местным форумам, кто не понимал многопоточность, тот продолжает пороть бока.
Здравствуйте, IT, Вы писали:
V>>А для чего в банках используется дотнет прямо на сейчас — все хорошо знают: клиентское ПО (рабочие места), отчетность, неспешная аналитика, пересчет итогов, бухгалтерия и т.д. Кароч, примерно так же, как в складских программах.
IT>Чья бы корова мукала. Запихнуть процессинг целой биржы в сохранённые процедуры базы данных — это офигительно спешное и главное супер расширяемое решение.
С чего ты решил, что биржа на хранимках? Что она вообще на БД? Я говорил о банковских наиболее популярных транзакциях в опердне, что они повсеместно на хранимках на сегодня.
Для бирж есть С/С++. Есть еще внутренние DSL, которые порождают код на С, но это ноу-хау каждой биржи.
Здравствуйте, gandjustas, Вы писали:
V>>Сколько складских программ написал уже? Сильно отличались? А вообще хоть что-то похожее было? ))) G>Учетная часть везде одинаковая (двойная запись)
Вот и нет. Это только для финансовых проводок так. А для складского учета существует несколько независимых подходов: карточный, партионный, регистровый, усреднённый, с учётом разносортицы и без этого учёта. Иногда по разным группам товаров бывает удобнее вести разный по принципу складской учёт. Т.е. в одной и той же складской программе может быть реализовано несколько алгоритмов.
G>+темпоральная часть, которая историю изменнеий хранит. Это как-бы и самая проблемная часть.
Это самая проблемная часть, когда создание исторических данных хочется автоматизировать, как в 1С — нажатием на чек-бокс. )))
А так-то какие проблемы? Карточный и партионный учёт — это разновидность "исторического" учета.
G>А сверху уже операции относительно несложно делаются. G>А в целом проще готовую платформу взять, типа 1с.
А вот и нет. Это только если встроенные ср-ва и уже имеющиеся "конфигурации" покрывают приличную часть функционала. А если нет, то с 0-ля писать на 1С — легче застрелиться.
G>>>Но для большинства программистов разница SQL или NoSQL как раз в том как с базой работать. NoSQL предлагает самый прямолинейный подход — сериализация объектов целиком, даже думать не надо, просто вызвал Save и все. Проблемы начинаются когда данные оказываются сильно связанными, присутствуют циклы в связях. Тогда NoSQL предлагает такой же прямолинейный подход — тяни все объекты и делай join руками или делай индекс и напрямую к индексу обращайся. SQL все это делает внутри, далеко не очевидным образом, что и вызывает проблемы у программистов.
V>>))) V>>Давно хотел спросить, сколько тебе лет... Можно не отвечать, это я так... ))) G>Мне 29. Но я и без этого вижу, что ответить тебе нечего.
Я думал меньше, если честно.
Мне есть что ответить. Ты часто не понимаешь МОТИВЫ тех или иных технических решений. Не понимаешь, почему именно так, а не иначе. При общении с более старшими разработчиками из местного дотнетного лагеря я таких боков не вижу — они обычно прекрасно понимают, что именно я спрашиваю или за какое место пытаюсь их поймать, когда опускаюсь до провокаций. )))
Тут когда-то был задан не очень хороший тон для общения. Это было из-за великой "битвы технологий" в те далёкие года, когда тебе было всего 17. Зря ты подхватил этот тон сейчас, объективных причин для этого на сегодня просто нет. Всё и так всем понятно. Практически всё, что мы пишем сегодня друг другу, IT, AVK, VlaD2 — мы это всё уже писали друг другу не один десяток раз еще до 2007-го, когда тебе исполнился годик на дотнете. ))) Сейчас так... фигней маемся... как бывшие спортсмены выходим иногда размяться. ))) С некоторой ленцой и заведомым пониманием, что именно ответит оппонент. ))) А ты слишком серьезно относишься к процессу, но несерьезно к фактическому материалу. AVK после залётов (у кого не бывает) хотя бы делал паузу. Ты — нет. )) Я тоже после "залётов" предпочитаю освежить/подкрепиться, кста. Что и тебе советую. Помнишь обсуждение байткода дотнетной VM, верификации, косвенности и признака управляемого и неуправляемого кода на дотнете? Тебе тогда стоило сделать паузу и подкрепиться, а не вырабатывать привычку переть на пролом даже после серии жесточайших залётов. А теперь мне трудно что-либо обсуждать с тобой всерьез. А смысл? ))
Здравствуйте, vdimas, Вы писали:
V>Упереться очень просто. Без специальных настроек виндов под системную память будет выделено ограниченное пространство верхних адресов. Адресов, а не памяти, соображаешь? Т.е. даже при наличии дохрена свободной обычной памяти — ничего уже не поделать.
Только ты забыл одну интересную вещь — это все критично для 32 бит, а 32битные серверные винды уже много лет не выпускаются. Ах да, я забыл, чуть менее чем все С++ приложения портировать на 64 бита — изрядный геморой.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>С .NET 2.0 SqlConnection поддерживает аснхронное чтение. Ты с 2005 года .NET то видел вообще?
V>Вот, опять ты подставился. Это "асинхронное" чтение в дотнете сделано по технологии Completion Routines.
Это асинхронное чтение сделано на базе нативного SNI. Так что все баги и сложность парсера — его следствие. Веб-стек, например, не опирается на сложные и старые API, поэтому там прекрасно работает асинхронность.
V>Это предъявляет определённые требования к потоку, в котором это происходит. В результате, твоя асинхронщина подключается только тогда, когда ты вызываешь асинхронное же АПИ, иначе событие Completion Routines никогда не получит шанса на обработку.
Логично, а ты что хотел? Если ты используегшь синхронное API, то ты и так занимаешь поток, зачем нужно занимать еще один поток на Completion или любые другие пляски исполнять, если в итоге получатель данных работает синхронно?
V>Более того, для тех же злополучных блобов, когда ты открывал к нему Stream и читал из него асинхронно, то там асинхронность эмулировалась на стороне дотнета, реально её не было.
Если у тебя не установлен CommandBehavior.SequentialAccess, то парсер TDS читает строку, а тебе отдает тупо MemoryStream.
Если у тебя установлен CommandBehavior.SequentialAccess, то тебе отдается SqlSequentialStream, который таки асинхронно читает поток. Глянь в ILSpy — он ожидает сигнала получения пакета и копирует байты в выходной буфер.
V>И именно там я обнаружил ошибку.
Какую ошибку? В каком методе? Ничего что GetStream появился в .NET 4.5, а ты рассказываешь про какие-то дремучие времена?
По моему эти ошибки только в твоем воображении существуют.
V>И да. Упомянутый мною баг я обнаружил на 2-м дотнете, ес-но. И мне пришлось изучить код дотнетного клиентского драйвера под MS SQL фактически наизусть. А твоя распальцовка попросту смешна, бо ты в глаза не его видел и понятие не имеешь, как он работает.
Ну ты окончательно заврался, GetStream появился только в .NET 4.5.
До .NET 4.5 не было API для асинхронного чтения ридера.
V>Далее. В Windows есть минимум 4 способа организации асинхронщины. Так вот, OLEDB давал "правильную" работу с TCP-соединением, даже при обычном, т.е. блокирующем чтении из него. Потому что overlapped API позволяет не только ожидать готовности данных, но может "само" заливать данные в заранее подготовленные буфера.
Ага, верю, чувак, верю. Жги дальше.
V>Ты ведь совсем не в курсе, что в дотнете до сих пор НЕТ нормального асинхронного ввода-вывода, в т.ч. у дров БД. (Вернее — в первую очередь у дров БД, бо самые большие бока с асинхронщиной в дотнете — это сетка). Ты ведь не в курсе, что типичная дотнетная асинхронщина сидит на простом сигналинге готовности, но не использует ср-ва ОС по фоновому заливу или чтению данных, которое происходит прямо по прерываниям устройств прямо из ядра, не заходя в юзверское кольцо?
Глянул в ILSpy говорит что в .NET используется WSASend\WSARecv функции с Overlapped.
Ты знаешь более православный способ, который "использует ср-ва ОС по фоновому заливу или чтению данных, которое происходит прямо по прерываниям устройств прямо из ядра, не заходя в юзверское кольцо"?
V>Только в дотнете 3.5 появился первый более-менее настоящий асинхронный сокет, а не та порнография, что была до этого. V>Курить тут: V>http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs(v=vs.90).aspx
V>Это реализация асинхронщины через Completion Ports. Ох мы и погоняли эту реализацию. Потом сравнили со своей, нейтивной. Скажем так, более неэффективной и тормозной реализации, чем по ссылке, свет еще не видел.
Хватит писать слова, просто покажи пример как надо. И замеры покажи.
Я вообще не верю что ты чтототам смотрел, не верю абсолютно ни одному твоему слову.
V>Кароч, я подробно знаю, в отличие от вас всех, внутренние механизмы библиотек ввода/вывода дотнета. Прекрасно, в отличие от вас, понимаю их ограничения. Прекрасно понимаю, почему ты, как клиент библиотеки, не имеешь возможности настраивать способ использования IO/CP или параметров overlapped в АПИ виндов. Прекрасно понимаю, почему самый эффективный сценарий асинхронности на дотнете (чтение/запись, не выходя из ядра) из дотнета недоступны. Вернее, доступны, через пины буферов, но когда кол-во пинов ужасащее (а для сервака это ВСЕГДА так, бо есть куча буферов на одно соединение, помноженное на кучу соединений), то сам дотнет начинает безбожно тормозить.
Ну приведи замеры, примеры кода итп, на слово тебе верить чтоли?
G>>>>Но даже если база не падает, то твой запрос, даже самый безобидный, может отвалиться по куче причин. Начиная от банального дедлока, заканчивая происками resource governor. V>>>Дедлок в базе? ))) G>>Да легко
V>Как? "Длинные транзакции"? )))
Нет. В одной сессии один селект, а в другой один update. Уровень изоляции read commited (без snapshot).
V>>>Тут кто-то пишет на курсорах пошагово? Не распланировав уровни блокировки данных? А, не! Тут же все крутые Linq-программисты, всё делается одним запросом, откуда дедлок-то? G>>Дедлок можно схватить с обычным select в одной сессии и insert в другой, даже на read commited. .NET не при чем.
V>Это ПРИНЦИПИАЛЬНО НЕВОЗМОЖНО при одном и том же уровне блокирования. Вот просто математически не существует такого способа, хоть ты убейся. А если у тебя разные уровни блокирования к одним и тем же таблицам... гы-гы-гы... я тут даже не знаю, что сказать. Это похлеще выхода за пределы массива в С++.
Действительно не знаешь, а на практике кейс очень частый.
Селект использует индекс по полю, и индекс оказывается не покрывающий.
Поэтому select делает сначала index seek, вешая S блокировку на ключ в индексе, а потом Key Lookup, блокируя ключ в странице данных.
А insert сначала пишет в кластерный индекс, вешая X блокировку на страницу, а потом пишет индекс, также пытаясь навесить X блокировку.
Порядок блокировок оказывается разный, возникает deadlock. В нагруженных системах, где нет возможости создать покрывающие индексы на все случаи, такое может случаться довольно часто.
Но я так понимаю ты к таким нагруженным даже близко не подходил, как и не делал большинство из того, что ты тут пишешь. У тебя это все теория, у тебя все "математически"
G>>Но я понимаю что ты не в курсе. V>Я тоже кое-чего уже понимаю. Хотя, относительно конкретно тебя мне всё понятно уже слишком давно. Ты подставляешься примерно каждый второй свой пост.
Кто бы говорил
V>Ты о гранулярности блокировок слышал хоть что-нить хоть когда-нить?
А-то сылшал, а ты, похоже, нет.
V>Я уже не о СУБД спрашиваю, а об обычной разработке. Опиши, плиз, простейший алгоритм избегать дедлока при обычной твоей разработке? Вот у тебя пара ресурсов. Процесс 1 лочит ресурс 1 и лезет в ресурс 2, в то же самое время процесс 2 уже залочил ресурс 2 и лезет в ресурс 1. Какой алгоритм недопущений дедлока в этой ситуации?
В отличие от тебя я не пишу такой код, который лочит ресурсы в случайном порядке. Бросил это дело еще на первой работе, открыл для себя lock-free алгоритмы. Они, конечно, медленнее в отдельности, но в совокупности в разы лучше локов работают.
G>>Судя по сообщениям только у тебя и глючило. Учитывая твой уровень знаний СУБД, мне кажется что проблема вовсе не в .NET. V>Судя по экранам с ошибкой на этом сайте и не только на этом — на дотнете глючит постоянно.
Ну покажи хоть один экран с ошибкой .NET. Почему эта ошибка только у тебя, а у тысяч других пользователей RSDN её нет?
V>>>Ну конечно же! Предикаты и проекции — самые изменяемый части!!! Методом несложной дедукции выводим, что джоины — это самые устойчивые конструкции в разных запросах. А что я предлагал запихивать во вьюхи? Ах, блин! Неужели их же? G>>И что ты собираешься выйграть от этого? Сокращение запросов на 3 строки? В чем смысл? Все равно придется генерить предикаты и проекции
V>Для 5 таблиц, связанных не только суррогатными атомарными ключами, а иногда и составными, это порядка 200-400 символов исходника сэкономленной копипасты. Причем, именно той копипасты, в которой чаще всего ошибаются.
Разговор начался с того, что у нас Linq позволяет не делать копипасту и позволяет делать много чего еще. Но даже эти 200 символов это менее 20% от среднего объема запроса будут, который все равно никак функциям или вьюхами не разрулишь.
V>>>Если для полной инфы по товару надо сделать джоин по примерно 5-ти таблицам (и это еще скромно), то я обязательно сделаю такую вьюху, где будет описан этот джоин. И буду пользовать её в сотнях разных запросов. Примаешь, вьюха для сервака "прозрачна". Т.е. это как текстовый макрос. Не бойся, что вьюха "выбирает" все поля, а тебе нужно в проекции всего пяток, нифига лишнего на самом деле не выбирается. Это просто уже предкомпиллированный приличный кусок SQL-конструкции. G>>Я тоже вьюху сделаю, но как она поможет уменьшить количество работы по генерации кучи запросов? V>Избежишь копипасты.
И? как это поможет около 15 различных запросов сгенерировать? С Linq таких проблем вообще не будет, а вьюха позволяет избавится от 200 символов копипасты, которые вообще не станут проблемой, пока схема не поменяется.
V>>>В том-то и дело, что не существует в природе "запросов с параметрами". Есть просто запросы и есть хранимки с параметрами. )) G>> G>>Существуют, эдак с 2000 года. Просто ты о них не знаешь. Более того в .NET используются с самой первой версии. V>Нет. Это заморочки драйвера. Просто ты об этом не знаешь.
Про sp_executesql слышал? А про автопараметризацию?
Но я уже понял что у тебя все только "математически"
V>>>Существует драйвер базы и временная хранимка уровня соединения на той стороне. Просто драйвер базы даёт такой синтаксис, что как бы просто запрос с как бы параметрами. Поэтому всё, что верно для хранимок, верно и для т.н. "запросов с параметрами". G>>Опять бессвязный набор слов... Временная хранимка, драйвер базы, как-бы запрос... чушь полнейшая, уж прости. V>Просто ты об этом не знаешь.
Ну да, об этом знаешь только ты. Даже создатели SQL Server не знают об этом.
V>>>Потому что параметры в запросы могут подставляться разным способом. В случае твоего Linq на каждое новое значение ID может генериться тупо другой итоговый текст с другим числовым ID, а не параметром. G>>Может, но не генерируется. Провайдеры не идиоты пишут к счастью. V>По-факту, кста, идиоты. Потому что зачастую новое числовое значение прямо в тексте эффективнее подставляемого параметра. И ты сам же верно говорил — почему.
Прости, но если сравнить тебя и среднего писателя Linq-провайдера, то звание идиота он не получит.
Под каждый новый параметр SQL начнет компилировать запрос, что будет долго. Запрос с параметром может быть хуже только в случае нестабильного плана, но это проблема плана, а не параметра.
V>>>И как ты предлагаешь держать это всё под контролем сквозь всё приложение, где у нас будет запрос с параметром, а где тупо другой текст с другим числовым ID? G>>Ты никогда не сможешь все держать под контролем. V>Вообще-то смогу. Я тебя проверял.
Да у тебя парсер TDS падает, что ты держать под контролем можешь вообще?
Сказки какие-то рассказываешь только.
G>>Ты всегда отдаешь часть контроля в обен на скорость разработки. В языке C отдали контроль над регистрами и над стеком. В C++ отдали контроль над способом передачи структур и генерацией кода, итд. Linq отдает контроль над гененрацией запроса, а авторы провайдеров берут на себя обязательства генерировать хорошие запросы. И как обычно у автоматического генератора получается лучше, чем у среднего программиста.
V>Еще раз. КАК мне отделить места в выражении Linq, использующем переменные и генерящем для них параметры от мест, где вместо параметров непосредственно подставляются значения переменных? Это тебе домашнее задание, разработчик ты наш.
В большинстве случаев константа подставляется в текст запроса, а переменная — нет. Но детали могут от провайдера зависеть. Например хорошим тоном считается подстановка NULL в запрос, ибо без этого можно получить хреновый план. Короче проще проверить, а не гадать или "математически доказывать".
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Я наблюдаю периодические вылеты ADO.Net не только здесь. И рядом указал одну из причин. Еще возможная причина — недетерминированное освобождение ресурсов. При хорошей нагрузке можно упереться в превышение максимального кол-ва открытых хендлов ОС. При детерминированном освобождении такое встречается всяко реже.
G>>Снова твои фантазии. В .NET с весрии 2.0 используется пул соедиений. По умолчанию до 100 соединений в пуле. Учитывая 50 рабочих потоков в пуле asp.net, а более одного соединения на поток не нужно, то даже 100 это много.
V>Как же ты забодал уже своей... назовём это "неосведомлённостью". И ведь спешишь отвечать первый! V>Кол-во одновременно открытых соединений/сессий может на порядки превышать кол-во потоков. Потоки обрабатывают запросы, а не соединения.
Ты похоже вообще не понимаешь...
Один рабочий поток в один момент времени обрабатывает один запрос, для одного запроса достаточно одного соединения. Зачем иметь более одного соединения на поток?
100 выбрано как раз из-за сценария asp.net, с учетом того что хреново написанный код может несколько соединений на один запрос использовать.
V>Я выделил место, в котором ты подставился (опять) так, что мне хочется с тобой не общаться еще несколько лет. Нарисуй себе, что ле, на листике, как соотносятся сетевые TCP-сессии с потоками из пула. ))) А теперь, если асинхронно? ))
Как раз об асинхронном я написал ниже, ты читаешь перед тем, как отвечать?
G>>При применении асинхронных обработчиков HTTP может быть понадобится увеличить до 1000. Лимит на количество дескрипторов — около 16 тысяч в очень древних версиях windows. В нынешних версиях упереться в лимит крайне сложно.
V>Упереться очень просто. Без специальных настроек виндов под системную память будет выделено ограниченное пространство верхних адресов. Адресов, а не памяти, соображаешь? Т.е. даже при наличии дохрена свободной обычной памяти — ничего уже не поделать.
А при чем тут адреса, если речь про дескрипторы? Для них не обязаны никакие адреса выделяться.
Ну даже если предположить что чтототам выделяется, то все равно в пуле соединений по умолчанию не более 100 соединений, я видел единицы проектов где этого не хватало. Упереться в максимальное количество хендлов при этом нельзя.
До этого момента ты и не знал, что есть пул соединений, то есть в живую ты не мог этой картины наблюдать. Получается что это снова твои фантазии и не более того, все вылеты ado.net просто плод твоего воображения.
G>>Будь добр укажи текст ошибки при "вылете ADO.NET", или приведи ссылку с описанием проблемы. А то ты сказки рассказываешь. Я 8 лет с .NET работаю (гораздо больше тебя судя по всему) и видел ошибок ADO.NET на порядок меньше, чем ты пишешь. V>Считаю года я плохо, поэтому соглашусь, что ты длиннее. )))
Все таки укажи текст ошибки.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Сколько складских программ написал уже? Сильно отличались? А вообще хоть что-то похожее было? ))) G>>Учетная часть везде одинаковая (двойная запись)
V>Вот и нет. Это только для финансовых проводок так. А для складского учета существует несколько независимых подходов: карточный, партионный, регистровый, усреднённый, с учётом разносортицы и без этого учёта. Иногда по разным группам товаров бывает удобнее вести разный по принципу складской учёт. Т.е. в одной и той же складской программе может быть реализовано несколько алгоритмов.
Да-да, я всю эту херню слышал от "эксперта", а потом запилил проводки с дополнительными аналитическими признаками. А сверху на них уже нужный учет накрутил. Основные проблема были — узнать сколько на складе товара определенного вида, а также узнать оборот за период (сколько пришло, сколько ушло). Эти операции делались медленно, как раз потому что "эксперт" в базе понарожал лишних сущностей.
G>>+темпоральная часть, которая историю изменнеий хранит. Это как-бы и самая проблемная часть. V>Это самая проблемная часть, когда создание исторических данных хочется автоматизировать, как в 1С — нажатием на чек-бокс. ))) V>А так-то какие проблемы? Карточный и партионный учёт — это разновидность "исторического" учета.
Конкретно в этой части у меня проблем не было.
G>>А сверху уже операции относительно несложно делаются. G>>А в целом проще готовую платформу взять, типа 1с.
V>А вот и нет. Это только если встроенные ср-ва и уже имеющиеся "конфигурации" покрывают приличную часть функционала. А если нет, то с 0-ля писать на 1С — легче застрелиться.
Честно не в курсе насколько сложно писать конфигурацию с нуля, но конфигурации для склада в 1С есть, дальше можно под себя пилить.
G>>>>Но для большинства программистов разница SQL или NoSQL как раз в том как с базой работать. NoSQL предлагает самый прямолинейный подход — сериализация объектов целиком, даже думать не надо, просто вызвал Save и все. Проблемы начинаются когда данные оказываются сильно связанными, присутствуют циклы в связях. Тогда NoSQL предлагает такой же прямолинейный подход — тяни все объекты и делай join руками или делай индекс и напрямую к индексу обращайся. SQL все это делает внутри, далеко не очевидным образом, что и вызывает проблемы у программистов.
V>>>))) V>>>Давно хотел спросить, сколько тебе лет... Можно не отвечать, это я так... ))) G>>Мне 29. Но я и без этого вижу, что ответить тебе нечего.
V>Я думал меньше, если честно.
А я думал, что ты умнее, если честно. А ты все доказываешь что у тебя больная фантазия и много слов нахватался. Реальных знаний и опыта у тебя очень мало.
V>Мне есть что ответить. Ты часто не понимаешь МОТИВЫ тех или иных технических решений. Не понимаешь, почему именно так, а не иначе. При общении с более старшими разработчиками из местного дотнетного лагеря я таких боков не вижу — они обычно прекрасно понимают, что именно я спрашиваю или за какое место пытаюсь их поймать, когда опускаюсь до провокаций. )))
Твои провокации смешны, ты выпячиваешь свое незнание и сыпишь кучей терминов, не имеющих отношения к делу. Доказательств твоих слов я пока не видел. Ни разу вообще.
Мотивы я понимаю получше тебя, потому что понимаю ЭКОНОМИЧЕСКИЕ мотивы ТЕХНИЧЕСКИХ решений. В отличие от тебя у меня экономических мотивов гораздо больше и я гораздо лучше знаю как они влияют.
Здравствуйте, gandjustas, Вы писали:
V>>>>Пока не увижу в новостях, что где-то вышел движок биржи на Linq или банковский оп-день — это всё сказки про белого бычка. G>>>А ты видишь в новостях про биржи на ODBC или опердни на ADO?
V>>Твой вопрос лишен смысла. G>Также как и твой.ODBC и ADO такие же технологии работы с данными, как и EF.
V>>Биржи написаны на С/С++. ВСЕ единицы попыток переписать биржи на дотнет закончились отказом от этих попыток. G>Я знаю только одну историю про LSE, у тебя еще есть?
Э, нет. В случае LSE биржа реально перешла на дотнет, а потом вернулась. А так-то многие ведущие биржи активно внедряли дотнет. Просто, в случае именно "движка" биржи, до релиза дело не дошло.
V>>Наиболее часто вызываемые рантайм-транзакции в оперднях банков сделаны на хранимках. G>Не факт что это хорошо.
Зато безопасно. Потому что, если процессить внешним серваком — то это можно быстро, конечно, но встаёт вопрос об журналинге транзакций в БД — в случае непредвиденности можно потерять транзакции за последние миллисекунды. А это ну ваще никак нельзя. А если делать на внешнем серваке приложений т.н. "длинные транзакции", то резко падает производительность. Поэтому, самые частовызываемые вещи делают в БД. В принципе, возможность писать хранимки на дотнете может помочь.
V>>Linq — это не просто генератор запросов, это еще мега-удобный маппер их результатов. В нейтиве такое на сегодня, увы, никак в подобном виде. В нейтиве код маппинга обычно генерируют отдельной тулзиной, типа http://www.qxorm.com/qxorm_en/home.html или http://www.codesynthesis.com/products/odb/, а то и просто ручками, см. boost::serialization. Только в следующем стандарте С++ ожидается, наконец, стандарт на ABI и на метаинформацию... только тогда можно будет делать сравнимые в плане удобства для разработчика мапперы на плюсах, без необходимости подключать и настраивать внешние утилиты для процесса разработки.
G>При чем тут маппер?
Потому что для нейтива это самая болезненная часть.
G>Код на C++ уже научился запросы генерить из лямбд?
Да. В С++, в отличие от, можно переопределить вообще все операторы языка, даже операторы присваивания. Это позволяет в том же синтаксисе организовать некий query builder.
G>Маппер это малекькая часть, которая при наличии прямых рук пишется за неделю.
Я напишу тебе маппер на десяток объектов с помощью boost::serialization за единицы минут. Дальше что? По мере разработки этих объектов, добавления/удаления — ничего автоматом не происходит. Нужно ручками синхронизировать. Кароч, геммор не приведи господь, если этих объектов сотни. Поэтому с внешними тулзами удобнее, они дают хоть какую-то автоматизацию. Тебе не с чем сравнить, ты не понимаешь, насколько это круто — интегрированный маппер. )))
G>>>Но именно этот генератор запросов позволяет разрабатывать приложения с огромной скоростью, не нагружая DBA написанием селектов. V>>Ну вот AVK утверждает, что он не пользуется специфическим Linq-синтаксисом. А используемый им синтаксис был доступен мне еще хрен его знает когда через самописный генератор запросов + маппинг через BLT. Более того, в нейтивных генераторах запросов тоже примерно такой же синтаксис, как показывает AVK. G>Ну и пусть утверждает. Но AVK один, а Linq используют десятки или сотни тысяч.
V>>Вот ты используешь синтаксис запросов Linq или пишешь в "классическом" стиле? G>Конечно пишу Linq когда возможно. Более того, даже оптимизировал некоторые приложения переписывая с хранимок на Linq.
Ты не понял вопроса, походу. Библиотеку Linq можно использовать как обычную библиотеку, без использования в коде "синтаксиса запросов". Я спрашиваю — ты используешь этот новый синтаксис запросов или используешь Linq в виде вызовов обычных методов (методов-расширений в т.ч.)?
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Только ты забыл одну интересную вещь — это все критично для 32 бит, а 32битные серверные винды уже много лет не выпускаются. Ах да, я забыл, чуть менее чем все С++ приложения портировать на 64 бита — изрядный геморой.
Уже лет 10 пишу код, который компилируется и в 32 и в 64 бита. В С++ есть такая удобнейшая штука, как typedef, которая разруливает подобные моменты. В Линухах тоже уже лет 10 все программы компилируются на любой target.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>>>Пока не увижу в новостях, что где-то вышел движок биржи на Linq или банковский оп-день — это всё сказки про белого бычка. G>>>>А ты видишь в новостях про биржи на ODBC или опердни на ADO?
V>>>Твой вопрос лишен смысла. G>>Также как и твой.ODBC и ADO такие же технологии работы с данными, как и EF.
V>>>Биржи написаны на С/С++. ВСЕ единицы попыток переписать биржи на дотнет закончились отказом от этих попыток. G>>Я знаю только одну историю про LSE, у тебя еще есть? V>Э, нет. В случае LSE биржа реально перешла на дотнет, а потом вернулась. А так-то многие ведущие биржи активно внедряли дотнет. Просто, в случае именно "движка" биржи, до релиза дело не дошло.
Где доказательства твоим словам?
Кстати только что появилась новость, что московская биржка упала и судя по лентам падает регулярно. А она как раз на C++. Вот тебе нэйтив и надежность.
V>>>Наиболее часто вызываемые рантайм-транзакции в оперднях банков сделаны на хранимках. G>>Не факт что это хорошо.
V>Зато безопасно. Потому что, если процессить внешним серваком — то это можно быстро, конечно, но встаёт вопрос об журналинге транзакций в БД — в случае непредвиденности можно потерять транзакции за последние миллисекунды. А это ну ваще никак нельзя. А если делать на внешнем серваке приложений т.н. "длинные транзакции", то резко падает производительность. Поэтому, самые частовызываемые вещи делают в БД. В принципе, возможность писать хранимки на дотнете может помочь.
А при чем тут хранимки? Транзакции и батчи отменили? Чем хранимка лучше запроса, отправленного с клиента? Все равно одна транзакция это один insert, больше не нужно. Если кто-то написал, то это не значит, что это правильно.
V>>>Linq — это не просто генератор запросов, это еще мега-удобный маппер их результатов. В нейтиве такое на сегодня, увы, никак в подобном виде. В нейтиве код маппинга обычно генерируют отдельной тулзиной, типа http://www.qxorm.com/qxorm_en/home.html или http://www.codesynthesis.com/products/odb/, а то и просто ручками, см. boost::serialization. Только в следующем стандарте С++ ожидается, наконец, стандарт на ABI и на метаинформацию... только тогда можно будет делать сравнимые в плане удобства для разработчика мапперы на плюсах, без необходимости подключать и настраивать внешние утилиты для процесса разработки.
G>>При чем тут маппер?
V>Потому что для нейтива это самая болезненная часть.
G>>Код на C++ уже научился запросы генерить из лямбд?
V>Да. В С++, в отличие от, можно переопределить вообще все операторы языка, даже операторы присваивания. Это позволяет в том же синтаксисе организовать некий query builder.
И оператор лямбды переопределять?
Покажи пример в конце концов чето-то похожего на linq to database.
G>>Маппер это малекькая часть, которая при наличии прямых рук пишется за неделю.
V>Я напишу тебе маппер на десяток объектов с помощью boost::serialization за единицы минут. Дальше что? По мере разработки этих объектов, добавления/удаления — ничего автоматом не происходит. Нужно ручками синхронизировать. Кароч, геммор не приведи господь, если этих объектов сотни. Поэтому с внешними тулзами удобнее, они дают хоть какую-то автоматизацию. Тебе не с чем сравнить, ты не понимаешь, насколько это круто — интегрированный маппер. )))
Еще раз повторю — маппер прямыми руками пишется за неделю. Уровня Dapper. На .NET. На C++ такое не пишется вообще, поэтому в корпоративной разработке и в вебе C++ сосет. Да и для большинства клиентских приложений сосет, по причине по той же причине.
G>>>>Но именно этот генератор запросов позволяет разрабатывать приложения с огромной скоростью, не нагружая DBA написанием селектов. V>>>Ну вот AVK утверждает, что он не пользуется специфическим Linq-синтаксисом. А используемый им синтаксис был доступен мне еще хрен его знает когда через самописный генератор запросов + маппинг через BLT. Более того, в нейтивных генераторах запросов тоже примерно такой же синтаксис, как показывает AVK. G>>Ну и пусть утверждает. Но AVK один, а Linq используют десятки или сотни тысяч.
V>>>Вот ты используешь синтаксис запросов Linq или пишешь в "классическом" стиле? G>>Конечно пишу Linq когда возможно. Более того, даже оптимизировал некоторые приложения переписывая с хранимок на Linq.
V>Ты не понял вопроса, походу. Библиотеку Linq можно использовать как обычную библиотеку, без использования в коде "синтаксиса запросов". Я спрашиваю — ты используешь этот новый синтаксис запросов или используешь Linq в виде вызовов обычных методов (методов-расширений в т.ч.)?
И то и другое, как удобнее.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>Кста. Народ уже экспериментирует на плюсах: V>https://github.com/k06a/boolinq
V>)))
Такие библиотеки с 2008 года плодятся со страшной скоростью. Вот только запросов к базе никто делать не умеет. Все только с массивами и работают.
Здравствуйте, gandjustas, Вы писали:
V>>Как же ты забодал уже своей... назовём это "неосведомлённостью". И ведь спешишь отвечать первый! V>>Кол-во одновременно открытых соединений/сессий может на порядки превышать кол-во потоков. Потоки обрабатывают запросы, а не соединения. G>Ты похоже вообще не понимаешь...
да-да
G>Один рабочий поток в один момент времени обрабатывает один запрос, для одного запроса достаточно одного соединения. Зачем иметь более одного соединения на поток?
Затем, что не факт, что соединение будет закрыто после запроса. Если браузер спрашивает ресурсы с этого же домена, то он может переиспользовать соединение. При нагрузке одновременно живут тысячи TCP-соединений. Твой пул потоков в ASP.Net тоже не фиксированный, может расти. Просто он не может падать ниже 50.
G>100 выбрано как раз из-за сценария asp.net, с учетом того что хреново написанный код может несколько соединений на один запрос использовать.
Нет, не из-за этого. А из-за того, что в хреново написанном коде не всегда явно вызывается Dispose, поэтому конекшен не возвращается в пул. А еще потому, что серверное приложение может что-то делать в фоне, поэтому коннекшен может жить гораздо дольше, чем запрос. А еще потому, что в случае асинхронщины мы на тех же 50 потоках можем одновременно обрабатывать хоть десятки-сотни тыщ соединений.
V>>Я выделил место, в котором ты подставился (опять) так, что мне хочется с тобой не общаться еще несколько лет. Нарисуй себе, что ле, на листике, как соотносятся сетевые TCP-сессии с потоками из пула. ))) А теперь, если асинхронно? )) G>Как раз об асинхронном я написал ниже, ты читаешь перед тем, как отвечать?
G>>>При применении асинхронных обработчиков HTTP может быть понадобится увеличить до 1000.
Ничего не надо. Если асинхронщина написана грамотно, то НЕ ТРЕБУЕТСЯ потоков больше, чем ядер в системе. В наших продуктах именно так. )) Но для дотнетчиков взят запас, потому что в обычном дотнетном коде асинхронный код запросто перемешивается с синхронным.
V>>Упереться очень просто. Без специальных настроек виндов под системную память будет выделено ограниченное пространство верхних адресов. Адресов, а не памяти, соображаешь? Т.е. даже при наличии дохрена свободной обычной памяти — ничего уже не поделать. G>А при чем тут адреса, если речь про дескрипторы? Для них не обязаны никакие адреса выделяться.
Для них выделяется системная память. Системная память сидит в определенном диапазоне адресов. Она мапится в адресное пространство каждого процесса при заходе в вызовы ядра.
G>Ну даже если предположить что чтототам выделяется, то все равно в пуле соединений по умолчанию не более 100 соединений, я видел единицы проектов где этого не хватало. Упереться в максимальное количество хендлов при этом нельзя.
Что-то ты заврался. Ты и не можешь увидеть, что этого не хватает. Просто соединения будут браться не из пула, а создаваться как обычные объекты. А затем лишние будут не возвращаться в пул, а просто удаляться.
G>До этого момента ты и не знал, что есть пул соединений, то есть в живую ты не мог этой картины наблюдать. Получается что это снова твои фантазии и не более того, все вылеты ado.net просто плод твоего воображения.
Какой же ты наивный даже для своего возраста. До "этого момента". Какая прелесть. Пройдись что-ле по дотнетным форумам здесь до 2005-го года. Я активно участвовал.
G>>>Будь добр укажи текст ошибки при "вылете ADO.NET", или приведи ссылку с описанием проблемы. А то ты сказки рассказываешь. Я 8 лет с .NET работаю (гораздо больше тебя судя по всему) и видел ошибок ADO.NET на порядок меньше, чем ты пишешь. V>>Считаю года я плохо, поэтому соглашусь, что ты длиннее. ))) G>Все таки укажи текст ошибки.
Всё-таки не наглей. Давно на игнор напрашиваешься. Твой опыт только на одном дотнете фактически никакой, мне реально все-равно, видел ты что-то или нет. Знач, мало работал. Знач, у вас нагрузка детская. 8 лет — это ни о чем в индустрии. И тем более ни о чем, если речь об одной только технологии. Тебе даже не с чем сравнить.
Здравствуйте, Ночной Смотрящий, Вы писали:
V>>С чего ты решил, что ошибка была именно из-за дедлока? НС>А что, нет?
В случае дедлока соединение сбрасывается по заметному таймауту. Без такого таймаута — это не дедлок. Мгновенно выдаётся скрин с дефолтной растеризацией ошибки.
V>>И почему, если ошибка в дедлоке, то просто-напросто не переспросить запрос заново? НС>Потому что это нафик никому не нужно.
А как же "лицо" команды разработчиков?
Тем более, что это дело одной строчки.
НС>А при чем тут дотнет?
Так не было до переезда на него такого. Я не верю, что в течении пары месяцев после переезда настолько резко возросла нагрузка на сайт. Но эти экраны стали появляться оч оперативно после переезда.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Как же ты забодал уже своей... назовём это "неосведомлённостью". И ведь спешишь отвечать первый! V>>>Кол-во одновременно открытых соединений/сессий может на порядки превышать кол-во потоков. Потоки обрабатывают запросы, а не соединения. G>>Ты похоже вообще не понимаешь...
V>да-да
G>>Один рабочий поток в один момент времени обрабатывает один запрос, для одного запроса достаточно одного соединения. Зачем иметь более одного соединения на поток?
V>Затем, что не факт, что соединение будет закрыто после запроса. Если браузер спрашивает ресурсы с этого же домена, то он может переиспользовать соединение. При нагрузке одновременно живут тысячи TCP-соединений. Твой пул потоков в ASP.Net тоже не фиксированный, может расти. Просто он не может падать ниже 50.
До .NET 4 был лимит по умолчанию в 50 потоков на одно приложение. После .NET 4 используется стандартный thread pool, который дает максимум 25 потоков на ядро. Количество соединений абсолютно нерелевантно этому числу. Соединение воовсе не обязательно должно поток занимать.
G>>100 выбрано как раз из-за сценария asp.net, с учетом того что хреново написанный код может несколько соединений на один запрос использовать.
V>Нет, не из-за этого. А из-за того, что в хреново написанном коде не всегда явно вызывается Dispose, поэтому конекшен не возвращается в пул. А еще потому, что серверное приложение может что-то делать в фоне, поэтому коннекшен может жить гораздо дольше, чем запрос. А еще потому, что в случае асинхронщины мы на тех же 50 потоках можем одновременно обрабатывать хоть десятки-сотни тыщ соединений.
Еще раз — пул был придуман задолго до того как асинхронщина в .NET была мейнстримом, и лимит в 100 очень хорошо отражает реалии asp.net того времени. В десктопном приложении вообще нет смысла иметь более одного активного соединения.
V>>>Я выделил место, в котором ты подставился (опять) так, что мне хочется с тобой не общаться еще несколько лет. Нарисуй себе, что ле, на листике, как соотносятся сетевые TCP-сессии с потоками из пула. ))) А теперь, если асинхронно? )) G>>Как раз об асинхронном я написал ниже, ты читаешь перед тем, как отвечать?
G>>>>При применении асинхронных обработчиков HTTP может быть понадобится увеличить до 1000.
V>Ничего не надо. Если асинхронщина написана грамотно, то НЕ ТРЕБУЕТСЯ потоков больше, чем ядер в системе. В наших продуктах именно так. )) Но для дотнетчиков взят запас, потому что в обычном дотнетном коде асинхронный код запросто перемешивается с синхронным.
Я вообще-то про кол-во соединений в пуле. Но обычно веб-сервер загибается раньше, чем забивает 100 соединений.
V>>>Упереться очень просто. Без специальных настроек виндов под системную память будет выделено ограниченное пространство верхних адресов. Адресов, а не памяти, соображаешь? Т.е. даже при наличии дохрена свободной обычной памяти — ничего уже не поделать. G>>А при чем тут адреса, если речь про дескрипторы? Для них не обязаны никакие адреса выделяться.
V>Для них выделяется системная память. Системная память сидит в определенном диапазоне адресов. Она мапится в адресное пространство каждого процесса при заходе в вызовы ядра.
Это не факт, у тебя есть доказательства твоих слов?
G>>Ну даже если предположить что чтототам выделяется, то все равно в пуле соединений по умолчанию не более 100 соединений, я видел единицы проектов где этого не хватало. Упереться в максимальное количество хендлов при этом нельзя.
V>Что-то ты заврался. Ты и не можешь увидеть, что этого не хватает. Просто соединения будут браться не из пула, а создаваться как обычные объекты. А затем лишние будут не возвращаться в пул, а просто удаляться.
Да конечно. Если соединения в пуле кончатся ты эксепшн получишь. Это ты выдумываешь небылицы уже несколько постов. Ты хоть знаешь как создать соединение с SQL Server без пулинга? Мне кажется что нет.
G>>До этого момента ты и не знал, что есть пул соединений, то есть в живую ты не мог этой картины наблюдать. Получается что это снова твои фантазии и не более того, все вылеты ado.net просто плод твоего воображения. V>Какой же ты наивный даже для своего возраста. До "этого момента". Какая прелесть. Пройдись что-ле по дотнетным форумам здесь до 2005-го года. Я активно участвовал.
Ты и тогда фантазировал во всю?
G>>>>Будь добр укажи текст ошибки при "вылете ADO.NET", или приведи ссылку с описанием проблемы. А то ты сказки рассказываешь. Я 8 лет с .NET работаю (гораздо больше тебя судя по всему) и видел ошибок ADO.NET на порядок меньше, чем ты пишешь. V>>>Считаю года я плохо, поэтому соглашусь, что ты длиннее. ))) G>>Все таки укажи текст ошибки.
V>Всё-таки не наглей. Давно на игнор напрашиваешься. Твой опыт только на одном дотнете фактически никакой, мне реально все-равно, видел ты что-то или нет. Знач, мало работал. Знач, у вас нагрузка детская. 8 лет — это ни о чем в индустрии. И тем более ни о чем, если речь об одной только технологии. Тебе даже не с чем сравнить.
Укажи текст ошибки, а то пока все это только твои фантазии.
Здравствуйте, vdimas, Вы писали:
V>В случае дедлока соединение сбрасывается по заметному таймауту.
Вовсе необязательно. Детектор может в ряде ситуаций обнаруживать дедлок сразу, без таймаута.
V>>>И почему, если ошибка в дедлоке, то просто-напросто не переспросить запрос заново? НС>>Потому что это нафик никому не нужно. V>А как же "лицо" команды разработчиков?
С ним все в порядке.
V>Тем более, что это дело одной строчки.
Дело тут далеко не в одной строчке.
НС>>А при чем тут дотнет? V>Так не было до переезда на него такого.
Это когда у сайта было полтора посетителя в день?
V> Я не верю, что в течении пары месяцев после переезда настолько резко возросла нагрузка на сайт. Но эти экраны стали появляться оч оперативно после переезда.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, vdimas, Вы писали:
V>>В случае дедлока соединение сбрасывается по заметному таймауту.
НС>Вовсе необязательно. Детектор может в ряде ситуаций обнаруживать дедлок сразу, без таймаута.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>Детектор дедлоков срабатывает каждые 500мс.
V>по умолчанию каждые 5 сек
Блин, 5000мс. Но при нахождении дедлока повторно срабатывает через 100мс, если не находит — интервал увеличивается.
Так что не обязательна заметная задержка. Если дедлоки появляются часто, то заметной задержки не будет.
Здравствуйте, gandjustas, Вы писали:
G>>>С .NET 2.0 SqlConnection поддерживает аснхронное чтение. Ты с 2005 года .NET то видел вообще?
V>>Вот, опять ты подставился. Это "асинхронное" чтение в дотнете сделано по технологии Completion Routines. G>Это асинхронное чтение сделано на базе нативного SNI.
Садись, два. SNI — это просто описание протокола. ЛЮБОЙ клиентский драйвер любой базы лишь реализует клиентскую часть этого протокола.
G>Так что все баги и сложность парсера — его следствие.
Баги парсера от убогого кода. Сложность там не большая, скорее — наоборот. Топорно в лоб написано, как студенты 2-го курса пишут лабораторки.
G>Веб-стек, например, не опирается на сложные и старые API, поэтому там прекрасно работает асинхронность.
Слышал звон, да не знаешь где он. На КАКОЙ именно асинхронной технологии работает Веб-стек?
А я тебе скажу — на никакой. Сидит хендлер событий на нейтивном АПИ IIS и вызывает дотнетный диспетчер.
Кароч, ты даже не в курсе, как работает твоя основная технология. Поздравляю, чо!
V>>Это предъявляет определённые требования к потоку, в котором это происходит. В результате, твоя асинхронщина подключается только тогда, когда ты вызываешь асинхронное же АПИ, иначе событие Completion Routines никогда не получит шанса на обработку. G>Логично, а ты что хотел?
А я хотел бы, чтобы completion routines исчезло раз и навсегда. Из всех асинхронных механизмов оно самое убогое и тормозное. К тому же с кучей ограничений. Но ты же не в курсе, видимо, что completion routines может работать в цикле GUI? Т.е. при заходе на SleepEx или WaitForXxxEx выполняются накопленные на тот момент completion routines. Прикинь, какая засада — пока ты сам не вызовешь определенные системные ф-ии, никакого колбека от асинхронщины не происходит. Т.е. вообще ничего не происходит. Именно поэтому так тормозят дотнетные асинхронные сокеты. А весь твой ASP.Net именно на них и написан. Просто в основном используется синхронное чтение и запись ответа, наверняка и у вас тоже. В общем, по характеристикам диспетчеризации нагрузки Asp.Net сосёт не нагибаясь. Слава богу, что основной трафик не на HTML-код, а на картинки и медиа.
G>Если ты используегшь синхронное API, то ты и так занимаешь поток, зачем нужно занимать еще один поток на Completion или любые другие пляски исполнять, если в итоге получатель данных работает синхронно?
Затем, чтобы пока ты выполняешь обработку поступившей порции данных, физическое устройство (вернее, его драйвер) могут заливать в твои буфера следующую порцию данных. А иначе, чтобы распараллелить обработку, на дотнете надо создать еще один поток, который будет заниматься сугубо выгребанием данных. А уже из этого потока передавать данные целевому. Правда, если бы еще дотнетчики lock-free умели хорошо... а то через дотнетную синхронизацию на мониторе убивается любая производительность.
Кароч, для того же TCP, чтобы поддерживать окно максимальным, необходимо оперативно выгребать данные из сокета. Для сравнения, дотнет не в состоянии нагрузить современные сетевые карточки, которые с легкостью нагружает нейтив. Разница в пропускной способности в среднем до 3-х раз. Чем меньшими порциями оперируем, тем больше разница вплоть до более 20 раз.
V>>Более того, для тех же злополучных блобов, когда ты открывал к нему Stream и читал из него асинхронно, то там асинхронность эмулировалась на стороне дотнета, реально её не было. G>Если у тебя не установлен CommandBehavior.SequentialAccess, то парсер TDS читает строку, а тебе отдает тупо MemoryStream. G>Если у тебя установлен CommandBehavior.SequentialAccess, то тебе отдается SqlSequentialStream, который таки асинхронно читает поток. Глянь в ILSpy — он ожидает сигнала получения пакета и копирует байты в выходной буфер.
Если аснхронно — то сам ничего не читает и не ожидает. Кароч, всё ясно, курить completion routines до просветления. Ты получаешь сигнал готовности данных не асинхронно, а только когда входишь в ожидание этого сигнала, т.н. alertable thread state. Получаешь сигнал готовности иногда с бооольшим опозданием, ведь ты заходишь в slertable state очень даже синхронно, причем, ты должен получить сигнал готовности в том же самом потоке, откуда ты начал "асинхронную" операцию. Поэтому, никакого load balancing. Поэтому, задержавшись по неким объективным причинам на обработке текущей порции данных от одной из асинхронных операций, ты тормозишь вообще все асинхронные операции, привязанные к данному потоку.
Сравнимая по убогости технология — только WsaSelect для сокетов. Но в нейтиве мы хоть можем выбирать, как работать из кучи вариантов. А вдотнете имеем нифига не масштабируемый ввод-вывод. Отсюда плачевные результаты по производительности этого ввода/вывода.
G>Ничего что GetStream появился в .NET 4.5, а ты рассказываешь про какие-то дремучие времена?
Ничего, ничего. Ты ж соврал про 8 лет на дотнете, походу.
Есть такой SqlBytes.Stream.
G>По моему эти ошибки только в твоем воображении существуют.
Рассуждая таким макаром, по твоему земля плоская. Ты же её и космоса не видел.
V>>И да. Упомянутый мною баг я обнаружил на 2-м дотнете, ес-но. И мне пришлось изучить код дотнетного клиентского драйвера под MS SQL фактически наизусть. А твоя распальцовка попросту смешна, бо ты в глаза не его видел и понятие не имеешь, как он работает. G>Ну ты окончательно заврался, GetStream появился только в .NET 4.5. G>До .NET 4.5 не было API для асинхронного чтения ридера.
Видишь суслика? А он есть! (С)
V>>Далее. В Windows есть минимум 4 способа организации асинхронщины. Так вот, OLEDB давал "правильную" работу с TCP-соединением, даже при обычном, т.е. блокирующем чтении из него. Потому что overlapped API позволяет не только ожидать готовности данных, но может "само" заливать данные в заранее подготовленные буфера. G>Ага, верю, чувак, верю. Жги дальше.
Порядком утомил своим невежеством и хамством. До встречи через годик-другой.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>>>С .NET 2.0 SqlConnection поддерживает аснхронное чтение. Ты с 2005 года .NET то видел вообще?
V>>>Вот, опять ты подставился. Это "асинхронное" чтение в дотнете сделано по технологии Completion Routines. G>>Это асинхронное чтение сделано на базе нативного SNI.
V>Садись, два. SNI — это просто описание протокола. ЛЮБОЙ клиентский драйвер любой базы лишь реализует клиентскую часть этого протокола.
Да что ты? А ничего что парсер TDS зовет нативные методы?
G>>Веб-стек, например, не опирается на сложные и старые API, поэтому там прекрасно работает асинхронность. V>Слышал звон, да не знаешь где он. На КАКОЙ именно асинхронной технологии работает Веб-стек? V>А я тебе скажу — на никакой. Сидит хендлер событий на нейтивном АПИ IIS и вызывает дотнетный диспетчер. V>Кароч, ты даже не в курсе, как работает твоя основная технология. Поздравляю, чо!
А причем тут IIS? Я про веб-стек .NETа. Он на обычных сокетах сидит, которые юзают обычные WSAфункции
V>>>Это предъявляет определённые требования к потоку, в котором это происходит. В результате, твоя асинхронщина подключается только тогда, когда ты вызываешь асинхронное же АПИ, иначе событие Completion Routines никогда не получит шанса на обработку. G>>Логично, а ты что хотел?
V>А я хотел бы, чтобы completion routines исчезло раз и навсегда. Из всех асинхронных механизмов оно самое убогое и тормозное. К тому же с кучей ограничений.
Тогда вопрос к нативной реализации SNI, которую использует парсер TDS. .NET тут не при чем.
V>Но ты же не в курсе, видимо, что completion routines может работать в цикле GUI?
С чего ты взял что я не в курсе? Снова свой мир в голове?
V>Т.е. при заходе на SleepEx или WaitForXxxEx выполняются накопленные на тот момент completion routines. Прикинь, какая засада — пока ты сам не вызовешь определенные системные ф-ии, никакого колбека от асинхронщины не происходит. Т.е. вообще ничего не происходит. Именно поэтому так тормозят дотнетные асинхронные сокеты.
Он не вызывют Wait — функций. Но даже если вызывают, приведи тесты.
V>А весь твой ASP.Net именно на них и написан.
Смотрю ILSpy код ASP.NET, нету там сокетов, снова воспаленное воображение.
G>>Если ты используегшь синхронное API, то ты и так занимаешь поток, зачем нужно занимать еще один поток на Completion или любые другие пляски исполнять, если в итоге получатель данных работает синхронно? V>Затем, чтобы пока ты выполняешь обработку поступившей порции данных, физическое устройство (вернее, его драйвер) могут заливать в твои буфера следующую порцию данных.
В чем проблема сделать это на .NET ?
V>А иначе, чтобы распараллелить обработку, на дотнете надо создать еще один поток, который будет заниматься сугубо выгребанием данных. А уже из этого потока передавать данные целевому. Правда, если бы еще дотнетчики lock-free умели хорошо... а то через дотнетную синхронизацию на мониторе убивается любая производительность.
Ну покажи как сделать быстро.
V>Кароч, для того же TCP, чтобы поддерживать окно максимальным, необходимо оперативно выгребать данные из сокета. Для сравнения, дотнет не в состоянии нагрузить современные сетевые карточки, которые с легкостью нагружает нейтив. Разница в пропускной способности в среднем до 3-х раз. Чем меньшими порциями оперируем, тем больше разница вплоть до более 20 раз.
Опять у тебя свой мир в голове. .NET может выплевывать данные в сетевой драйвер с той же скоростью, что и нативный код, собственно от нативности тут вообще ничего не зависит, время выполнения коллбека в .NET бесконечно мало по сравнению со временем выполнения send. Для того, чтобы запустить чтение данных параллельно с обработкой не нужно создавать потоки?
V>>>Более того, для тех же злополучных блобов, когда ты открывал к нему Stream и читал из него асинхронно, то там асинхронность эмулировалась на стороне дотнета, реально её не было. G>>Если у тебя не установлен CommandBehavior.SequentialAccess, то парсер TDS читает строку, а тебе отдает тупо MemoryStream. G>>Если у тебя установлен CommandBehavior.SequentialAccess, то тебе отдается SqlSequentialStream, который таки асинхронно читает поток. Глянь в ILSpy — он ожидает сигнала получения пакета и копирует байты в выходной буфер.
V>Если аснхронно — то сам ничего не читает и не ожидает. Кароч, всё ясно, курить completion routines до просветления. Ты получаешь сигнал готовности данных не асинхронно, а только когда входишь в ожидание этого сигнала, т.н. alertable thread state. Получаешь сигнал готовности иногда с бооольшим опозданием, ведь ты заходишь в slertable state очень даже синхронно, причем, ты должен получить сигнал готовности в том же самом потоке, откуда ты начал "асинхронную" операцию. Поэтому, никакого load balancing. Поэтому, задержавшись по неким объективным причинам на обработке текущей порции данных от одной из асинхронных операций, ты тормозишь вообще все асинхронные операции, привязанные к данному потоку.
Прочитал внимательно код TDS — явного вызова completion routines не увидел, все уходит через нативную библиотеку SNI, как она вызывает завершение — хз.
Так что есть подозрение что ты и тут свистишь.
V>Сравнимая по убогости технология — только WsaSelect для сокетов. Но в нейтиве мы хоть можем выбирать, как работать из кучи вариантов. А вдотнете имеем нифига не масштабируемый ввод-вывод. Отсюда плачевные результаты по производительности этого ввода/вывода.
Ну ок, покажи как надо. На слово тебе верить чтоли?
G>>Ничего что GetStream появился в .NET 4.5, а ты рассказываешь про какие-то дремучие времена? V>Ничего, ничего. Ты ж соврал про 8 лет на дотнете, походу. V>Есть такой SqlBytes.Stream.
Так он синхронный. Конечно вся асинхронность в нем эмулируется.
Ты же говорил о честном асинхронном стриме от SQL.
G>>По моему эти ошибки только в твоем воображении существуют. V>Рассуждая таким макаром, по твоему земля плоская. Ты же её и космоса не видел.
Тут какбы есть разница, много людей видело землю из космоса, да и физические эксперимены позволяют утверждать что земля круглая.
А ты рассказываешь про баги и тормоза, которых кроме тебя никто не видел. Кроме того неоднократно уже откровенно свистел про многие вещи.
V>>>И да. Упомянутый мною баг я обнаружил на 2-м дотнете, ес-но. И мне пришлось изучить код дотнетного клиентского драйвера под MS SQL фактически наизусть. А твоя распальцовка попросту смешна, бо ты в глаза не его видел и понятие не имеешь, как он работает. G>>Ну ты окончательно заврался, GetStream появился только в .NET 4.5. G>>До .NET 4.5 не было API для асинхронного чтения ридера. V>Видишь суслика? А он есть! (С)
Ну вот опять ты врешь. Не было до .NET 4.5 асинхронного чтения из ридера. Даже если тебе в руки стрим попадал, то все равно он был насквозь синхронный.
V>>>Далее. В Windows есть минимум 4 способа организации асинхронщины. Так вот, OLEDB давал "правильную" работу с TCP-соединением, даже при обычном, т.е. блокирующем чтении из него. Потому что overlapped API позволяет не только ожидать готовности данных, но может "само" заливать данные в заранее подготовленные буфера. G>>Ага, верю, чувак, верю. Жги дальше. V>Порядком утомил своим невежеством и хамством. До встречи через годик-другой.
Давай, послушаем сказки снова, ибо ты уже совсем слился.
Сюда, пожалуй, направлю свой вопрос, т.к. тема весьма интересная:
В данный момент есть только 2 бесплатные heavy ORM под .NET:
1. NHibernate — тормозное чудовище. Работать можно, но лучше не связываться.
2. EF 6. Тоже кривой проект, который вроде бы доведён до нормального уровня в последней версии, но (согласно "неуравновешанной" мягко говоря стратегии майкрософт) будет выпилен и заменён на EF 7 с которым будет не полностью совместим.
Из light ORM тоже особо не понавыбираешь:
1. Dapper — слишком примитивный и для специфических целей.
2. Linq to sql — давно не развивается, но теоретически поддерживается.
3. BLToolkit — вроде хорош, но завязан на одного/нескольких человек, которым он перестал быть особенно интересен и они переключились на linq to db. Тоже теоретически поддерживается, но общие прогнозы пессимистические, т.к. полноценно тянуть 2 фреймворка вряд ли будут.
4. Linq to db — в разработке, пока не богат функционалом, мало информации в инете, возможны баги.
К чему этот вопрос: мне сейчас надо накидать прототип, который возможно перерастёт в большой проект (а возможно и нет). Нужен ORM. Хотелось бы, конечно, плюшек в виде lazy loading и change tracking (т.к. неизвестно куда потом требования угуляют), но и без них можно обойтись.
Так же важен момент быстрого вхождения средних (не совсем бестолковых, но и не "10x") разработчиков.
Хотелось бы надёжную штуковину, которая бы 3-4 года ещё была актуальна и "в струе" дотнета.
База планируется средней нагруженности — будут блобы, файлы-документы, сотни пользователей, планировщики и т.д.
Что бы мне такое выбрать, чтобы не очень промахнуться?
Здравствуйте, A-Myth, Вы писали:
AM>4. Linq to db — в разработке, пока не богат функционалом, мало информации в инете, возможны баги.
l2db по функционалу во многом богаче blt. А большая часть отсуствующего там отсутствует специально.
AM>К чему этот вопрос: мне сейчас надо накидать прототип, который возможно перерастёт в большой проект (а возможно и нет). Нужен ORM.
linq2db
AM> Хотелось бы, конечно, плюшек в виде lazy loading и change tracking
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>linq2db
Ок. Посмотрю внимательнее.
AM>> Хотелось бы, конечно, плюшек в виде lazy loading и change tracking НС>Они тебе не нужны, поверь мне.
А вот с change tracking была история. В одном приложении с развесистым UI внезапно понадобился глобальный undo/redo.
Написано всё было на linq2sql и чтобы прикрутить нормальный ct пришлось попотеть. А вот была бы поддержка на уровне orm...
Здравствуйте, A-Myth, Вы писали:
AM>Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>linq2db
AM>Ок. Посмотрю внимательнее.
AM>>> Хотелось бы, конечно, плюшек в виде lazy loading и change tracking НС>>Они тебе не нужны, поверь мне. AM>А вот с change tracking была история. В одном приложении с развесистым UI внезапно понадобился глобальный undo/redo. AM>Написано всё было на linq2sql и чтобы прикрутить нормальный ct пришлось попотеть. А вот была бы поддержка на уровне orm...
Бери ef и не парься. Примеров в интернете можно нагулить на любую задачу.
Здравствуйте, A-Myth, Вы писали:
AM>Написано всё было на linq2sql и чтобы прикрутить нормальный ct пришлось попотеть. А вот была бы поддержка на уровне orm...
Зачем мешать два разных функционала? Это не является задачей ORM.
Здравствуйте, gandjustas, Вы писали:
G>Бери ef и не парься. Примеров в интернете можно нагулить на любую задачу.
Тоже вариант. Но сейчас, когда детальнее смотрю на задачу то вижу, что будет много разнообразной работы с базой, возможно, даже ручного анализа на первых порах (+ будет немного высоконагруженных мест), тонкой настройки.
Т.е. это точно не code first — хочется больше держать под ручным контролем и переделывать при необходимости.
В общем — пока не решил.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Зачем мешать два разных функционала? Это не является задачей ORM.
На концептуальном уровне согласен.
Но в реальности — зависит от дизайна и от других факторов. В тот момент поддержка ct хотя бы на уровне EF нам бы была выгодна просто с финансовой точки зрения.
Здравствуйте, gandjustas, Вы писали:
G>Бери ef и не парься.
Это несовместимые условия ))
Опять же, стартовать новый проект на заведомо устаревших технологиях — довольно странный совет, если только задача не "сделать и забыть".
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>Бери ef и не парься. IB>Это несовместимые условия )) IB>Опять же, стартовать новый проект на заведомо устаревших технологиях — довольно странный совет, если только задача не "сделать и забыть".
Апгрейд сделать не проблема вообще. Я переводил с 4.0 database first на 5.0 codefirst, заняло от силы пару часов. Переезд ef6 -> ef7 гораздо проще будет.
Здравствуйте, gandjustas, Вы писали:
G>Апгрейд сделать не проблема вообще. Я переводил с 4.0 database first на 5.0 codefirst, заняло от силы пару часов. Переезд ef6 -> ef7 гораздо проще будет.
We’ll be keeping the same concepts and patterns wherever it makes sense. The upgrade to EF7 will require some changes to your code. Our aim is that code that uses the core functionality of the DbContext API will upgrade easily, code that makes use of the lower level APIs in EF may require more complicated changes.
То есть переводя в практическую плоскоть — они даже API не собираются сохранять.
Переезд с 4.0 на 5.0 и должен был пройти гладко так как старый функционал не выкидывали. Здесь же в корне меняется концепция — из Havy ORM будут делать lightweight ORM, переписав продукт заново и сохранив API лишь там где концепции пересекаются.
В свете этого, я не понимаю откуда надежда, что переезд на 7-ю версию пройдет безболезненно.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>Апгрейд сделать не проблема вообще. Я переводил с 4.0 database first на 5.0 codefirst, заняло от силы пару часов. Переезд ef6 -> ef7 гораздо проще будет.
IB>We’ll be keeping the same concepts and patterns wherever it makes sense. The upgrade to EF7 will require some changes to your code. Our aim is that code that uses the core functionality of the DbContext API will upgrade easily, code that makes use of the lower level APIs in EF may require more complicated changes. IB>То есть переводя в практическую плоскоть — они даже API не собираются сохранять.
IB>Переезд с 4.0 на 5.0 и должен был пройти гладко так как старый функционал не выкидывали. Здесь же в корне меняется концепция — из Havy ORM будут делать lightweight ORM, переписав продукт заново и сохранив API лишь там где концепции пересекаются. IB>В свете этого, я не понимаю откуда надежда, что переезд на 7-ю версию пройдет безболезненно.
еще раз: я переводил с 4.0 database-first (с использованием генератора POCO) на 5.0 code first. Там поменялось все — меппинг, апи, дефолтное поведение. Это заняло пару часов.
Переезд ef6 -> ef7, которые оба codefirst, выльется в правку пары вызовов API.
Здравствуйте, gandjustas, Вы писали:
G>еще раз: я переводил с 4.0 database-first (с использованием генератора POCO) на 5.0 code first.
Странно, что приходится объяснять... code-first или last — значения не имеет. Это вообще фича с боку.
Между 4 и 5 — была обратная совместимость. Между 6 и 7 ее не будет.
G>Переезд ef6 -> ef7, которые оба codefirst, выльется в правку пары вызовов API.
Они оба ORM, на этом сходство заканчивается.
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, gandjustas, Вы писали:
G>>еще раз: я переводил с 4.0 database-first (с использованием генератора POCO) на 5.0 code first. IB>Странно, что приходится объяснять... code-first или last — значения не имеет. Это вообще фича с боку. IB>Между 4 и 5 — была обратная совместимость. Между 6 и 7 ее не будет.
Между database-frist и code first не было и нет.
G>>Переезд ef6 -> ef7, которые оба codefirst, выльется в правку пары вызовов API. IB>Они оба ORM, на этом сходство заканчивается. https://github.com/aspnet/EntityFramework посмотри примеры, тот же DbContext и DbSet, те же мапинги и миграции.
Ты тоже ведешься на сказки о "полном переписывании" ? Посмотри историю, там видно что в начале тупо скопировали из существующей кодовой базы.
Здравствуйте, gandjustas, Вы писали:
G>Между database-frist и code first не было и нет.
и еще раз: что именно там first — фича с боку, и на переход межу версиями не влияет.
G>https://github.com/aspnet/EntityFramework посмотри примеры, тот же DbContext и DbSet, те же мапинги и миграции.
Какая разница, DbContext или DataContext? Важно как оно работает. Если ты заложишься на LazyLoading или ChangeTracking какой-нибудь, а тебе его открутят в новой версии, то это будет уже совсем другой масштаб проблемы.
G>Ты тоже ведешься на сказки о "полном переписывании" ? Посмотри историю, там видно что в начале тупо скопировали из существующей кодовой базы.
У меня все просто — я смотрю не на сказки, а на готовый результат. Если результат мне нравится, я его использую, если же я вижу, что уродец получился (как в случае EF) — то не использую и другим не рекомендую.
IT>Чем HTML лучше того же WPF и что вообще подразумевается под "лучший UI"? IT>Ну не знаю. По мне так вроде нормально работает. Есть, конечно, косяки, в том числе касающиеся не только производительности. Например, сама по себе вполне качественная идея обезображена местами кривой имплементацией. Что касается производительности, то с ней всё впорядке, если не увлекаться кривыми левыми контролами и самому не злоупотреблять вложенностью контролов. IT>XAML — это по сути один большой костыль. Парни из MS вроде как сообразили, что для разметки UI пора делать свой собственный DSL, но не решились его сделать по человечески как тот же Razor, например. Вот и получился редкосный уродец на XML, который у нас в таких случаях выступает как универсальный всемогутор-языкозаменитель. IT>Всё это по сути лишь подтверждение моих слов о том, что идёт отбраковка и шлифовка.
В WPF (даже по сравнению с html/css/js) плохо всё: XAML, Dependency Properties, Data Binding, Control Templates, Data Templating, Triggers, Resource dictionaries, Commands, Logical and Visual Trees, Animation.
Всё перечисленное это безумие архитекторов астронавтов, которые малом писали приложений для конечных пользователей.
WPF не шлифовать надо, а просто выкинуть. Собственно, так и происходит, никто его не шлифует. Инсайдер из компании, которая занимается разработкой визуальных компонент, говорил, что продажи WPF компонент крайне малы (не окупаются даже). У Silverlight с продажами контролов было получше. Из-за того, что разработчики жаждут C# на клиенте и через web (но отнюдь не благодаря архитектуре). Но теперь это уже прошлое, не о чем говорить.
html/css/js далеко не идеален. Но это нормальный проверенный временем набор элементарных UI кирпичиков, из которых можно строить сложный UI. Никому не пришло в голову в UI ядро встраивать Data Binding, Data Templating, Control Templates. UI должен отвечать за UI.
Из концептуальных серьезных недостатков html/css/js отсутствие статической типизации, но для js это худо бедно решили с помощью TypeScript. А в css можно и отсутствие статической типизации потерпеть.
Т.е. у .NET огромный потенциал сделать лучший UI движок на базе статической типизации, но архитекторы астронавты умудрились слить даже html/css/js.
Здравствуйте, gandjustas, Вы писали:
V>>А я говорил, что ты не понимаешь нифига. Visual Studio вышла до выхода WinRT. Более того, она должна работать даже на тех версиях виндов, где WinRT не поддерживается. Более того, запуск студии в 5-15 секунд никого не волнует. Это же утилитное приложение. Вот если бы виндовый калькулятор запускался 5-15 секунд, то никто бы его не использовал. Вот почему в коробочных продуктах фактически нет WPF.
G>Действительно не понимаю как это связано. Похоже что связь у тебя в голове только существует.
Я же сразу сказал — не понимаешь нифига. Не понимаешь, почему студия написана на WPF, а не на WinRT. Не понимаешь, почему виндовый калькулятор на WPF не написан, хотя (я уверен) будет переписан на winRT (или уже полно аналогов с аналогичным временем запуска, как у старого).
G>>>А если учесть что из WPF родился UI для Windows 8 и Windows Phone, то не понимаю вдвойне. V>>А я говорил, что ты не понимаешь нифига. Этим UI должен был стать дотнетный "Авалон". Поищи по "Avalon Longhorn". G>Кому должен?
Согласно планам MS, где дидлайн был на конец 2006-го.
G>Может быть и стал бы, не будь у Синофски зуб на .NET.
Чего же до него не стал? Лет 6 было в запасе даже после дидлайна.
G>На WP таки сделали на .NET UI, только через несколько лет таки переписали на COM, чтобы единая платформа была.
Нет. Не сделали. Должна была быть не просто очередная ГУИ-либа для дотнета, а фундаментальная ГУИ среда для виндов, типа как было Win32+GDI. Так вот, WPF так и не стал тем, чем должен был стать. Собсно, наличие сервелатов уже говорило само за себя.
V>>Так вот. Эпик фейл WPF в том, что он так и не стал Авалоном. Заодно ЗАДЕРЖАЛ выход новых виндов более чем на 5 лет. Windows Vista должна была быть последним фейс-лифтом старых виндов, типа как Windows 98 перед Windows XP. А по-факту Windows Vista задержалась на 8 лет как основная операционка в виде "ребрендинга" Windows 7. И эта задержка могла бы продолжаться вечно, если бы не волевое решение переписать нафик Авалон на нейтиве. G>Ты веришь в маркетинговый буллшит? Слишком много слов "должен\должна", тебе никто ничего не должен, успокойся.
Ты утомил своей непроходимостью, реально. Официальный объявленный MS дидлайн операционки на Авалон был конец 2006-го года. Что здесь сложного для понимания?
V>>6 лет задержки из-за того, что дотнет так и не стал обладать необходимыми потребительскими характеристиками. G>При чем тут .NET? Почему это не помешало сделать UI для WP7 на .NET?
Потому что WP7 в ж-пе, по факту. WP8 — цаца. Некоторые аппараты можно обновить до 8-й.
V>>Масштаб этого эпик фейла не поддаётся осмыслению. Собсно, именно с конца 2006-го года начался обратный отсчет уровню доверия дотнету, как универсальной платформе. Прямо на сегодня этот уровень нулевой. Дотнет нифига не универсален, а занял лишь те ниши, в которых неплоха была и Джава. На этом всё. G>Сильную роль сыграло развитие JS, которое по сути похоронило идею Rich Desktop UI, очень популярную в начале 20 века
Не вижу никаких похорон. ГУИ внутри браузера как было унылым г-ном, так и осталось. А так-то десктопный ГУИ на скриптах отродясь писался что в Линухах, что под виндой на VBS, твоя JS — просто одна из популярных технологий. Ты не туда смотришь, кароч. Автоматизация на скриптах делается над каким-то низлежащим движком. Так вот, дотнетный движок им не стал, winRT — полностью нейтивная платформа.
V>>В 2005-2006 годах я занимался этим вопросом много и видел много таких проектов. На сегодня они не актуальны, ес-но, т.к. вопрос можно считать закрытым. Можешь поискать еще кодеки, например по speex dotnet. Я сходу нашел NAudio, например. Но более детальное знакомство показало, что для того же speex используется нейтивный кодек, хотя в проекте NSpeex были планы по релизу "родного" дотнетного кодека. Собсно, перевести открытый исходник на дотнет — это 2-3 дня работы разработчику средней руки. Я видел в те времена несколько "родных" дотнетных реализаций кодеков. Один из кодеков на дотнете как-то публиковал здесь я, для G.711. Портирование его из нейтива заняло меньше часа. Пользовали это в своих проектах. Характеристики производительности ни к черту. Поэтому, дотнет остался только для макетирования всех этих вещей, для боевого применения более половины движка переписали на нейтив, оставив дотнету только сигналинг. G>Я понял, про астериск были фантазии.
Нифиг ты не понял опять. Все эти эпик-фейлы ушли с горизонта уже к 2008-му окончательно. Но я тебе дал вполне конкретные имена проектов. Но эти проекты можно использовать лишь для макетирования, а не для боевого применения.
G>Про кодеки — не ясно зачем их на .NET писать вообще, там же числомолотилка, .NET ничего не даст.
1. Почему числомолотилка на дотнете хуже нейтивной? А как же JIT?
2. А где вообще дотнет что-то даст, окромя неспешного разбора ответа базы или формирования неспешного WEB-ответа?
V>>Если сможешь заставить работать быстрее — велкам. )) При том, что этот кодек до невозможности примитивен, в сравнении с тем же speex. G>Пот посмотрел на код, его чуть ли не 1-в-1 можно на C заменить (даже не C++), только массивы надо извне передавать. А для .NET можно написать обертку, которая зовет эту либу.
Еще раз повторю вопрос №1.
Вычисления по ссылке целочисленные, заметь. То бишь, даже пресловутое неумение дотнета пользовать SSEx оставим за кадром. Там банальные табличные вычисления. Дотнет сливает раза в 3 нейтиву даже на этом примитиве.
V>>Paint.Net не требует быстродействия. Вообще. Я разработал графический редактор для конференций на дотнете в 2006-м, где участники конференций могут рисовать на одной доске совместно. Никакой скорости не требуется. Вообще. Потому что основные тормоза от самой сетки. Потому что события даже от самых крутых мышек поступали не чаще 100 раз в секунду. Более того, мой редактор векторный, участники конференций могут изменять объекты, нарисованные другими участниками. Это намного сложнее растровой графики. G>Большинство десктопных приложений не требует быстродействия, вообще.
Фотошоп или CorelDraw требует еще как. Про AutoCAD я вообще молчу. Не говори таких глупостей никогда — засмеют.
G>Ни мессенджеры, ни заметки, ни какая-либо еще фигня.
Мессенджер должен запускаться мгновенно, так же как заметки и прочая фигня. Яховский мессенджер сдох именно по причине долгого (до 20 сек) запуска. OneNote тоже нейтивный и тоже быстро запускается. Кароч, я не понимаю, как ты не понимаешь очевидных аргументов.
G>Быстродействия на десктопе требуют игры
ВСЁ требует быстродействия. Браузер, калькулятор, мессенджер, фото-редактор.
G>в которых кстати игровая логика пишется на скриптовых языках
ы-ы-ы
G>которые по твоему гораздо менее надежны и быстры
А где надежность сидит, по-твоему?
В типичной современной навороченной игре используется нейтивный движок на порядка 3-5 млн строк исходников, порядка 30-50 тыщ строк исходников тех самых "скриптов для логики" и гигабайты медиа.
V>>В плане требований к производительности сравни с теми же нейтивными фильтрами для фотошлёпа, где даже на современных рабочих станциях хочется добавить мощщи. На дотнете это просто не влетит. От слова вообще. Се ля ви. G>Хм... почему фотошопу требуется быстродействие, а paint.nt — нет?
Хороший вопрос. Предлагаю освоить оба продукта самостоятельно. "Ты же программист!" ))
G>Разница только в тормозных фильтрах? Которые кстати тоже числомолотилки.
Даже без фильтров, при десятке слоёв с наложением для современной 16мбпкс фоты с камеры твой дотнетный паинт сразу мертв. А фотошлёп живее всех живых.
G>>>EverNote написали на .NET, получили инвестиции, пошли переписывать на C++. С таким баблом можно было и на ассемблере написать. А бекенд то на .NET и остался. Если бы начали на C++, то не то что инвестиций, даже релиза не было бы.
V>>Не юли. ЗАЧЕМ они переписали клиента под нейтив? Причем, он переписан под нейтив на кучи мобильных платформ в т.ч. V>>Вот нафига было переписывать со сверхудобного дотнета на страшный и ужасный нейтив? Твои варианты?
G>Потому что они могли это сделать и у них была на это куча бабла.
Детсад.
G>А альтернативы какие?
Добавить потребительских фич. Вложиться в сам сервис.
G>Разогнать команду и положить бабло в карман? Увы на инвестиционные деньги так поступать нельзя.
Детсад.
G>Дали бы мне столько бабла, я бы тоже все переписал на C++, даже за 1% прироста быстродействия.
Не так уж там много бабла было дано. Перепись на С++ была на грани бизнес-рисков. За ради 1% никто бы не возился.
G>Но мне не дают столько, поэтому пишу на .NET и проблем из-за этого не испытываю.
От твоих прог не требуется мгновенно появиться, проглотить заметку и так же мгновенно испариться.
V>>А я видел кучу влетевших нейтивных продуктов в то же самое время, хотя, нейтивные, как ты понимаешь, требуют больше человеко-лет, так? G>Ну приведи хотябы маленький список из этой кучи. Особенно, которые стартанули за последние 5-10 лет.
Скайп, Евернот, Вибер, ОпенОфис (и его клоны), переписанный на фик Гимп, переписанный с 0-ля на новом С++ и бусте КДЕ, переписанный нафик QT, сразу несколько физических и геометрических движков для игр, nosql-базы, самый популярный веб-сервак ngix. Список можно продолжать бесконечно.
V>>Так вот, по опыту серьезной разработки на дотнете и нейтиве одновременно я уже делился с тобой своими собственными наблюдениями еще пару лет назад (или даже больше). На дотнете можно оч быстро накидать "макет". Можно даже заставить его работать при полной функциональности. Затем, при попытке выжать эффективность с этого "макета" мы обнаруживаем, что вложения трудоёмкости оч быстро переплёвывают вложения трудоёмкости в сравнении с нейтивным вариантом. Ну т.е., когда такое же кол-во усилий по вылизыванию тратишь на нейтив, то результат просто несравнимый не в пользу дотнета. Поэтому, дотнет хорош там, где никакую эффективность ни от куда выжимать не надо, а надо чтобы написал — и оно работает и этого было уже достаточно. G>Ты опять про свой мир говоришь. Я никогда проблем с оптимизацией .NET коа до приемлемого уровня быстродействия не испытывал. Я конечно верю, что у тебя с этим проблемы, но .NET в этом не виноват.
Во-во, у тебя исключительно вопрос веры, бо опыта ноль. Дотнет виноват в том, что на нём очень трудоёмко добиться приемлимой производительности. Например, в одном из проектов мы полностью переписали основные коллекции таким образом, что сами объекты-коллекции стали value-type. Сразу всплыла куча ограничений на то, как этими коллекциями пользоваться... Зато быстродействие на ровном месте подскочило почти вдвое.
Да кароч, я пару лет назад приводил простой пример очереди задержки на аналогичной технике, где разница с вариантом на встроенных либах была 2.7 раз не в пользу последней. По моей статистике, простое уменьшение косвенности в 4 раза способно дать общее увеличение производительности в 2 раза. Прикол нейтивной программы в том, что в ней нет такого развесистого графа объектов, как в дотнете, бо 99% объектов размещаются в памяти других объектов как value-type в дотнете. И ты этот феномен не переплюнешь, как не прыгай.
G>>>Очень даже представляю, если понабрать таких грамотных посонов как ты и отправить писать .NET приложение, то его ждет эпик фейл. Постоянные баги и борьба с ветрянными мельницами. А еще потом полученное убожество надо продать.
V>>Ну так в дотнет "планка вхождения" ниже или как? Или дотнет требует сверх-мега спецов, чтобы написать продаваемый коробочный продукт? G>Одно другому не мешает. Ты же сам писал что не везде требуется супер-быстродействие.
Тебе мешает ограниченность. У тебя есть свой мир, своя вера. А если кто даёт тебе "неудобную" информацию, то ты, первым делом, пытаешься подвергнуть сомнению его профессиональный уровень. Это при том, что из обсуждений пары лет назад мне стало видно, что любую работу, которую ты вообще в состоянии выполнить, я сделаю быстрее и качественнее. Как бы ты ни старался, я всё-равно напишу эффективнее и быстрее на твоей же вотчине — дотнете. )) Потому что я хорошо понимаю, как работает низлежащая платформа, а ты — нет. Поэтому, такие как ты могут оптимизировать только оценку сложности сверху, но не снизу и не реальную сложность. Это уже не ваш удел.
V>>Зря ты перешел на личности, кста. По опыту разбора с тобой технических моментов за последние года 4 я бы оценил твоё владение платформой .Net как очень посредственное и очень поверхностное. Ничего более-менее серьезного, чем то, что можно сделать, пользуя лишь готовые библиотеки и инструменты, тебе поручать нельзя. Т.е. ты типичный пользователь технологий, а не их разработчик. G>Ну верь в это, может легче станет.
Ну я как бы могу поискать твои эпичные фейлы. Эпичные в том плане, что нельзя же столько постов подряд подставляться. ))
V>>>>Даже SQL-сервак и IIS. ))) G>>>SQL Server в таком виде как мы его знаем был создан в 2000 году, дальше были только доработки. Но вот что странно, новые фичи SQL часто реализуются через .NETтипы.
V>>Новые фичи самого сервака там реализуются в нейтиве, ес-но. Ты, наверно, хотел сказать, про поддержку хранимок на дотнете? Дык, Оракл это давно делает. Еще один дык от тебя и таких как ты говорит, что хранимки — это зло. Я уже запутался. Не поможешь распутать? G>hierarchyid как ни странно — .NET тип, Geometry и Geography тоже реализованы через .NET обертки. Но это все фигня, ибо главное в быстродействии SQL Server — чтение с диска.
Потрясающее невежество.
Ну и как твои Net-типы устроены, хранятся и обрабатываются, не в курсе? ))
И да... Если бы для SQL-сервака было важно только быстрое чтение с диска, то его бы давно и насовсем вытеснил бы какой-нить MySQL.
G>>>Ибо быстродействие зависит от скорости работы с диском, а не от того нативный там код или нет. V>>Та нифига. В "разогретой" базе индексы и статистика в основном сидят в ОП, а значит, скорость обработки их влияет существенно. Разница в скорости работы разогретой базы и не разогретой на порядки. G>Ты же понимаешь что в любой серьезной задаче с БД рассчитывать на то, что все данные будут в памяти невозможно. Поэтому и пилят запросы, чтобы количество чтений страниц уменьшить.
Поэтому индексы — это лишь проекции данных, а не все данные. Поэтому статистика — это диапазоны данных, а не сами данные. Поэтому, разогретая база работает почти на порядок быстрее холодной, что частоиспользуемые индексы и статистика оседают в ОП. У MS SQL свой механизм маппинга оперативки на файлы, вот этот шедуллер, который решает — какие страницы ОП освобождать, а какие еще оставить — это и есть один из важных моментов итогового быстродействия, эдакое важнейшее ноу-хау. А ты пытаешься выхолащивать всё до "быстрого чтения с диска".
V>>Думаю, что с момента выхода дотнета прошло дохрена времени. Думаю, что существует просто море альтернативных HTML-движков, в т.ч. есть пара и на дотнете. Не взлетели на дотнете, увы. А на нейтиве — взлетели. Даже на этом сайте есть форум, посвящённый одному из них. G>Опять твои фантазии, какие движки на .NET? Ссылок хоть пару приведешь? Не исследовательские проекты, а реальные попытки сделать браузер на .NET?
С чего ты взял, что это исследовательские проекты, а не реальные попытки, которые были заброшены из-за неперспективности.
Ты теперь понял, в чем твои сложности понимания реальности? Читать предыдущий вопрос до просветления.
G>Какой смысл в этом когда есть WebKit?
Ты о других движках не слышал, что ле?
И этот вебкит уже не разрабатывается, что ле? Он пилится быстро и много в данный момент.
К тому же, браузер — это же не числобробилка. Почему бы его не сделать на дотнете, ы? )))
Ведь это было бы так круто и модно, проще развивать и поддерживать новые стандарты HTML, не? Ты же сам утверждаешь, что на сравнимую задачу на дотнете надо в 10 раз меньше человекоресурсов. Прикинь, что если переписать вебкит на дотнете (а это работы на меньше месяца паре опытных разрабов, которые владеют и нейтивом и дотнетом), так вот, если прямо сейчас начать переписывать вебкит на дотнете при сравнимых человекоресурсах, то уже через 3-4 месяца он обгонит по надежности, кол-ву фич и стандартизации исходный вебкит. Но, почему-то, так никто не делает. Твои версии происходящего?
V>>Более того, движок IE был фактически полностью переписан с выходом 8-го IE. Расскажи нам, когда же вышел IE 8. )) G>"Полностью переписан" это маркетинговый буллшит. От силы 30% перписали, остальное скопипастили.
Увы, нет. Бока с CSS потребовали переделать внутренности. И после этого IE резво стал "правильным" и "совместимым". На предыдущей кодовой базе они бодались с этим бесполезно хрен знает сколько лет.
G>Как можно на несколько лет полностью переписать продукт, в который вложено несколько сотен человеко-лет труда и суммарно сотни лет тестирования, в том числе на реальных пользователях.
Потому что на современных либах и соврееменных ср-вах разработки и контроля кода это намного проще. Засада в либах, амиго. На нынешних либах буста и внутренних либах нашей конторы я могу переписать свои старые проекты 10-тилетней давности, ужав исходник в 3-10 раз и повысив надежность в бесконечное кол-во раз.
Я ж тебе грю — фишка дотнета в ОГРОМНОМ кол-ве отлаженного функционала.
G>IE 10 кстати тоже "полностью переписали" судя по маркетинговым заявлениями.
Ты плохо читаешь. Ему изменили только технологию вывода на экран и внешний ГУЙ. О внутренней переработке никто не заикался. Говорили еще что-то о JS-движке, но он общий на винду и браузер.
G>Откуда у МС ресурсы раз в 3 года полностью переписывать браузер?
По-твоему, код пишется со скоростью набора с клавиатуры?
Тогда бы средний программист писал 10-30 тыщ строк кода в день, а не 100-300.
Код пишется со скоростью принятия проектных (и других) решений. Со скоростью набивки тестовой регрессионной базы, со скоростью обрастания артефактами проектирования и сопровождения.
G>Это опять кратина в твоей голове. Самый популярный софт на мобилках — клиенты соцсетей. Все, как ни странно, не на C++ написаны.
Самый популярный из них — официальный клиент ВКонтакте. На 90% нейтивный на андроиде и полностью нейтивный на Симбиан, ИОС, Бада.
G>Яндекс карты, которыми постоянно пользуюсь, тоже не нативные.
О.М.Г.
У меня в браузере они какие, по твоему?
Жжешь не по детски.
G>Мобильный банк — тоже не нативный.
У меня он вообще в браузере, и?
G>Многие игры на Unity, который на .NET.
Это в твоих влажных мечтах он на .Net. Для дотнета там только бинд его библиотек. Утилиты и редактор на дотнете.
Основная фишка — это сервер ресурсов. Нейтивный, ес-но. Сам движок полностью нейтивный. И т.д.
V>>Не отожмут. Философия Аксапты примерно такая же, как у Паруса. Поэтому — не отожмут никогда. Парусы/Аксапты хороши в крупном секторе с большими инвестициями. А для средних и мелких предприятий они пролетают из-за своей бизнес-модели. А эта модель, в свою очередь, целиком и полностью зависит от технологии платформы. Кароч, для программирования под Парус и Аксапту нужны спецы в программировании, в отличие от спецов сугубо в прикладной области, которые могут "настраивать" 1С. Не зря же огромное программистов 1С — девушки. Но их почти нет в разработке под Парус и Аксапту. Поэтому рынок 1С и не отожмут — это другой совсем рынок. G>А ты думаешь МС интересуют внедрения в конторах на 10 человек с одним бухгалтеорм?
Это отмазка.
Дело в том, что в самой Америке бухгалтерия проста как дважды два. Можно прямо в Экселе её вести. А у нас сложна. Поэтому у нас появилась платформа 1C (были и конкурирующие похожие, типа Акцента и т.д.), а в Штатах такой платформы нет и не предвидится. А теперь гоу на оставленное цитирование, где речь была таки о технологических ограничениях, а не об офисах в 10 человек... MS им продаёт же серверную ОСь и офис, не гнушается, так? ))
G>>>Смотрю самсунг — http://hh.ru/search/vacancy?no_magic=true&text=Samsung&clusters=true&search_field=company_name&area=1&specialization=1.221&from=cluster_specialization G>>>Java\Android через одну. Много разработок драйверов, там по понятным причинам managed платформ нету. Да и чето не сильно похоже на "коробочные продукты" сервисы всякие в основном.
V>>hh.ru??? V>>Ты издеваешься? А на сам Самсунг зайти не судьба? G>Кинь ссылку, мне искать лень.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>А я говорил, что ты не понимаешь нифига. Visual Studio вышла до выхода WinRT. Более того, она должна работать даже на тех версиях виндов, где WinRT не поддерживается. Более того, запуск студии в 5-15 секунд никого не волнует. Это же утилитное приложение. Вот если бы виндовый калькулятор запускался 5-15 секунд, то никто бы его не использовал. Вот почему в коробочных продуктах фактически нет WPF.
G>>Действительно не понимаю как это связано. Похоже что связь у тебя в голове только существует.
V>Я же сразу сказал — не понимаешь нифига. Не понимаешь, почему студия написана на WPF, а не на WinRT. Не понимаешь, почему виндовый калькулятор на WPF не написан, хотя (я уверен) будет переписан на winRT (или уже полно аналогов с аналогичным временем запуска, как у старого).
Я не понимаю к чему ты это пишешь. Калькулятор в W8 кстати есть в виде app на JS.
G>>>>А если учесть что из WPF родился UI для Windows 8 и Windows Phone, то не понимаю вдвойне. V>>>А я говорил, что ты не понимаешь нифига. Этим UI должен был стать дотнетный "Авалон". Поищи по "Avalon Longhorn". G>>Кому должен? V>Согласно планам MS, где дидлайн был на конец 2006-го.
И че?
G>>Может быть и стал бы, не будь у Синофски зуб на .NET. V>Чего же до него не стал? Лет 6 было в запасе даже после дидлайна.
Синофски, если что, ушел только в 2012, а фарш назад не провернешь.
G>>На WP таки сделали на .NET UI, только через несколько лет таки переписали на COM, чтобы единая платформа была.
V>Нет. Не сделали.
Опять фантазии? Я вот видел WPF\Silverlight UI на WP7-8, а ты куда смотрел в это время?
V>Должна была быть не просто очередная ГУИ-либа для дотнета, а фундаментальная ГУИ среда для виндов, типа как было Win32+GDI. Так вот, WPF так и не стал тем, чем должен был стать. Собсно, наличие сервелатов уже говорило само за себя.
Кому должна? Успокойся, тебе никто ничего не должен.
Отсутствие .NET на клиенте — заслуга синофски. На сервере дофига .NET, как минимум треть серверных фич использует .NET. А уж то, что все серверные продукты на .NET я вообще молчу.
V>>>Так вот. Эпик фейл WPF в том, что он так и не стал Авалоном. Заодно ЗАДЕРЖАЛ выход новых виндов более чем на 5 лет. Windows Vista должна была быть последним фейс-лифтом старых виндов, типа как Windows 98 перед Windows XP. А по-факту Windows Vista задержалась на 8 лет как основная операционка в виде "ребрендинга" Windows 7. И эта задержка могла бы продолжаться вечно, если бы не волевое решение переписать нафик Авалон на нейтиве. G>>Ты веришь в маркетинговый буллшит? Слишком много слов "должен\должна", тебе никто ничего не должен, успокойся. V>Ты утомил своей непроходимостью, реально. Официальный объявленный MS дидлайн операционки на Авалон был конец 2006-го года. Что здесь сложного для понимания?
Еще раз — никто тебе ничего не должен. То что ты поверил в маркетинговый буллшит — твоя проблема на 100%. МС стабильно меняет планы каждые 3 года, так что вполне ожидаемо, что avalon не родился. Так десятки продуктов и технологий не родились. И вовсе не по техническим причинам, а по политическим.
V>>>6 лет задержки из-за того, что дотнет так и не стал обладать необходимыми потребительскими характеристиками. G>>При чем тут .NET? Почему это не помешало сделать UI для WP7 на .NET? V>Потому что WP7 в ж-пе, по факту. WP8 — цаца. Некоторые аппараты можно обновить до 8-й.
Ситуация после появления WP8 не изменилась. Посмотри графики долей рыка и продаж устройств.
V>>>Масштаб этого эпик фейла не поддаётся осмыслению. Собсно, именно с конца 2006-го года начался обратный отсчет уровню доверия дотнету, как универсальной платформе. Прямо на сегодня этот уровень нулевой. Дотнет нифига не универсален, а занял лишь те ниши, в которых неплоха была и Джава. На этом всё. G>>Сильную роль сыграло развитие JS, которое по сути похоронило идею Rich Desktop UI, очень популярную в начале 20 века V>Не вижу никаких похорон.
Потому что ты видишь только фантазии в твоей голове.
МС пытался Rich Desktop UI вытянуть очень долго, только после релиза W7 сдался. Думаешь почему на IE забивали столько времени, а сейчас в попыхах догоняют? Какая стратегия привела к такой ситуации? Догадаешься?
V>ГУИ внутри браузера как было унылым г-ном, так и осталось.
Тем не менее сейчас это самый популярный вариант.
V>А так-то десктопный ГУИ на скриптах отродясь писался что в Линухах, что под виндой на VBS, твоя JS — просто одна из популярных технологий. Ты не туда смотришь, кароч. Автоматизация на скриптах делается над каким-то низлежащим движком. Так вот, дотнетный движок им не стал, winRT — полностью нейтивная платформа.
Это разговор ни о чем. В любом случае где-то выполняется нативный код. Но это абсолютно нерелевантно тому, на чем люди пишут. Ты наверное удивишься, но большинство WinRT приложений это JS и .NET.
V>>>В 2005-2006 годах я занимался этим вопросом много и видел много таких проектов. На сегодня они не актуальны, ес-но, т.к. вопрос можно считать закрытым. Можешь поискать еще кодеки, например по speex dotnet. Я сходу нашел NAudio, например. Но более детальное знакомство показало, что для того же speex используется нейтивный кодек, хотя в проекте NSpeex были планы по релизу "родного" дотнетного кодека. Собсно, перевести открытый исходник на дотнет — это 2-3 дня работы разработчику средней руки. Я видел в те времена несколько "родных" дотнетных реализаций кодеков. Один из кодеков на дотнете как-то публиковал здесь я, для G.711. Портирование его из нейтива заняло меньше часа. Пользовали это в своих проектах. Характеристики производительности ни к черту. Поэтому, дотнет остался только для макетирования всех этих вещей, для боевого применения более половины движка переписали на нейтив, оставив дотнету только сигналинг. G>>Я понял, про астериск были фантазии. V>Нифиг ты не понял опять. Все эти эпик-фейлы ушли с горизонта уже к 2008-му окончательно. Но я тебе дал вполне конкретные имена проектов. Но эти проекты можно использовать лишь для макетирования, а не для боевого применения.
Ну так приведи ссылки. На слово тебе верить что ли?
G>>Про кодеки — не ясно зачем их на .NET писать вообще, там же числомолотилка, .NET ничего не даст. V>1. Почему числомолотилка на дотнете хуже нейтивной? А как же JIT?
Тут есть проблема: у JIT довольно мало времени заниматься оптимизацией, а сделать оптимизацию на уровне IL сложно, ибо IL должен быть верифицируемым.
Чтобы добиться максимального быстродействия нужен умный AOT-компилятор, который работает с учетом профилирования. МС сейчас делает такой, .NET Native называется. Вангую что через 3-5 лет он заменит\дополнит стандартный ngen.
V>2. А где вообще дотнет что-то даст, окромя неспешного разбора ответа базы или формирования неспешного WEB-ответа?
Фактически везде. Потому что писать быстрее, готовых либ больше и средства разработки удобнее.
А на сервере так вообще .NET рвет C++, потому что:
1) Есть эффективная и удобная асинхронность.
2) Есть Linq. который позволяет генерировать хорошие запросы к базе.
3) Готовые библиотеки с реализацией кеширования, которое необходимо для разработки приложения.
4) Склейка строк для генерации HTML делается на .NET быстрее, чем на C++.
V>>>Если сможешь заставить работать быстрее — велкам. )) При том, что этот кодек до невозможности примитивен, в сравнении с тем же speex. G>>Пот посмотрел на код, его чуть ли не 1-в-1 можно на C заменить (даже не C++), только массивы надо извне передавать. А для .NET можно написать обертку, которая зовет эту либу.
V>Еще раз повторю вопрос №1. V>Вычисления по ссылке целочисленные, заметь. То бишь, даже пресловутое неумение дотнета пользовать SSEx оставим за кадром. Там банальные табличные вычисления. Дотнет сливает раза в 3 нейтиву даже на этом примитиве.
И что? Никто не спорит, что чилополотилка на C будет быстрее, чем на .NET. Но числомолотилки в реальных приложениях встречаются крайне редко.
V>>>Paint.Net не требует быстродействия. Вообще. Я разработал графический редактор для конференций на дотнете в 2006-м, где участники конференций могут рисовать на одной доске совместно. Никакой скорости не требуется. Вообще. Потому что основные тормоза от самой сетки. Потому что события даже от самых крутых мышек поступали не чаще 100 раз в секунду. Более того, мой редактор векторный, участники конференций могут изменять объекты, нарисованные другими участниками. Это намного сложнее растровой графики. G>>Большинство десктопных приложений не требует быстродействия, вообще.
V>Фотошоп или CorelDraw требует еще как. Про AutoCAD я вообще молчу. Не говори таких глупостей никогда — засмеют.
Для автокада успешно пишут плагины на .NET, да и сам он WPF использует (по крайней мере в 2009).
В фотошопе скорость нужна только в фильтрах (числомолотилках). Во всем остальном — нет. Paint.NET нормально работает, для большинства пользователей отлично заменяет фотошоп.
Кстати никто не мешает сделать на C либу фильтра, завернуть в .NET и использовать с тем же успехом в Paint.net.
G>>Ни мессенджеры, ни заметки, ни какая-либо еще фигня.
V>Мессенджер должен запускаться мгновенно, так же как заметки и прочая фигня. Яховский мессенджер сдох именно по причине долгого (до 20 сек) запуска. OneNote тоже нейтивный и тоже быстро запускается. Кароч, я не понимаю, как ты не понимаешь очевидных аргументов.
У меня почему-то Paint.NET запускается быстрее OneNote. Да и вообще приложения как-то не торопясь стуртуют, пара секунд — вполне.
Кстати скорость запуска != скорость работы. Сделай NGen сборкам и приложение начнет также "мгновенно" запускаться.
G>>Быстродействия на десктопе требуют игры V>ВСЁ требует быстродействия. Браузер, калькулятор, мессенджер, фото-редактор.
Успокойся, у тебя снова фантазия воспаляется. Были исследования по скорости запуска, человек спокойно ждет пару секунд.
G>>в которых кстати игровая логика пишется на скриптовых языках V>ы-ы-ы
Совсем заклинило? Lua, Python и даже C# (Unity) не слышал?
G>>которые по твоему гораздо менее надежны и быстры V>А где надежность сидит, по-твоему?
Уж точно не в C++
V>В типичной современной навороченной игре используется нейтивный движок на порядка 3-5 млн строк исходников, порядка 30-50 тыщ строк исходников тех самых "скриптов для логики" и гигабайты медиа.
Только движок не пишется на каждую игру, а логика пишется. У меня есть подозрение что для игр на сегодня пишется гораздо больше кода на скриптовых языках, чем на C++.
А если учеть Unity, то на C++ пишется очень маленькая часть.
И, кстати, по твоей логике нет смылса вообще использовать скриптовые движки, ибо C++ надежнее, а по факту оказывается наоборот.
V>>>В плане требований к производительности сравни с теми же нейтивными фильтрами для фотошлёпа, где даже на современных рабочих станциях хочется добавить мощщи. На дотнете это просто не влетит. От слова вообще. Се ля ви. G>>Хм... почему фотошопу требуется быстродействие, а paint.nt — нет?
V>Хороший вопрос. Предлагаю освоить оба продукта самостоятельно. "Ты же программист!" ))
Кроме фильтров не вижу где вообще может потребоваться быстродейстие. Отзывчивость интерфейса гораздо важнее. А это для C++ гораздо большая проблема, чем для .NET.
G>>Разница только в тормозных фильтрах? Которые кстати тоже числомолотилки.
V>Даже без фильтров, при десятке слоёв с наложением для современной 16мбпкс фоты с камеры твой дотнетный паинт сразу мертв. А фотошлёп живее всех живых.
Открыл Paint.NET, сделал 12 слоев с прозрачностью с 10мп фотками, полет нормальный. Не тормозит.
И как-бы логично, рисуется только один раз, разницы нет будет это 10мс или 100мс.
Так что снова твои воспаленные фантазии, крайне далекие от реальной жизни.
G>>>>EverNote написали на .NET, получили инвестиции, пошли переписывать на C++. С таким баблом можно было и на ассемблере написать. А бекенд то на .NET и остался. Если бы начали на C++, то не то что инвестиций, даже релиза не было бы.
V>>>Не юли. ЗАЧЕМ они переписали клиента под нейтив? Причем, он переписан под нейтив на кучи мобильных платформ в т.ч. V>>>Вот нафига было переписывать со сверхудобного дотнета на страшный и ужасный нейтив? Твои варианты?
Еще раз — надо было куда-то потратить бабло. Переписать на C++ — хороший способ. Будь у меня избыток бабла я тоже буду все на C++ переписывать.
G>>Потому что они могли это сделать и у них была на это куча бабла. V>Детсад.
Правда жизни. Ты слишком далек от бизнеса чтобы понимать это.
G>>А альтернативы какие? V>Добавить потребительских фич. Вложиться в сам сервис.
Каких фич? Думаешь это так просто, взять и добавить фичу?
Это вообще хороший способ убить продукт — вкладываться в тонну новых фич, когда получил инвестиции.
G>>Разогнать команду и положить бабло в карман? Увы на инвестиционные деньги так поступать нельзя. V>Детсад.
Правда жизни. Ты слишком далек от бизнеса чтобы понимать это.
G>>Дали бы мне столько бабла, я бы тоже все переписал на C++, даже за 1% прироста быстродействия. V>Не так уж там много бабла было дано. Перепись на С++ была на грани бизнес-рисков. За ради 1% никто бы не возился.
Бабло куда-то пустить надо. Новые фичи это сложно, ибо надо не перегрузить продукт. А переписать — прекрасная идея чтобы бабло потратить и выйграть время подумать над продуктом. На самом деле можно удачно релизить пару мажорных версий, изменяя шрифты и добавляя 1% быстродействия. Еще и бабла за апгрейд брать.
G>>Но мне не дают столько, поэтому пишу на .NET и проблем из-за этого не испытываю. V>От твоих прог не требуется мгновенно появиться, проглотить заметку и так же мгновенно испариться.
Угу, от моих прог требуется обрабатывать терабайты данных и выдавать ответ менее чем за секунду.
Это конечно крайне далеко от того, чтобы "мгновенно испариться".
А кто мешает приложение в фоне держать и показывать окно по нажатию кнопки? При чем тут скорость запуска и скорость работы вообще? Разве реально требуется запускать и останавливать приложение?
V>>>А я видел кучу влетевших нейтивных продуктов в то же самое время, хотя, нейтивные, как ты понимаешь, требуют больше человеко-лет, так? G>>Ну приведи хотябы маленький список из этой кучи. Особенно, которые стартанули за последние 5-10 лет.
V>Скайп, Евернот, Вибер, ОпенОфис (и его клоны), переписанный на фик Гимп, переписанный с 0-ля на новом С++ и бусте КДЕ, переписанный нафик QT, сразу несколько физических и геометрических движков для игр, nosql-базы, самый популярный веб-сервак ngix. Список можно продолжать бесконечно.
Скайп старше 10 лет, а текущая версия вообще на JS.
Эвернот был написан на .NET
опенофис — говно, лучше бы его не упоминал
гимп рядом не валялся с Paint.NET
Самая крутая NoSQL база написана на .NET
V>>>Так вот, по опыту серьезной разработки на дотнете и нейтиве одновременно я уже делился с тобой своими собственными наблюдениями еще пару лет назад (или даже больше). На дотнете можно оч быстро накидать "макет". Можно даже заставить его работать при полной функциональности. Затем, при попытке выжать эффективность с этого "макета" мы обнаруживаем, что вложения трудоёмкости оч быстро переплёвывают вложения трудоёмкости в сравнении с нейтивным вариантом. Ну т.е., когда такое же кол-во усилий по вылизыванию тратишь на нейтив, то результат просто несравнимый не в пользу дотнета. Поэтому, дотнет хорош там, где никакую эффективность ни от куда выжимать не надо, а надо чтобы написал — и оно работает и этого было уже достаточно. G>>Ты опять про свой мир говоришь. Я никогда проблем с оптимизацией .NET коа до приемлемого уровня быстродействия не испытывал. Я конечно верю, что у тебя с этим проблемы, но .NET в этом не виноват.
V>Во-во, у тебя исключительно вопрос веры, бо опыта ноль. Дотнет виноват в том, что на нём очень трудоёмко добиться приемлимой производительности.
Это тебе трудно, я всегда добивался, при чем довольно быстро. Конечно у меня и в мыслях не было кодеки писать на .NET.
Так что это у тебя опыта написания и оптимизации на .NET нету. Но не переживай, готов тебя научить за небольшое вознаграждение.
V>Например, в одном из проектов мы полностью переписали основные коллекции таким образом, что сами объекты-коллекции стали value-type. Сразу всплыла куча ограничений на то, как этими коллекциями пользоваться... Зато быстродействие на ровном месте подскочило почти вдвое.
Пример кода и тестов в студию. На слово тебе чтоли верить?
V>Да кароч, я пару лет назад приводил простой пример очереди задержки на аналогичной технике, где разница с вариантом на встроенных либах была 2.7 раз не в пользу последней. По моей статистике, простое уменьшение косвенности в 4 раза способно дать общее увеличение производительности в 2 раза. Прикол нейтивной программы в том, что в ней нет такого развесистого графа объектов, как в дотнете, бо 99% объектов размещаются в памяти других объектов как value-type в дотнете. И ты этот феномен не переплюнешь, как не прыгай.
Давай код, я тебе не верю. У меня слишком много оснований для этого.
G>>>>Очень даже представляю, если понабрать таких грамотных посонов как ты и отправить писать .NET приложение, то его ждет эпик фейл. Постоянные баги и борьба с ветрянными мельницами. А еще потом полученное убожество надо продать. V>>>Ну так в дотнет "планка вхождения" ниже или как? Или дотнет требует сверх-мега спецов, чтобы написать продаваемый коробочный продукт? G>>Одно другому не мешает. Ты же сам писал что не везде требуется супер-быстродействие.
V>Тебе мешает ограниченность. У тебя есть свой мир, своя вера. А если кто даёт тебе "неудобную" информацию, то ты, первым делом, пытаешься подвергнуть сомнению его профессиональный уровень.
Ты от зеркала отойди
V>Это при том, что из обсуждений пары лет назад мне стало видно, что любую работу, которую ты вообще в состоянии выполнить, я сделаю быстрее и качественнее. Как бы ты ни старался, я всё-равно напишу эффективнее и быстрее на твоей же вотчине — дотнете. )) Потому что я хорошо понимаю, как работает низлежащая платформа, а ты — нет. Поэтому, такие как ты могут оптимизировать только оценку сложности сверху, но не снизу и не реальную сложность. Это уже не ваш удел.
Успокой уже свою воспаленную фантазию. Ты уже столько раз откровенно врал, что вообе нет никаких оснований верить, что ты хоть что-либо писал.
Более того я помню эпик фейл, когда ты рассказывал как WPF работает и почему он тормозит, а профайлер показал что тормозит тупо загрузка стандартных ресурсов.
Да и про SqlClient ты уже показал свои "знания", про APС, хотя ни одного APC вызова в .NET и не существет.
Но ты продолжай, к успеху идешь.
V>>>Зря ты перешел на личности, кста. По опыту разбора с тобой технических моментов за последние года 4 я бы оценил твоё владение платформой .Net как очень посредственное и очень поверхностное. Ничего более-менее серьезного, чем то, что можно сделать, пользуя лишь готовые библиотеки и инструменты, тебе поручать нельзя. Т.е. ты типичный пользователь технологий, а не их разработчик. G>>Ну верь в это, может легче станет. V>Ну я как бы могу поискать твои эпичные фейлы. Эпичные в том плане, что нельзя же столько постов подряд подставляться. ))
Ты о чем? Помоему ты уже не первый пост просто врешь. Ты еще ни одного доказательства своим словам не привел. Зато насвистел уже столько, что уровень доверия к твоим словам не просто нулевой, а отрицательный.
V>>>>>Даже SQL-сервак и IIS. ))) G>>>>SQL Server в таком виде как мы его знаем был создан в 2000 году, дальше были только доработки. Но вот что странно, новые фичи SQL часто реализуются через .NETтипы.
V>>>Новые фичи самого сервака там реализуются в нейтиве, ес-но. Ты, наверно, хотел сказать, про поддержку хранимок на дотнете? Дык, Оракл это давно делает. Еще один дык от тебя и таких как ты говорит, что хранимки — это зло. Я уже запутался. Не поможешь распутать? G>>hierarchyid как ни странно — .NET тип, Geometry и Geography тоже реализованы через .NET обертки. Но это все фигня, ибо главное в быстродействии SQL Server — чтение с диска. V>Потрясающее невежество.
Да, чувак, ты прав, ты настолько не понимаешь как делается разработка, что даже не знаю что тебе еще сказать.
V>Ну и как твои Net-типы устроены, хранятся и обрабатываются, не в курсе? ))
В курсе. Хранятся на диске в виде массива байт, для обработки десериализуется в .NET объект и с ним выполняется обычный .NET код.
V>И да... Если бы для SQL-сервака было важно только быстрое чтение с диска, то его бы давно и насовсем вытеснил бы какой-нить MySQL.
Шутка дня, спасибо, записал.
обогнать SQL Serer по прямому чтению с диска не может ни один движок. Потому что в SQL Server вложено столько знаний об особенностях Windows, что ни одному MySQL не под силу.
Кроме этого SQL еще очень хорошо умеет оптимизировать чтение, за счет индексов, статистики итп. При чем для этой оптимизации тратится доифга ресурсов на стадии записи.
G>>>>Ибо быстродействие зависит от скорости работы с диском, а не от того нативный там код или нет. V>>>Та нифига. В "разогретой" базе индексы и статистика в основном сидят в ОП, а значит, скорость обработки их влияет существенно. Разница в скорости работы разогретой базы и не разогретой на порядки. G>>Ты же понимаешь что в любой серьезной задаче с БД рассчитывать на то, что все данные будут в памяти невозможно. Поэтому и пилят запросы, чтобы количество чтений страниц уменьшить.
V>Поэтому индексы — это лишь проекции данных, а не все данные.
Что означает эта фраза? Чем проекции отличаются от "самих данных" ? Проекция колонки типа int это что?
V>Поэтому статистика — это диапазоны данных, а не сами данные.
А эта фраза что означает?
V>Поэтому, разогретая база работает почти на порядок быстрее холодной, что частоиспользуемые индексы и статистика оседают в ОП.
Статистика используется только при построении планов. Никакого "оседания" в оп нет. Там нечто вроде LRU для buffer pool используется.
V>У MS SQL свой механизм маппинга оперативки на файлы, вот этот шедуллер, который решает — какие страницы ОП освобождать, а какие еще оставить — это и есть один из важных моментов итогового быстродействия, эдакое важнейшее ноу-хау. А ты пытаешься выхолащивать всё до "быстрого чтения с диска".
Это "ноу-хау" это LRU кеш, а "свой механизм маппинга оперативки на файлы" — обычное небуфиризированное чтение. Магии никакой нет, но есть куча тонкостей, что без ковыряния довольно сложно сходу такое повторить.
Но это далеко не самое главное. Самое главное в находится в оптимизаторе запросов, который определяет какие страницы читать, а какие нет. Вот там действительно дофига науки.
Короче как обычно ты не там ишещь потенциал оптимизации. На низком уровне довольно простые вещи используются причем их и на .NET можно написать с тем же успехом (см RavenDB).
V>>>Думаю, что с момента выхода дотнета прошло дохрена времени. Думаю, что существует просто море альтернативных HTML-движков, в т.ч. есть пара и на дотнете. Не взлетели на дотнете, увы. А на нейтиве — взлетели. Даже на этом сайте есть форум, посвящённый одному из них. G>>Опять твои фантазии, какие движки на .NET? Ссылок хоть пару приведешь? Не исследовательские проекты, а реальные попытки сделать браузер на .NET?
V>С чего ты взял, что это исследовательские проекты, а не реальные попытки, которые были заброшены из-за неперспективности.
Как минимум с того что про это говоришь ты Поводов верить тебе никаких, а не верть — хоть отбавляй.
V>Ты теперь понял, в чем твои сложности понимания реальности? Читать предыдущий вопрос до просветления.
Да, в том что моя реальность билже к объективной, чем твоя. Но это я давно понял.
G>>Какой смысл в этом когда есть WebKit? V>Ты о других движках не слышал, что ле? V>И этот вебкит уже не разрабатывается, что ле? Он пилится быстро и много в данный момент.
И какой смысл пилить другой? Если бы был хоть один экономический фактор, из-за которого имеет смысл свой движок делать, то уже бы кто-нибудь это делал. А без такого стимула будут только исследовательские проекты.
V>К тому же, браузер — это же не числобробилка. Почему бы его не сделать на дотнете, ы? )))
Потому что браузеры не пишутся с нуля.
V>Ведь это было бы так круто и модно, проще развивать и поддерживать новые стандарты HTML, не? Ты же сам утверждаешь, что на сравнимую задачу на дотнете надо в 10 раз меньше человекоресурсов. Прикинь, что если переписать вебкит на дотнете (а это работы на меньше месяца паре опытных разрабов, которые владеют и нейтивом и дотнетом), так вот, если прямо сейчас начать переписывать вебкит на дотнете при сравнимых человекоресурсах, то уже через 3-4 месяца он обгонит по надежности, кол-ву фич и стандартизации исходный вебкит. Но, почему-то, так никто не делает. Твои версии происходящего?
Давай посчитаем.
Вебкит начали разрабатывать в 2000 году. Не знаю сколько человек его пилило, но по статистике таких проектов это около 50 человек должно быть. То есть в него вложено порядка 700 человеко-лет. Предположим, что .NET реально увеличит скорость разработки в 10 раз. То есть 70 человеко-лет. И это только движок. Если его на .NET переписать, то надо будет и всю обвязку вокруг него сделать на .NET. Это еще примерно столько же. Грубо говоря полноценный браузер на .NET это в лучшем случае 150 человеко-лет. Стоимость программиста такого уровня будет порядка $100,000 год. Итого $15 лямов баксов. Это только программисты. А еще тестеры, манагеры итп. Короче суммарно выйдет не мене $50М и пара-тройка лет. А какой выхлоп будет? В деньгах. Чето мне кажется никакого.
Если ты думаешь что в таких проектах есть хоть какие-то технические причины не писать на .NET, то ты сльно заблуждаешься. Достаточно посчитать бабло и понять что причины чисто экономические.
V>>>Более того, движок IE был фактически полностью переписан с выходом 8-го IE. Расскажи нам, когда же вышел IE 8. )) G>>"Полностью переписан" это маркетинговый буллшит. От силы 30% перписали, остальное скопипастили.
V>Увы, нет. Бока с CSS потребовали переделать внутренности. И после этого IE резво стал "правильным" и "совместимым". На предыдущей кодовой базе они бодались с этим бесполезно хрен знает сколько лет.
Походу ты реально поверил. А в реальности "полное переписывание" — от силы 30% кодовой базы затрагивает. Во времена офиса 2007 говорил о "полном переписывании", а выяснилось что переписали совсем не много, увы ссылку не найду.
G>>Как можно на несколько лет полностью переписать продукт, в который вложено несколько сотен человеко-лет труда и суммарно сотни лет тестирования, в том числе на реальных пользователях. V>Потому что на современных либах и соврееменных ср-вах разработки и контроля кода это намного проще. Засада в либах, амиго. На нынешних либах буста и внутренних либах нашей конторы я могу переписать свои старые проекты 10-тилетней давности, ужав исходник в 3-10 раз и повысив надежность в бесконечное кол-во раз.
Да-да, видел я таких бравых парней. А после переписывания появляется 100500 новых багов и правка их приводит к тому, что от сил в 2 раза меньше трудозатрат уходит на переписываение, и то потому что уже знаешь как оно должно работать. Вообще ни один крупный продукт никогда 100% не переписывался. Один раз попытались это сделать в Netscape и это убило и браузер, и компанию. И любой руководитель большой разработки прекрасно это знает и никогда не допустит такого развития событий.
V>Я ж тебе грю — фишка дотнета в ОГРОМНОМ кол-ве отлаженного функционала.
А почему нет этого огромного количества в C++? Чем он хуже?
G>>IE 10 кстати тоже "полностью переписали" судя по маркетинговым заявлениями. V>Ты плохо читаешь. Ему изменили только технологию вывода на экран и внешний ГУЙ. О внутренней переработке никто не заикался. Говорили еще что-то о JS-движке, но он общий на винду и браузер.
Я как раз хорошо читаю и не верю в буллшит о "переписывании". JS движок тоже неслабая часть браузера в современных браузерах.
G>>Откуда у МС ресурсы раз в 3 года полностью переписывать браузер? V>По-твоему, код пишется со скоростью набора с клавиатуры? V>Тогда бы средний программист писал 10-30 тыщ строк кода в день, а не 100-300.
Это ты о чем?
V>Код пишется со скоростью принятия проектных (и других) решений. Со скоростью набивки тестовой регрессионной базы, со скоростью обрастания артефактами проектирования и сопровождения.
Если надо переписать готовое приложение, то к чему это ты написал?
G>>Это опять кратина в твоей голове. Самый популярный софт на мобилках — клиенты соцсетей. Все, как ни странно, не на C++ написаны. V>Самый популярный из них — официальный клиент ВКонтакте. На 90% нейтивный на андроиде и полностью нейтивный на Симбиан, ИОС, Бада.
Доказательства? На слово тебе верить чтоли?
G>>Яндекс карты, которыми постоянно пользуюсь, тоже не нативные.
V>О.М.Г. V>У меня в браузере они какие, по твоему?
У тебя в браузере они на JS.
А у меня на планшете и на телефоне на .NET.
А на iOS они на ObjC написаны.
G>>Мобильный банк — тоже не нативный. V>У меня он вообще в браузере, и?
И он не нативный
G>>Многие игры на Unity, который на .NET.
V>Это в твоих влажных мечтах он на .Net. Для дотнета там только бинд его библиотек. Утилиты и редактор на дотнете. V>Основная фишка — это сервер ресурсов. Нейтивный, ес-но. Сам движок полностью нейтивный. И т.д.
Да какая разница, не важно на начем движок, важно на чем пишет программист.
Почему не существует такого Unity для C++?
V>>>Не отожмут. Философия Аксапты примерно такая же, как у Паруса. Поэтому — не отожмут никогда. Парусы/Аксапты хороши в крупном секторе с большими инвестициями. А для средних и мелких предприятий они пролетают из-за своей бизнес-модели. А эта модель, в свою очередь, целиком и полностью зависит от технологии платформы. Кароч, для программирования под Парус и Аксапту нужны спецы в программировании, в отличие от спецов сугубо в прикладной области, которые могут "настраивать" 1С. Не зря же огромное программистов 1С — девушки. Но их почти нет в разработке под Парус и Аксапту. Поэтому рынок 1С и не отожмут — это другой совсем рынок. G>>А ты думаешь МС интересуют внедрения в конторах на 10 человек с одним бухгалтеорм?
V>Это отмазка.
Это правда жизни.
V>Дело в том, что в самой Америке бухгалтерия проста как дважды два. Можно прямо в Экселе её вести. А у нас сложна. Поэтому у нас появилась платформа 1C (были и конкурирующие похожие, типа Акцента и т.д.), а в Штатах такой платформы нет и не предвидится. А теперь гоу на оставленное цитирование, где речь была таки о технологических ограничениях, а не об офисах в 10 человек... MS им продаёт же серверную ОСь и офис, не гнушается, так? ))
Ты не в курсе что банки должны отчитываться по МСФО, что успешно умеет AX. Но есть свои особенности налогооблажения, для которых собственно и пилят.
G>>>>Смотрю самсунг — http://hh.ru/search/vacancy?no_magic=true&text=Samsung&clusters=true&search_field=company_name&area=1&specialization=1.221&from=cluster_specialization G>>>>Java\Android через одну. Много разработок драйверов, там по понятным причинам managed платформ нету. Да и чето не сильно похоже на "коробочные продукты" сервисы всякие в основном.
V>>>hh.ru??? V>>>Ты издеваешься? А на сам Самсунг зайти не судьба? G>>Кинь ссылку, мне искать лень.
V>Просто потрать квант своей внимательности на эти ссылки. Не по диагонали. Не отмахиваясь, как от назойливой мухи.
И? Где реальные вакансии? Чтобы можно было откликнуться.
V>Ты еще относительно молод. У тебя всё еще может сложится по-другому.
За меня не переживай. Я за работу беру по $100\час, при этом работаю когда мне захочется.
Здравствуйте, QrystaL, Вы писали:
QL>Здравствуйте, Dair, Вы писали: D>>в Django/RoR накладываются довольно жёсткие ограничения даже на именование таблиц в БД
QL>Ну это проблемы реализации Django/RoR В .NET с этим всё порядке.
Ну, хорошо. Как написать вот такой запрос на ОРМ.NET?
Это реальный запрос и, наверно, самый сложный, который я реально применяю.
select count(e.id), l.id, l.name from location l left outer join event e on (e.cr_date >= now() - '#{sanitize(period)}h'::interval and e.location_id = l.id) group by l.id order by l.id asc
Фрагмент "e.cr_date >= now() — '#{sanitize(period)}h'::interval" означает "за последние period часов".
Здравствуйте, Dair, Вы писали:
D>Здравствуйте, QrystaL, Вы писали: D>Ну, хорошо. Как написать вот такой запрос на ОРМ.NET?
Что такое ОРМ.NET? Любой ORM под дотнет?
D>Это реальный запрос и, наверно, самый сложный, который я реально применяю.
D>
select count(e.id), l.id, l.name from location l left outer join event e on (e.cr_date >= now() - '#{sanitize(period)}h'::interval and e.location_id = l.id) group by l.id order by l.id asc
D>Фрагмент "e.cr_date >= now() — '#{sanitize(period)}h'::interval" означает "за последние period часов".
Оно точно рабочее? Потому что известные мне сервера скажут, что l.name отсутствует в group by.
D>>Ну, хорошо. Как написать вот такой запрос на ОРМ.NET? НС>Что такое ОРМ.NET? Любой ORM под дотнет?
Я ни одним не владею, поэтому да, любой. Мне для примера понять, как оно будет выглядеть.
D>>Это реальный запрос и, наверно, самый сложный, который я реально применяю. D>>
select count(e.id), l.id, l.name from location l left outer join event e on (e.cr_date >= now() - '#{sanitize(period)}h'::interval and e.location_id = l.id) group by l.id order by l.id asc
D>>Фрагмент "e.cr_date >= now() — '#{sanitize(period)}h'::interval" означает "за последние period часов".
НС>Оно точно рабочее? Потому что известные мне сервера скажут, что l.name отсутствует в group by.
у меня на PostgreSQL 9.1 вполне работает, это copy&paste из рабочего проекта.
Таблица event содержит события, таблица location — места этих событий, связка event->location "много к одному". Запрос возвращает кол-во событий по локациям за указанное кол-во часов он настоящего времени. Для тех локаций, в которых событий не было — 0, для этого, собсно, outer join.
Здравствуйте, Dair, Вы писали:
D>Я ни одним не владею, поэтому да, любой. Мне для примера понять, как оно будет выглядеть.
Да примерно так же и будет:
from loc in db.Locations
from evt in loc.Events
where evt.CrDate > DateTime.Now - TimeSpan.FromHours(period)
order by loc.Id
group loc by new {loc.Id, loc.Name} into g
select new {g.Key.Id, g.Key.Name, g.Count()};
НС>>Оно точно рабочее? Потому что известные мне сервера скажут, что l.name отсутствует в group by.
D> у меня на PostgreSQL 9.1 вполне работает, это copy&paste из рабочего проекта.
И что в name попадает? Первое попавшееся значение из группы?
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>>Оно точно рабочее? Потому что известные мне сервера скажут, что l.name отсутствует в group by.
D>> у меня на PostgreSQL 9.1 вполне работает, это copy&paste из рабочего проекта.
НС>И что в name попадает? Первое попавшееся значение из группы?
Так как задана группировка по первичному ключу location, то группировка i.id даст тот же результат, что и (l.id, l.name).
Здравствуйте, A-Myth, Вы писали:
AM>К чему этот вопрос: мне сейчас надо накидать прототип, который возможно перерастёт в большой проект (а возможно и нет). Нужен ORM. Хотелось бы, конечно, плюшек в виде lazy loading и change tracking (т.к. неизвестно куда потом требования угуляют), но и без них можно обойтись. AM>Так же важен момент быстрого вхождения средних (не совсем бестолковых, но и не "10x") разработчиков. AM>Хотелось бы надёжную штуковину, которая бы 3-4 года ещё была актуальна и "в струе" дотнета. AM>База планируется средней нагруженности — будут блобы, файлы-документы, сотни пользователей, планировщики и т.д. AM>Что бы мне такое выбрать, чтобы не очень промахнуться?
Не очень понимаю где будет проблема. Если код ORM полностью скрыт от остальной программы за слоем репозиториев (тут важное уточнение: многие под репозиториями понимают почему-то шлюзы к таблицам), то сменить его будет просто или вообще использовать SQL и ADO.NET.
На практике, увы, люди таскают классы-маппинги ORM (хоть POCO, хоть нет) по всей системе, пытаются вывернуть ORM наизнанку, заставляя внешний код вникать в детали того, как эта конкретная ORM работает. Сам так делал пока не вырос. В результате, их код очень цепко связан с конкретной ORM.
Здравствуйте, Vladek, Вы писали:
V>Сам так делал пока не вырос. В результате, их код очень цепко связан с конкретной ORM.
Сейчас, в принципе, ни одна ORM не доросла до уровня, который позволит абстрагироваться от ее специфики. Так что попытка такую абстракцию ввести — классический случай leaky abstraction со всеми вытекающими.
Здравствуйте, Vladek, Вы писали:
V>Здравствуйте, A-Myth, Вы писали:
AM>>К чему этот вопрос: мне сейчас надо накидать прототип, который возможно перерастёт в большой проект (а возможно и нет). Нужен ORM. Хотелось бы, конечно, плюшек в виде lazy loading и change tracking (т.к. неизвестно куда потом требования угуляют), но и без них можно обойтись. AM>>Так же важен момент быстрого вхождения средних (не совсем бестолковых, но и не "10x") разработчиков. AM>>Хотелось бы надёжную штуковину, которая бы 3-4 года ещё была актуальна и "в струе" дотнета. AM>>База планируется средней нагруженности — будут блобы, файлы-документы, сотни пользователей, планировщики и т.д. AM>>Что бы мне такое выбрать, чтобы не очень промахнуться?
V>Не очень понимаю где будет проблема. Если код ORM полностью скрыт от остальной программы за слоем репозиториев (тут важное уточнение: многие под репозиториями понимают почему-то шлюзы к таблицам), то сменить его будет просто или вообще использовать SQL и ADO.NET.
V>На практике, увы, люди таскают классы-маппинги ORM (хоть POCO, хоть нет) по всей системе, пытаются вывернуть ORM наизнанку, заставляя внешний код вникать в детали того, как эта конкретная ORM работает. Сам так делал пока не вырос. В результате, их код очень цепко связан с конкретной ORM.
Приведи пример такого кода.
Для начала простой кейс как в StackOverflow:
1) Показывать посты по дате добавления
2) Показывать посты по количеству оценок за день (самые популярные)
3) Показывать посты по комментов за день (самые обсуждаемые)
Еще обязательно пейджинг.
Я предполагаю что получится такой набор методов в репозитариях:
IEnumerable<PostData> GetPostsByDate(int start, int pageSize);
IEnumerable<PostData> GetPostsByComments(int start, int pageSize);
IEnumerable<PostData> GetPostsByScore(int start, int pageSize);
Потом внезапно требуется сделать фильтр по тегам, придется править все три метода. В итоге у нас "нижние" слои приложения страдают от изменений деталей представления. Значит расслоение сделано неверно.
В сценарии интернет-магазина или CRM может быть куча фильтров и сортировок и таких методов в репозитарии будет очень много. Поэтому цена изменения станет огромной.
Здравствуйте, gandjustas, Вы писали: G>Приведи пример такого кода. G>Для начала простой кейс как в StackOverflow: G>1) Показывать посты по дате добавления G>2) Показывать посты по количеству оценок за день (самые популярные) G>3) Показывать посты по комментов за день (самые обсуждаемые) G>Еще обязательно пейджинг. G>Я предполагаю что получится такой набор методов в репозитариях: G>
G>IEnumerable<PostData> GetPostsByDate(int start, int pageSize);
G>IEnumerable<PostData> GetPostsByComments(int start, int pageSize);
G>IEnumerable<PostData> GetPostsByScore(int start, int pageSize);
G>
Я в репозиторий передаю наследников такого класса:
DataFetch.cs
public class DataFetch
{
public static readonly int[] AvailablePageSizes = new[] { 10, 20, 50, 100 };
private int? pageSize;
public DataFetch()
{
this.PageSize = NormalizePageSize(null);
}
public bool? Ascending { get; set; }
public int Page { get; set; }
public int? PageSize
{
get
{
return this.pageSize;
}
set
{
this.pageSize = NormalizePageSize(value);
}
}
public bool? Reset { get; set; }
public string SortBy { get; set; }
private static int NormalizePageSize(int? pageSize)
{
if (pageSize == null)
return AvailablePageSizes.Min();
return AvailablePageSizes.Aggregate((x, y) => Math.Abs(x - pageSize.Value) < Math.Abs(y - pageSize.Value) ? x : y);
}
}
G>Потом внезапно требуется сделать фильтр по тегам, придется править все три метода. В итоге у нас "нижние" слои приложения страдают от изменений деталей представления. Значит расслоение сделано неверно. G>В сценарии интернет-магазина или CRM может быть куча фильтров и сортировок и таких методов в репозитарии будет очень много. Поэтому цена изменения станет огромной.
При изменении требований я добавляю поля в наследника (PostFetch) и изменяю реализацию метода GetPosts в репозитории (в единственном экземпляре).
Здравствуйте, A-Myth, Вы писали:
AM>А вот с change tracking была история. В одном приложении с развесистым UI внезапно понадобился глобальный undo/redo.
Для этой функциональности нужен не change tracking, а реализация IEditableObject. Это делается элементарно, добавлением в T4 модели данных слудующей строчки:
<#@ include file="..\..\Templates\EditableObject.ttinclude" #>
А добавлением следующей строчки реализуется INotifyPropertyChanged для всех объектов модели:
<#@ include file="..\..\Templates\NotifyPropertyChanged.ttinclude" #>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Vladek, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>Я предполагаю что получится такой набор методов в репозитариях:
G>>
G>>IEnumerable<PostData> GetPostsByDate(int start, int pageSize);
G>>IEnumerable<PostData> GetPostsByComments(int start, int pageSize);
G>>IEnumerable<PostData> GetPostsByScore(int start, int pageSize);
G>>
V>Я в репозиторий передаю наследников такого класса:
V>DataFetch.cs V>
V>public class DataFetch
V>{
V> //Skipped
V>}
Поздравляю, вы изобрели свой IQueryable<T>, только гораздо более слабый и неудобный в использовании.
Например текстовое поле SortBy как будет работать? Там же нужно считать агрегаты по связанным таблицам, поэтому просто передать Sort в ORDER BY не выйдет. В зависимости от значения Sort надо будет генерировать разные запросы, а это не решает исходную проблему. При добавлении сценария UI — надо править репозиторий, только вы скрыли проблему из интерфейса репозиториев и спрятали её в реализацию.
Также со временем ваш DataFetch распухнет, что его надежно использовать станет сложно.
Предположим в том же кейсе понадобилось добавить фильтр по тегам для трех описанных выше выборок, а также добавился ее один экран, где надо показывать посты текущего пользователя (без фильтра по тегам).
Вы сделаете два разных DataFetch или будете кидать эксепшн на некорректном сочетании параметров?
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, Vladek, Вы писали:
V>>Сам так делал пока не вырос. В результате, их код очень цепко связан с конкретной ORM.
НС>Сейчас, в принципе, ни одна ORM не доросла до уровня, который позволит абстрагироваться от ее специфики. Так что попытка такую абстракцию ввести — классический случай leaky abstraction со всеми вытекающими.
Дело не в конкретных ORM, а в том как они используются.
SQL очень выразительный язык, гораздо выразительнее любого мейнстримного языка, Linq создавался как раз чтобы не сильно отставать по выразительности от SQL.
Попытка абстрагироваться от ORM с Linq это обычно создание классов с RPC-style интрфейсом, иногда со своим набором классов-спецификаций, которые на два порядка менее выразительны, чем Linq. Естественно такое абстрагирование приводит к распуханию кода, падению производительности и уменьшению мощности системы. А для потребителя эта абстракция не дает ничего хорошего.
Здравствуйте, gandjustas, Вы писали:
G>Поздравляю, вы изобрели свой IQueryable<T>, только гораздо более слабый и неудобный в использовании.
Я его инкапсулировал.
G>Например текстовое поле SortBy как будет работать? Там же нужно считать агрегаты по связанным таблицам, поэтому просто передать Sort в ORDER BY не выйдет. В зависимости от значения Sort надо будет генерировать разные запросы, а это не решает исходную проблему. При добавлении сценария UI — надо править репозиторий, только вы скрыли проблему из интерфейса репозиториев и спрятали её в реализацию.
У меня сортировка по одному полю, поэтому этого SortBy мне достаточно. Если сортировка будет более сложной, то вместо текстовой строки я буду передавать что-то другое — зависит от условий задачи. А уж что там генерируется или делается за кулисами по этим полям, будет скрыто от внешнего мира.
G>Также со временем ваш DataFetch распухнет, что его надежно использовать станет сложно.
Любой код распухнет при бесконечном изменении и расширении требований, в реальности новые требования перестают рано или поздно поступать или наступает дедлайн.
G>Предположим в том же кейсе понадобилось добавить фильтр по тегам для трех описанных выше выборок, а также добавился ее один экран, где надо показывать посты текущего пользователя (без фильтра по тегам). G>Вы сделаете два разных DataFetch или будете кидать эксепшн на некорректном сочетании параметров?
В данном случае, теги и авторство вполне сочетаются. А если параметры точно не будут сочетаться, то тогда сделаю два разных класса.
Здравствуйте, Vladek, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>Поздравляю, вы изобрели свой IQueryable<T>, только гораздо более слабый и неудобный в использовании.
V>Я его инкапсулировал.
Нет, DataFetch делает ровно тоже, что и методы OrderBy, Top, Skip, при этом не дает никаких гарантий что Top и Skip применяются при наличии OrderBy.
Инкапсуляция, которая не дает дополнительных гарантий потребителю не нужна от слова вообще.
G>>Например текстовое поле SortBy как будет работать? Там же нужно считать агрегаты по связанным таблицам, поэтому просто передать Sort в ORDER BY не выйдет. В зависимости от значения Sort надо будет генерировать разные запросы, а это не решает исходную проблему. При добавлении сценария UI — надо править репозиторий, только вы скрыли проблему из интерфейса репозиториев и спрятали её в реализацию.
V>У меня сортировка по одному полю, поэтому этого SortBy мне достаточно. Если сортировка будет более сложной, то вместо текстовой строки я буду передавать что-то другое — зависит от условий задачи. А уж что там генерируется или делается за кулисами по этим полям, будет скрыто от внешнего мира.
Тогда возвращаемся к кейсу:
1) Показывать посты по дате добавления
2) Показывать посты по количеству оценок за день (самые популярные)
3) Показывать посты по комментов за день (самые обсуждаемые)
Во втором и третьем случае надо сделать join и посчитать реальное количество комментов\оценок за день. Обойтись SortBy по одному полю не выйдет.
Как в этом случае сделать репозитарии?
Кстати текстовый SortBy гораздо хуже лямбды в OrderBy.
G>>Также со временем ваш DataFetch распухнет, что его надежно использовать станет сложно. V>Любой код распухнет при бесконечном изменении и расширении требований, в реальности новые требования перестают рано или поздно поступать или наступает дедлайн.
У вас распухнет в двух местах: появится много классов DataFetch или в него добавится неприлично много методов, а также распухнет обработчик этого монструозного класса(ов) DataFetch.
Если напрямую писать Linq и использовать комбинаторы, то распухать будет только в одном месте.
G>>Предположим в том же кейсе понадобилось добавить фильтр по тегам для трех описанных выше выборок, а также добавился ее один экран, где надо показывать посты текущего пользователя (без фильтра по тегам). G>>Вы сделаете два разных DataFetch или будете кидать эксепшн на некорректном сочетании параметров?
V>В данном случае, теги и авторство вполне сочетаются. А если параметры точно не будут сочетаться, то тогда сделаю два разных класса.
В данном случае не сочетаются. По условиям задачи. Даже если эти условия вам не нарвятся легко придумать правдоподобные условия задачи, где будут две независимые выборки, и объединить их параметры в один DataFetch не выйдет.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Vladek, Вы писали:
V>>Здравствуйте, gandjustas, Вы писали:
G>>>Поздравляю, вы изобрели свой IQueryable<T>, только гораздо более слабый и неудобный в использовании.
V>>Я его инкапсулировал.
G>Нет, DataFetch делает ровно тоже, что и методы OrderBy, Top, Skip, при этом не дает никаких гарантий что Top и Skip применяются при наличии OrderBy. G>Инкапсуляция, которая не дает дополнительных гарантий потребителю не нужна от слова вообще.
Это выворачивание деталей реализации наизнанку. Не нужна вам инкапсуляция, не пользуйтесь. Мне нужна гарантия, что репозиторий делает то, что нужно и ничего меньше или больше, поэтому наружу торчит куцый DataFetch.
G>>>Например текстовое поле SortBy как будет работать? Там же нужно считать агрегаты по связанным таблицам, поэтому просто передать Sort в ORDER BY не выйдет. В зависимости от значения Sort надо будет генерировать разные запросы, а это не решает исходную проблему. При добавлении сценария UI — надо править репозиторий, только вы скрыли проблему из интерфейса репозиториев и спрятали её в реализацию.
V>>У меня сортировка по одному полю, поэтому этого SortBy мне достаточно. Если сортировка будет более сложной, то вместо текстовой строки я буду передавать что-то другое — зависит от условий задачи. А уж что там генерируется или делается за кулисами по этим полям, будет скрыто от внешнего мира.
G>Тогда возвращаемся к кейсу: G>1) Показывать посты по дате добавления G>2) Показывать посты по количеству оценок за день (самые популярные) G>3) Показывать посты по комментов за день (самые обсуждаемые)
G>Во втором и третьем случае надо сделать join и посчитать реальное количество комментов\оценок за день. Обойтись SortBy по одному полю не выйдет. G>Как в этом случае сделать репозитарии? G>Кстати текстовый SortBy гораздо хуже лямбды в OrderBy.
Что такое лямбды, джойны и OrderBy? Зачем вам, пользователю репозитория, об этом знать? Может там все посты в обычном текстовом файле хранятся.
Сделаю поле вот такого типа и уже потом буду размышлять как это реализовать — через лямбды или строки.
public enum PostSortingMethod
{
Recent,
HighlyRated,
Flames
}
G>>>Также со временем ваш DataFetch распухнет, что его надежно использовать станет сложно. V>>Любой код распухнет при бесконечном изменении и расширении требований, в реальности новые требования перестают рано или поздно поступать или наступает дедлайн. G>У вас распухнет в двух местах: появится много классов DataFetch или в него добавится неприлично много методов, а также распухнет обработчик этого монструозного класса(ов) DataFetch. G>Если напрямую писать Linq и использовать комбинаторы, то распухать будет только в одном месте.
В том-то и дело, что у меня Linq написан только внутри репозиториев. Чистый и конкретный, без моих лишних велосипедов и абстракций. Наследники DataFetch предназначены для передачи параметров, методов у них нет. Много классов я не боюсь, причём через некоторое время начинаешь замечать их похожесть и объединяешь их.
G>>>Предположим в том же кейсе понадобилось добавить фильтр по тегам для трех описанных выше выборок, а также добавился ее один экран, где надо показывать посты текущего пользователя (без фильтра по тегам). G>>>Вы сделаете два разных DataFetch или будете кидать эксепшн на некорректном сочетании параметров?
V>>В данном случае, теги и авторство вполне сочетаются. А если параметры точно не будут сочетаться, то тогда сделаю два разных класса. G>В данном случае не сочетаются. По условиям задачи. Даже если эти условия вам не нарвятся легко придумать правдоподобные условия задачи, где будут две независимые выборки, и объединить их параметры в один DataFetch не выйдет.
Ну значит будут отдельные классы входящих параметров для особых случаев, ничего страшного.
Здравствуйте, Vladek, Вы писали:
G>>>>Например текстовое поле SortBy как будет работать? Там же нужно считать агрегаты по связанным таблицам, поэтому просто передать Sort в ORDER BY не выйдет. В зависимости от значения Sort надо будет генерировать разные запросы, а это не решает исходную проблему. При добавлении сценария UI — надо править репозиторий, только вы скрыли проблему из интерфейса репозиториев и спрятали её в реализацию.
V>>>У меня сортировка по одному полю, поэтому этого SortBy мне достаточно. Если сортировка будет более сложной, то вместо текстовой строки я буду передавать что-то другое — зависит от условий задачи. А уж что там генерируется или делается за кулисами по этим полям, будет скрыто от внешнего мира.
G>>Тогда возвращаемся к кейсу: G>>1) Показывать посты по дате добавления G>>2) Показывать посты по количеству оценок за день (самые популярные) G>>3) Показывать посты по комментов за день (самые обсуждаемые)
G>>Во втором и третьем случае надо сделать join и посчитать реальное количество комментов\оценок за день. Обойтись SortBy по одному полю не выйдет. G>>Как в этом случае сделать репозитарии? G>>Кстати текстовый SortBy гораздо хуже лямбды в OrderBy.
V>Что такое лямбды, джойны и OrderBy? Зачем вам, пользователю репозитория, об этом знать? Может там все посты в обычном текстовом файле хранятся.
Почему репозиторий определяет что я должен знать?
Я хочу задавать сортировку так, чтобы при переименовании поля код ругался. Лямбды для этого хорошо подходят, а linq идеально. Строки тут в жопе.
V>Сделаю поле вот такого типа и уже потом буду размышлять как это реализовать — через лямбды или строки.
V>
То есть будет количество членов в enum по количеству разных выборок, а внутри будет большой swith. Это полностью аналогично разным методам. Более того разные методы даже удобнее, ибо списки параметров есть. А DataFetch позволяет легко не указать то, что надо.
Здравствуйте, gandjustas, Вы писали:
V>>Что такое лямбды, джойны и OrderBy? Зачем вам, пользователю репозитория, об этом знать? Может там все посты в обычном текстовом файле хранятся. G>Почему репозиторий определяет что я должен знать? G>Я хочу задавать сортировку так, чтобы при переименовании поля код ругался. Лямбды для этого хорошо подходят, а linq идеально. Строки тут в жопе.
Это зона ответственности репозитория, а снаружи ничего не известно и потому одну реализацию легко заменить на другую. Вместо строк можно использовать другие объекты, никаких ограничивающих правил нет.
V>>Сделаю поле вот такого типа и уже потом буду размышлять как это реализовать — через лямбды или строки.
V>>
G>То есть будет количество членов в enum по количеству разных выборок, а внутри будет большой swith. Это полностью аналогично разным методам. Более того разные методы даже удобнее, ибо списки параметров есть. А DataFetch позволяет легко не указать то, что надо.
Тогда сортировка просто не будет работать как надо, программист быстро укажет то, что нужно, и всё заработает.
Здравствуйте, Vladek, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Что такое лямбды, джойны и OrderBy? Зачем вам, пользователю репозитория, об этом знать? Может там все посты в обычном текстовом файле хранятся. G>>Почему репозиторий определяет что я должен знать? G>>Я хочу задавать сортировку так, чтобы при переименовании поля код ругался. Лямбды для этого хорошо подходят, а linq идеально. Строки тут в жопе.
V>Это зона ответственности репозитория, а снаружи ничего не известно и потому одну реализацию легко заменить на другую.
Это в теории.
А на практике разберем пример, что все посты хранятся в текстовом файле. Для простоты будем считать, что все оценки и комменты также хранятся вместе с постами (чтобы согласованность изменений была).
И вот нам надо получить самые популярные посты за день. Для этого надо "всего лишь" пробежать по всем постам и посчитать оценку за день. Когда постов станет пару тысяч это перестанет работать.
Чтобы оно работало надо будет написать фоновый процесс, который при добавлении оценки будет считать оценку за день и обновлять список лучших постов.
Замена репозитария будет настолько маленькой проблемой, что её в этом контексте можно не рассматривать.
Получается для того, чтобы "одну реализацию легко заменить на другую" нужно чтобы все стореджи поддерживали как минимум SQL, а это значит что они будут поддерживать Linq.
Тогда зачем прятать Linq внутри репозитария, если можно IQueryable<T> отдать потребителю, а специфичные вещи спрятать в комбинаторы.
V>Вместо строк можно использовать другие объекты, никаких ограничивающих правил нет.
Какие например? Ну чтобы получить тот же уровень контроля компилятором, как в случае Linq.
G>>То есть будет количество членов в enum по количеству разных выборок, а внутри будет большой swith. Это полностью аналогично разным методам. Более того разные методы даже удобнее, ибо списки параметров есть. А DataFetch позволяет легко не указать то, что надо.
V>Тогда сортировка просто не будет работать как надо, программист быстро укажет то, что нужно, и всё заработает.
Программист может и не заметить. И тестер может не заметить. Ты же понимаешь что это хуже, чем проверка компилятором, что все параметры переданы.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Да примерно так же и будет: НС>
НС>from loc in db.Locations
НС>from evt in loc.Events
НС>where evt.CrDate > DateTime.Now - TimeSpan.FromHours(period)
НС>order by loc.Id
НС>group loc by new {loc.Id, loc.Name} into g
НС>select new {g.Key.Id, g.Key.Name, g.Count()};
НС>
О, мне тут ответов понаписали, а я и не видел
НС>SQL, надеюсь, понимаешь?
Да, довольно неплохо.
НС>
НС>SELECT TOP 1
НС> f.ForumShortName, m.CreatedOn, m.Subject, a.Origin, mt.Text
НС>FROM Messages m
НС> JOIN Forums f ON f.ID = m.ForumID
НС> OUTER JOIN Accounts a ON a.ID = m.AccountID
НС> JOIN MessageTexts mt ON mt.ID = m.ID
НС>WHERE m.ID = @id AND f.ReadLevel <= @accessLevel
НС>
Запрос понятен, да.
НС>Приведенный код открывает коннект к БД, выполняет этот sql с передачей значений двух параметров, читает результат. Если записей нет — возвращает null, если есть — создает и заполняет данными экземпляр класса MessageModel (при этом вызывается функция FormatMessageBody с частью полей результата) и возвращает этот экземпляр. При этом все типы в запросе, его параметрах и результате контролируются комспилятором. НС>Теперь понятно?
Спасибо.
Да, всё понятно, кроме одного момента — что именно и как контролирует компилятор?
Здравствуйте, gandjustas, Вы писали:
НС>>Сейчас, в принципе, ни одна ORM не доросла до уровня, который позволит абстрагироваться от ее специфики. Так что попытка такую абстракцию ввести — классический случай leaky abstraction со всеми вытекающими.
G>Дело не в конкретных ORM
Конечно не в конкретных. Потому что ровно 100% ORM не способны полностью спрятать детали реализации. Причем с тяжелыми ORM вообще сразу все понятно. Из легковесных linq2db продвинулась дальше всего, но и там такое море специфики, что о полной абстракции не приходится даже мечтать. Итого, нетекущая абстракция сейчас возможна только на уровне самых простых запросов с явными джойнами.
G>SQL очень выразительный язык, гораздо выразительнее любого мейнстримного языка,
Чего? Я тебе как садовод могу сказать, что даже та выразительность, что дает expression tree в шарпе на голову выше, чем выразительность SQL. Потому что постоянно приходится сталкиваться с ситуацией, когда тривиальное выражение на linq невозможно или очень сложно оттранслировать в SQL. Банальный group by порой таких жестких приседаний на sql требует, что в пору застрелиться.
G> Linq создавался как раз чтобы не сильно отставать по выразительности от SQL.
Здравствуйте, Vladek, Вы писали:
V>Я в репозиторий передаю наследников такого класса:
Куда интереснее что ты делаешь, когда в одном месте нужны посты с рейтингом, а в другом без, или в одном месте достаточно имени автора, а в другом потребно пяток полей из его профиля?
Здравствуйте, Vladek, Вы писали:
V>Что такое лямбды, джойны и OrderBy? Зачем вам, пользователю репозитория, об этом знать? Может там все посты в обычном текстовом файле хранятся.
Ну и как, хоть раз приходилось доставать данные, которые раньше доставались из БД, из текстового файла?
V>
Т.е., получаем, на каждый запрос я создаю отдельный метод выборки, который будет использоваться ровно в одном месте? Ну и ради чего? Чтобы когда нибудь БД заменить на текстовый файл?
Здравствуйте, gandjustas, Вы писали:
V>>Это зона ответственности репозитория, а снаружи ничего не известно и потому одну реализацию легко заменить на другую. G>Это в теории.
G>А на практике разберем пример, что все посты хранятся в текстовом файле. Для простоты будем считать, что все оценки и комменты также хранятся вместе с постами (чтобы согласованность изменений была). G>И вот нам надо получить самые популярные посты за день. Для этого надо "всего лишь" пробежать по всем постам и посчитать оценку за день. Когда постов станет пару тысяч это перестанет работать. G>Чтобы оно работало надо будет написать фоновый процесс, который при добавлении оценки будет считать оценку за день и обновлять список лучших постов.
Нет, надо выбросить код с текстовыми файлами и написать код, работающий с БД.
G>Замена репозитария будет настолько маленькой проблемой, что её в этом контексте можно не рассматривать.
Что изменится в контракте репозитория? Правильно, ничего.
G>Получается для того, чтобы "одну реализацию легко заменить на другую" нужно чтобы все стореджи поддерживали как минимум SQL, а это значит что они будут поддерживать Linq. G>Тогда зачем прятать Linq внутри репозитария, если можно IQueryable<T> отдать потребителю, а специфичные вещи спрятать в комбинаторы.
Потому что внешний мир обходится IEnumerable, отфильтрованным, отсортированным и порезанным на странички. ORM отдают IQueryable внешнему миру, а мы не пишем ORM, мы пишем репозиторий. Для нашего ORM весь внешний мир ограничивается репозиторием. А это значит, пользователь репозитория не имеет доступа к объектам ORM, которые маппятся из БД — нечего выдавать в качестве T для IQueryable<T>.
V>>Вместо строк можно использовать другие объекты, никаких ограничивающих правил нет. G>Какие например? Ну чтобы получить тот же уровень контроля компилятором, как в случае Linq.
PostSortingMethod.
V>>Тогда сортировка просто не будет работать как надо, программист быстро укажет то, что нужно, и всё заработает. G>Программист может и не заметить. И тестер может не заметить. Ты же понимаешь что это хуже, чем проверка компилятором, что все параметры переданы.
Ещё программить может привести IQueryable к IEnumerable, отсортировать и в цикле выбрать нужные объекты. Компилятор с радостью это скомпилирует. И оно даже будет работать быстро некоторое время.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, Vladek, Вы писали:
V>>Я в репозиторий передаю наследников такого класса:
НС>Куда интереснее что ты делаешь, когда в одном месте нужны посты с рейтингом, а в другом без, или в одном месте достаточно имени автора, а в другом потребно пяток полей из его профиля?
Просто делаю параметры выборки в виде Nullable. Тогда их можно комбинировать как угодно. На моей практике таких полей редко больше четырёх. Пользователи не очень любят заполнять формы со 100500 полями.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Т.е., получаем, на каждый запрос я создаю отдельный метод выборки, который будет использоваться ровно в одном месте? Ну и ради чего? Чтобы когда нибудь БД заменить на текстовый файл?
Чтобы код был простым и его было легко расширять и менять.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
НС>>>Сейчас, в принципе, ни одна ORM не доросла до уровня, который позволит абстрагироваться от ее специфики. Так что попытка такую абстракцию ввести — классический случай leaky abstraction со всеми вытекающими.
G>>Дело не в конкретных ORM НС>Конечно не в конкретных. Потому что ровно 100% ORM не способны полностью спрятать детали реализации. Причем с тяжелыми ORM вообще сразу все понятно. Из легковесных linq2db продвинулась дальше всего, но и там такое море специфики, что о полной абстракции не приходится даже мечтать. Итого, нетекущая абстракция сейчас возможна только на уровне самых простых запросов с явными джойнами.
Что ты понимаешь под "полной абстракциией" ? Даже если на уровне синтаксиса запросов к БД привести все к общему знаменателю, то на уровне семантики и быстродействия все равно найдутся различия. А попытка сделать объектную обертку над ОРМ ни к чему хорошему не приводит.
G>>SQL очень выразительный язык, гораздо выразительнее любого мейнстримного языка,
НС>Чего? Я тебе как садовод могу сказать, что даже та выразительность, что дает expression tree в шарпе на голову выше, чем выразительность SQL. Потому что постоянно приходится сталкиваться с ситуацией, когда тривиальное выражение на linq невозможно или очень сложно оттранслировать в SQL. Банальный group by порой таких жестких приседаний на sql требует, что в пору застрелиться.
То что можно больше написать не означает что выразительность выше. Иначе получится что самый выразительный язык это perl, в нем почти любая последовательность символов будет корректной программой.
SQL (на примере TSQL) умеет, а Linq нет:
1) CTE и рекурсию
2) ranking-функции и агрегаты с partition
3) MERGE-оператор
4) PIVOT\UNPIVOT
G>> Linq создавался как раз чтобы не сильно отставать по выразительности от SQL. НС>Это ты сам придумал?
Нет, об этом Мейер говорил. Он еще в Haskell такое изобретал.
НС>Он то расказал правильно, а вот ты понял его как то странно, судя по всему.
А ты тогда о чем говоришь?
Различия в СУБД не позволяют эффективно построить один API для любой СУБД. А Linq в этих случаях как раз и используется как генератор СУБД-специфичных запросов.
Здравствуйте, Vladek, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>Это зона ответственности репозитория, а снаружи ничего не известно и потому одну реализацию легко заменить на другую. G>>Это в теории.
G>>А на практике разберем пример, что все посты хранятся в текстовом файле. Для простоты будем считать, что все оценки и комменты также хранятся вместе с постами (чтобы согласованность изменений была). G>>И вот нам надо получить самые популярные посты за день. Для этого надо "всего лишь" пробежать по всем постам и посчитать оценку за день. Когда постов станет пару тысяч это перестанет работать. G>>Чтобы оно работало надо будет написать фоновый процесс, который при добавлении оценки будет считать оценку за день и обновлять список лучших постов.
V>Нет, надо выбросить код с текстовыми файлами и написать код, работающий с БД.
Не понял фразы. Кому надо? Куда выбросить? Вот я тебе привет пример кода, который с субд работает. Ты предположил что репозиторий поможет "одну реализацию легко заменить на другую" и сам привел пример с файлами. В результате поменять субд на файлы окажется совсем нелегко, несмотря на репозитарии.
G>>Замена репозитария будет настолько маленькой проблемой, что её в этом контексте можно не рассматривать. V>Что изменится в контракте репозитория? Правильно, ничего.
Даже если переписать весь контракт репозитария изменится 4-5 строк в методах, которые взывают этот репзитарий, по сравнению с написанием джоба по вычислению топовых постов, эти изменения не будут видны в микроскоп.
G>>Получается для того, чтобы "одну реализацию легко заменить на другую" нужно чтобы все стореджи поддерживали как минимум SQL, а это значит что они будут поддерживать Linq. G>>Тогда зачем прятать Linq внутри репозитария, если можно IQueryable<T> отдать потребителю, а специфичные вещи спрятать в комбинаторы.
V>Потому что внешний мир обходится IEnumerable, отфильтрованным, отсортированным и порезанным на странички.
Ну ок, сделай все что надо непосредственно перед отдачей во внешний мир (в рендеринг страницы). Зачем тебе репозиторий?
V>ORM отдают IQueryable внешнему миру, а мы не пишем ORM, мы пишем репозиторий. Для нашего ORM весь внешний мир ограничивается репозиторием. А это значит, пользователь репозитория не имеет доступа к объектам ORM, которые маппятся из БД — нечего выдавать в качестве T для IQueryable<T>.
И какой в этом смысл? То что оно усложняет код я уже увидел, а где положительные эффекты?
V>>>Вместо строк можно использовать другие объекты, никаких ограничивающих правил нет. G>>Какие например? Ну чтобы получить тот же уровень контроля компилятором, как в случае Linq. V>PostSortingMethod.
Что это? Пример кода приведи.
V>>>Тогда сортировка просто не будет работать как надо, программист быстро укажет то, что нужно, и всё заработает. G>>Программист может и не заметить. И тестер может не заметить. Ты же понимаешь что это хуже, чем проверка компилятором, что все параметры переданы.
V>Ещё программить может привести IQueryable к IEnumerable, отсортировать и в цикле выбрать нужные объекты. Компилятор с радостью это скомпилирует. И оно даже будет работать быстро некоторое время.
А кто мешает сделать программисту тоже самое с IEnumerable? Или ты думаешь, что если ты отдаешь IEnumerable. то никто к нему Linq применить не сможет, родив очень неэффективный код? Кстати именно поэтому имеет смысл отдавать Iqueryable, ибо тогда Linq превратится в запрос и улетит в базу, а привести к IEnumerable еще и не каждый догадается.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Vladek, Вы писали:
V>>Здравствуйте, gandjustas, Вы писали:
V>>>>Это зона ответственности репозитория, а снаружи ничего не известно и потому одну реализацию легко заменить на другую. G>>>Это в теории.
G>>>А на практике разберем пример, что все посты хранятся в текстовом файле. Для простоты будем считать, что все оценки и комменты также хранятся вместе с постами (чтобы согласованность изменений была). G>>>И вот нам надо получить самые популярные посты за день. Для этого надо "всего лишь" пробежать по всем постам и посчитать оценку за день. Когда постов станет пару тысяч это перестанет работать. G>>>Чтобы оно работало надо будет написать фоновый процесс, который при добавлении оценки будет считать оценку за день и обновлять список лучших постов.
V>>Нет, надо выбросить код с текстовыми файлами и написать код, работающий с БД.
G>Не понял фразы. Кому надо? Куда выбросить? Вот я тебе привет пример кода, который с субд работает. Ты предположил что репозиторий поможет "одну реализацию легко заменить на другую" и сам привел пример с файлами. В результате поменять субд на файлы окажется совсем нелегко, несмотря на репозитарии.
Если все детали того, как репозиторий хранит данные, скрыты, то мы можем легко сменить файлы на субд и наоборот. Даже если это будет тяжёлая работа, торгать код за пределами репозиториев нам не понадобится.
G>>>Замена репозитария будет настолько маленькой проблемой, что её в этом контексте можно не рассматривать. V>>Что изменится в контракте репозитория? Правильно, ничего. G> G>Даже если переписать весь контракт репозитария изменится 4-5 строк в методах, которые взывают этот репзитарий, по сравнению с написанием джоба по вычислению топовых постов, эти изменения не будут видны в микроскоп.
Контракт репозитория оперирует объектами из модели данных программы и они не будут затронуты изменениями в стратегии хранения данных.
G>>>Получается для того, чтобы "одну реализацию легко заменить на другую" нужно чтобы все стореджи поддерживали как минимум SQL, а это значит что они будут поддерживать Linq. G>>>Тогда зачем прятать Linq внутри репозитария, если можно IQueryable<T> отдать потребителю, а специфичные вещи спрятать в комбинаторы.
V>>Потому что внешний мир обходится IEnumerable, отфильтрованным, отсортированным и порезанным на странички. G>Ну ок, сделай все что надо непосредственно перед отдачей во внешний мир (в рендеринг страницы). Зачем тебе репозиторий?
Этим и занимается репозиторий — выборкой данных — дальше не его забота куда данные отправляются.
V>>ORM отдают IQueryable внешнему миру, а мы не пишем ORM, мы пишем репозиторий. Для нашего ORM весь внешний мир ограничивается репозиторием. А это значит, пользователь репозитория не имеет доступа к объектам ORM, которые маппятся из БД — нечего выдавать в качестве T для IQueryable<T>. G>И какой в этом смысл? То что оно усложняет код я уже увидел, а где положительные эффекты?
Код должен делать работу здесь и сейчас (для твоего работодателя и заказчика), код должен легко поддаваться изменениям и оставаться полезным (для тебя в будущем).
Положительные эффекты в разделении зон ответственности кода. Если тебе надо работать с кодом доступа к бд, ты делаешь это в одном месте и не тебе не приходится лазать по всему дереву исходников. В будущем, тебе не придётся долго искать этот код и потом читать половину проекта, чтобы внести изменения и быть уверенным, что ничего не забыто.
V>>>>Вместо строк можно использовать другие объекты, никаких ограничивающих правил нет. G>>>Какие например? Ну чтобы получить тот же уровень контроля компилятором, как в случае Linq. V>>PostSortingMethod. G>Что это? Пример кода приведи.
Был выше. Это перечисление способов сортировки постов, репозиторий их отсортирует в зависимости от заданного значения этого параметра. Да, ты можешь попробовать пилить японской пилой рельсу вместо сосны и пила обязательно сломается. Лучше всё же пилить сосну.
V>>>>Тогда сортировка просто не будет работать как надо, программист быстро укажет то, что нужно, и всё заработает. G>>>Программист может и не заметить. И тестер может не заметить. Ты же понимаешь что это хуже, чем проверка компилятором, что все параметры переданы.
V>>Ещё программить может привести IQueryable к IEnumerable, отсортировать и в цикле выбрать нужные объекты. Компилятор с радостью это скомпилирует. И оно даже будет работать быстро некоторое время. G>А кто мешает сделать программисту тоже самое с IEnumerable? Или ты думаешь, что если ты отдаешь IEnumerable. то никто к нему Linq применить не сможет, родив очень неэффективный код? Кстати именно поэтому имеет смысл отдавать Iqueryable, ибо тогда Linq превратится в запрос и улетит в базу, а привести к IEnumerable еще и не каждый догадается.
Этот IEnumerable будет содержать с десяток объектов, уже готовых для отображения пользователю. Любые манипуляции с ним не будут отличаться большими накладными расходами.
Здравствуйте, gandjustas, Вы писали:
G>Что ты понимаешь под "полной абстракциией" ?
Чтобы писать код не задумываясь о деталях реализации ORM. Сейчас таких ORM нет.
G>То что можно больше написать не означает что выразительность выше.
Как раз таки означает.
G> Иначе получится что самый выразительный язык это perl, в нем почти любая последовательность символов будет корректной программой.
Перл элементарно транслируется в банальный плоский С. Так что негодная у тебя аналогия. Проблема не в транслируемости конструкций, а в том что вполне осмысленные, нормально выглядящие и работающие на linq2objects конструкции на SQL фик переведешь.
G>SQL (на примере TSQL) умеет, а Linq нет: G>1) CTE и рекурсию
СТЕ сама по себе линку просто не нужна. А поддердка рекурсии — вопрос конкретных провайдеров, которым просто никто не занимался всерьез.
G>2) ranking-функции и агрегаты с partition
Это вообще не проблема.
G>3) MERGE-оператор
Тоже не проблема.
G>4) PIVOT\UNPIVOT
Опять же вопрос конкретного провайдера. Выразительных функций линка хватает за глаза.
При этом есть несколько моментов, которые действительно несколько фигово в линке выражаются по сравнению с сиквелом. Но ни один из них ты не упомянул.
G>>> Linq создавался как раз чтобы не сильно отставать по выразительности от SQL. НС>>Это ты сам придумал? G>Нет, об этом Мейер говорил.
Эрик? Ссылку можно? А то я немножко на эту тему с ним общался, и ничего подобного не услышал.
НС>>Он то расказал правильно, а вот ты понял его как то странно, судя по всему. G>А ты тогда о чем говоришь?
Я, кажется, вполне понятно написал. Любая ОРМ, если попытаться от нее абстрагироваться, приведет к leaky abstraction. Без вариантов. Что тебе в этом утверждении непонятно?
G>Различия в СУБД не позволяют эффективно построить один API для любой СУБД. А Linq в этих случаях как раз и используется как генератор СУБД-специфичных запросов.
Здравствуйте, Vladek, Вы писали:
НС>>Т.е., получаем, на каждый запрос я создаю отдельный метод выборки, который будет использоваться ровно в одном месте? Ну и ради чего? Чтобы когда нибудь БД заменить на текстовый файл?
V>Чтобы код был простым
То есть ты считаешь, что если вместо просто запроса будет запрос + руками описанный набор DTO + публичный интерфейс + вызов метода, то это будет более простой код?
V>и его было легко расширять и менять.
Т.е. ты считаешь, что расширять просто запрос сложнее, чем запрос + руками описанный набор DTO + публичный интерфейс + вызов метода? Сможешь аргументировать?
Здравствуйте, Vladek, Вы писали:
НС>>Куда интереснее что ты делаешь, когда в одном месте нужны посты с рейтингом, а в другом без, или в одном месте достаточно имени автора, а в другом потребно пяток полей из его профиля?
V>Просто делаю параметры выборки в виде Nullable.
Подожди, а с джойнами как? Заранее втыкиваешь ссылки и коллекции на все теоретически возможные джойны? ИМ потом таскаешь везде этот мегакласс, полагаясь на авость что никто в клиентском коде не дернет поля, в которые данные не запихнуты?
V>На моей практике таких полей редко больше четырёх.
А на моей практике и пару десятков не редкость.
V> Пользователи не очень любят заполнять формы со 100500 полями.
Далеко не всегда соотношение полей формы и полей в таблице 1 к 1.
Здравствуйте, Vladek, Вы писали:
V>Если все детали того, как репозиторий хранит данные, скрыты, то мы можем легко сменить файлы на субд и наоборот.
Повторяю вопрос — тебе хотя бы раз такое понадобилось? Мне вот, за 18 лет стажа, большая часть которого связана с БД, не понадобилось ни разу. Но если вдруг понадобится — тоже не проблема. Придется только поправить неймспейсы и перекомпилировать, чтобы ET заменилось на лямбды.
V>Положительные эффекты в разделении зон ответственности кода. Если тебе надо работать с кодом доступа к бд, ты делаешь это в одном месте и не тебе не приходится лазать по всему дереву исходников.
В случае линка код доступа в БД ты вообще не пишешь. Нигде. Ты просто декларативно описываешь, что тебе надо.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
G>>Что ты понимаешь под "полной абстракциией" ?
НС>Чтобы писать код не задумываясь о деталях реализации ORM. Сейчас таких ORM нет.
В первую очередь нужно задумываться о той СУБД, для которой пишешь. Это уже не дает возможности полностью абстрагироваться.
G>>То что можно больше написать не означает что выразительность выше. НС>Как раз таки означает.
G>> Иначе получится что самый выразительный язык это perl, в нем почти любая последовательность символов будет корректной программой. НС>Перл элементарно транслируется в банальный плоский С. Так что негодная у тебя аналогия.
Любой императивный язык транслируется в C. Даже SQL транслируется в C. Это не говорит о выразительности.
НС>Проблема не в транслируемости конструкций, а в том что вполне осмысленные, нормально выглядящие и работающие на linq2objects конструкции на SQL фик переведешь.
Обратное также верно. Если мы говорим о работе с данными в СУБД, то linq менее выразителен, чем SQL.
G>>SQL (на примере TSQL) умеет, а Linq нет: G>>1) CTE и рекурсию НС>СТЕ сама по себе линку просто не нужна. А поддердка рекурсии — вопрос конкретных провайдеров, которым просто никто не занимался всерьез.
В linq нет средств для рекурсии.
G>>2) ranking-функции и агрегаты с partition НС>Это вообще не проблема.
G>>3) MERGE-оператор НС>Тоже не проблема.
Что значит "не проблема" ?
Как можно написать в Linq простое выражения вроде:
select rank() over (partition by customerid order by orderdate desc) as r, sum() over (partition by customerid order by orderdate desc) from orders
Увы в linq таких средств нет
G>>4) PIVOT\UNPIVOT НС>Опять же вопрос конкретного провайдера. Выразительных функций линка хватает за глаза. НС>При этом есть несколько моментов, которые действительно несколько фигово в линке выражаются по сравнению с сиквелом. Но ни один из них ты не упомянул.
То что ты не видишь не значит что их нет.
G>>>> Linq создавался как раз чтобы не сильно отставать по выразительности от SQL. НС>>>Это ты сам придумал? G>>Нет, об этом Мейер говорил. НС>Эрик? Ссылку можно? А то я немножко на эту тему с ним общался, и ничего подобного не услышал.
Это очень давно было, сейчас не найду даже.
НС>>>Он то расказал правильно, а вот ты понял его как то странно, судя по всему. G>>А ты тогда о чем говоришь? НС>Я, кажется, вполне понятно написал. Любая ОРМ, если попытаться от нее абстрагироваться, приведет к leaky abstraction. Без вариантов. Что тебе в этом утверждении непонятно?
ты отвечаешь не на то, что я писал.
Я говорил что нет смысла абстрагироваться, так как приложение обычно затачивается на работу с конкретной СУБД.
Здравствуйте, Vladek, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>Здравствуйте, Vladek, Вы писали:
V>>>Здравствуйте, gandjustas, Вы писали:
V>>>>>Это зона ответственности репозитория, а снаружи ничего не известно и потому одну реализацию легко заменить на другую. G>>>>Это в теории.
G>>>>А на практике разберем пример, что все посты хранятся в текстовом файле. Для простоты будем считать, что все оценки и комменты также хранятся вместе с постами (чтобы согласованность изменений была). G>>>>И вот нам надо получить самые популярные посты за день. Для этого надо "всего лишь" пробежать по всем постам и посчитать оценку за день. Когда постов станет пару тысяч это перестанет работать. G>>>>Чтобы оно работало надо будет написать фоновый процесс, который при добавлении оценки будет считать оценку за день и обновлять список лучших постов.
V>>>Нет, надо выбросить код с текстовыми файлами и написать код, работающий с БД.
G>>Не понял фразы. Кому надо? Куда выбросить? Вот я тебе привет пример кода, который с субд работает. Ты предположил что репозиторий поможет "одну реализацию легко заменить на другую" и сам привел пример с файлами. В результате поменять субд на файлы окажется совсем нелегко, несмотря на репозитарии.
V>Если все детали того, как репозиторий хранит данные, скрыты, то мы можем легко сменить файлы на субд и наоборот. Даже если это будет тяжёлая работа, торгать код за пределами репозиториев нам не понадобится.
Файл на субд — легко, наоборот — нет. Слишком много надо написать, чтобы с помощью файлов отвечать на запросы как СУБД. То есть если ты начинаешь проект в котором будет работа с субд, то репозитарий не дает ничего.
G>>>>Замена репозитария будет настолько маленькой проблемой, что её в этом контексте можно не рассматривать. V>>>Что изменится в контракте репозитория? Правильно, ничего. G>> G>>Даже если переписать весь контракт репозитария изменится 4-5 строк в методах, которые взывают этот репзитарий, по сравнению с написанием джоба по вычислению топовых постов, эти изменения не будут видны в микроскоп.
V>Контракт репозитория оперирует объектами из модели данных программы и они не будут затронуты изменениями в стратегии хранения данных.
И что? Интересует не репозитарий, а его влияние на программу в целом. Пока что положительного влияния не было замечено.
G>>>>Получается для того, чтобы "одну реализацию легко заменить на другую" нужно чтобы все стореджи поддерживали как минимум SQL, а это значит что они будут поддерживать Linq. G>>>>Тогда зачем прятать Linq внутри репозитария, если можно IQueryable<T> отдать потребителю, а специфичные вещи спрятать в комбинаторы.
V>>>Потому что внешний мир обходится IEnumerable, отфильтрованным, отсортированным и порезанным на странички. G>>Ну ок, сделай все что надо непосредственно перед отдачей во внешний мир (в рендеринг страницы). Зачем тебе репозиторий? V>Этим и занимается репозиторий — выборкой данных — дальше не его забота куда данные отправляются.
Это не является ответом на вопрос зачем он нужен. Ты можешь миллион классов придумать, со своими функциями, но это не оправдывает их существования.
Тем более реальной выборкой данных нанимается ORM, а репозиторий только обертка, которая ничего положительного не приносит в код.
V>>>ORM отдают IQueryable внешнему миру, а мы не пишем ORM, мы пишем репозиторий. Для нашего ORM весь внешний мир ограничивается репозиторием. А это значит, пользователь репозитория не имеет доступа к объектам ORM, которые маппятся из БД — нечего выдавать в качестве T для IQueryable<T>. G>>И какой в этом смысл? То что оно усложняет код я уже увидел, а где положительные эффекты? V>Код должен делать работу здесь и сейчас (для твоего работодателя и заказчика), код должен легко поддаваться изменениям и оставаться полезным (для тебя в будущем).
И как это онсоится к репозитарию?
"Здесь и сейчас" можно добиться, написав Linq прямо в контроллере. А "легко поддаваться изменениям и оставаться полезным" можно добиться сделав комбинаторы, примерно вот так: http://gandjustas.blogspot.ru/2010/05/iqueryable-generics.html?&tpwf_mode=main
А какая польза от репозитория?
V>Положительные эффекты в разделении зон ответственности кода. Если тебе надо работать с кодом доступа к бд, ты делаешь это в одном месте и не тебе не приходится лазать по всему дереву исходников. В будущем, тебе не придётся долго искать этот код и потом читать половину проекта, чтобы внести изменения и быть уверенным, что ничего не забыто.
Весь код работы с БД находится в ORM, а запросы "в одном месте" это фантастика, потому что в каждом контроллере нужны разные запросы. Где-то нужны сортировки, где-то проекции итп. Очень редко запросы дублируются.
V>>>>>Вместо строк можно использовать другие объекты, никаких ограничивающих правил нет. G>>>>Какие например? Ну чтобы получить тот же уровень контроля компилятором, как в случае Linq. V>>>PostSortingMethod. G>>Что это? Пример кода приведи.
V>Был выше. Это перечисление способов сортировки постов, репозиторий их отсортирует в зависимости от заданного значения этого параметра.
Я уже писал, что это даже хуже разных методов. А преимуществ не вижу.
V>Да, ты можешь попробовать пилить японской пилой рельсу вместо сосны и пила обязательно сломается. Лучше всё же пилить сосну.
Доказательство по аналогии? Тут профессиональный форум, такая демагогия не катит.
V>>>>>Тогда сортировка просто не будет работать как надо, программист быстро укажет то, что нужно, и всё заработает. G>>>>Программист может и не заметить. И тестер может не заметить. Ты же понимаешь что это хуже, чем проверка компилятором, что все параметры переданы.
V>>>Ещё программить может привести IQueryable к IEnumerable, отсортировать и в цикле выбрать нужные объекты. Компилятор с радостью это скомпилирует. И оно даже будет работать быстро некоторое время. G>>А кто мешает сделать программисту тоже самое с IEnumerable? Или ты думаешь, что если ты отдаешь IEnumerable. то никто к нему Linq применить не сможет, родив очень неэффективный код? Кстати именно поэтому имеет смысл отдавать Iqueryable, ибо тогда Linq превратится в запрос и улетит в базу, а привести к IEnumerable еще и не каждый догадается.
V>Этот IEnumerable будет содержать с десяток объектов, уже готовых для отображения пользователю. Любые манипуляции с ним не будут отличаться большими накладными расходами.
А где гарантия что десятки?
Откуда репозиторий узнает что нужно для отображения пользователю?
С такими рассуждениями у тебя вся логика уедет в репозитории и методы репозиториев будут 1-в-1 повторять контроллеры. А проблемы никуда не денутся.
Здравствуйте, gandjustas, Вы писали:
НС>>Чтобы писать код не задумываясь о деталях реализации ORM. Сейчас таких ORM нет. G>В первую очередь нужно задумываться о той СУБД, для которой пишешь.
И это тоже. Но, по опыту, работать на разных СУБД все таки намного проще, чем работать на разных ORM. Первое у меня еще получалось, а вот второе — никогда. Даже переезд с blt linq на linq2db на крупных проектах совсем нетривиальная задача.
НС>>Проблема не в транслируемости конструкций, а в том что вполне осмысленные, нормально выглядящие и работающие на linq2objects конструкции на SQL фик переведешь. G>Обратное также верно.
Да не особо. Приведенные тобой примере это точно не доказывают.
НС>>СТЕ сама по себе линку просто не нужна. А поддердка рекурсии — вопрос конкретных провайдеров, которым просто никто не занимался всерьез. G>В linq нет средств для рекурсии.
Т.е. с CTE без рекурсии вопросов нет? А средства для рекурсии есть, просто их придется иначе выражать. Идея проста:
var q =
db
.SomeEntity
.With(db.SomeEntity, (e1, e2) => new {e1, e2})
.Select(...);
Но это так, мелочь. Куда интереснее другое — рекурсия в SQL в 99% случаев используется для запросов по деревьям. А запросы по деревьям на линке выражаются вообще без рекурсии, потому что линк плоской моделью не ограничен. Т.е. на линке в модели дерево можно описать сразу деревом, а рекурсивные запросы пусть строит провайдер.
G>>>3) MERGE-оператор НС>>Тоже не проблема. G>Что значит "не проблема" ?
То и значит что на линке это легко выражается, просто существующие провайдеры такое не умеют.
G>Увы в linq таких средств нет
Ты query comprehension с linq не путаешь? В QC и DML нет, а в linq провайдерах оно таки есть.
НС>>При этом есть несколько моментов, которые действительно несколько фигово в линке выражаются по сравнению с сиквелом. Но ни один из них ты не упомянул. G>То что ты не видишь не значит что их нет.
Ну так давай, рассказывай. А то тот же PIVOT/UNPIVOT, который легко описывается extension методом явно на такое не тянет.
НС>>Эрик? Ссылку можно? А то я немножко на эту тему с ним общался, и ничего подобного не услышал. G>Это очень давно было, сейчас не найду даже.
Я примерно такое и ожидал. Скорее всего ты просто неверно понял — наоборот, выразительные возможности линка больше, и это создает серьезные проблемы. Потому что люди, не искушенные в специфике провайдеров линка пишут вполне логичные запросы, которые нормально оттранслировать не выходит. Даже я, будучи в теме, изредка натыкаюсь на такое.
НС>>Я, кажется, вполне понятно написал. Любая ОРМ, если попытаться от нее абстрагироваться, приведет к leaky abstraction. Без вариантов. Что тебе в этом утверждении непонятно? G>ты отвечаешь не на то, что я писал.
Извини, но я вообще то и не тебе отвечал по поводу абстракций.
Здравствуйте, gandjustas, Вы писали:
G>Это не является ответом на вопрос зачем он нужен. Ты можешь миллион классов придумать, со своими функциями, но это не оправдывает их существования. G>Тем более реальной выборкой данных нанимается ORM, а репозиторий только обертка, которая ничего положительного не приносит в код.
Скрыть механизм хранения данных от других слоёв приложения. Репозиторий оперирует коллекциями объектов, описывающих предметную область программы. Его контракт свободен от деталей того, какая технология используется внутри него. Это позволяет писать простой код как внутри репозитория, так и снаружи его. Простой код означает, что я быстрее закончу свою работу сейчас и быстрее внесу изменения потом. Простой код — это свободное время, которое я трачу в собственное удовольствие и не думаю о неработающем коде или хитроумном баге.
G>И как это онсоится к репозитарию? G>"Здесь и сейчас" можно добиться, написав Linq прямо в контроллере. А "легко поддаваться изменениям и оставаться полезным" можно добиться сделав комбинаторы, примерно вот так: http://gandjustas.blogspot.ru/2010/05/iqueryable-generics.html?&tpwf_mode=main G>А какая польза от репозитория?
И простая читабельная реализация метода GetEntites. Без велосипеда IVisible и костыля к нему FixupVisitor. Хотя бы название метода Fix — не заставило задаться вопросом о целесообразности решения?
V>>Положительные эффекты в разделении зон ответственности кода. Если тебе надо работать с кодом доступа к бд, ты делаешь это в одном месте и не тебе не приходится лазать по всему дереву исходников. В будущем, тебе не придётся долго искать этот код и потом читать половину проекта, чтобы внести изменения и быть уверенным, что ничего не забыто. G>Весь код работы с БД находится в ORM, а запросы "в одном месте" это фантастика, потому что в каждом контроллере нужны разные запросы. Где-то нужны сортировки, где-то проекции итп. Очень редко запросы дублируются.
Их конечное количество и мы не тратим время на написание универсальных велосипедов.
V>>Этот IEnumerable будет содержать с десяток объектов, уже готовых для отображения пользователю. Любые манипуляции с ним не будут отличаться большими накладными расходами. G>А где гарантия что десятки? G>Откуда репозиторий узнает что нужно для отображения пользователю?
DataFetch.PageSize
А про пользователя репозиторий ничего не знает.
G>С такими рассуждениями у тебя вся логика уедет в репозитории и методы репозиториев будут 1-в-1 повторять контроллеры. А проблемы никуда не денутся.
Логика выборки данных для набора конкретных случаев, которые нужны в приложении. И, главное, код будет простой как доска.
Здравствуйте, gandjustas, Вы писали:
G>SQL (на примере TSQL) умеет, а Linq нет: G>1) CTE и рекурсию G>2) ranking-функции и агрегаты с partition G>3) MERGE-оператор G>4) PIVOT\UNPIVOT
Всё это реализуемо. Достаточно придумать удобную сигнатуру методов.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Т.е. ты считаешь, что расширять просто запрос сложнее, чем запрос + руками описанный набор DTO + публичный интерфейс + вызов метода? Сможешь аргументировать?
Не, не смогу. Да просто создавай контекст, там где нужно, и тут же пиши запрос данных. Работает же.
var ctx = new BlogContext();
var posts = ctx.Posts.Where(p => p.Rating == 10);
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
НС>>>Чтобы писать код не задумываясь о деталях реализации ORM. Сейчас таких ORM нет. G>>В первую очередь нужно задумываться о той СУБД, для которой пишешь.
НС>И это тоже. Но, по опыту, работать на разных СУБД все таки намного проще, чем работать на разных ORM. Первое у меня еще получалось, а вот второе — никогда. Даже переезд с blt linq на linq2db на крупных проектах совсем нетривиальная задача.
У меня опыт ровно обратный, не было проблем при переключении между Linq2SQL\EF\NHibernate, большинство запросов не меняются, разница в мелочах, которые отлично прячутся в Extension-методы. А вот когда надо было адаптировать код для SQL Server под SQLCE пришлось потрахацца.
НС>>>Проблема не в транслируемости конструкций, а в том что вполне осмысленные, нормально выглядящие и работающие на linq2objects конструкции на SQL фик переведешь. G>>Обратное также верно. НС>Да не особо. Приведенные тобой примере это точно не доказывают.
Ты везде сводишь к тому, что можно написать свои функции и потом их както мапить. Вот только с ranking function ничего хорошего не получается, увы. Особенно если надо сохранить семантику, чтобы аналогичный запрос для linq2objects работал.
НС>>>СТЕ сама по себе линку просто не нужна. А поддердка рекурсии — вопрос конкретных провайдеров, которым просто никто не занимался всерьез. G>>В linq нет средств для рекурсии.
НС>Т.е. с CTE без рекурсии вопросов нет? А средства для рекурсии есть, просто их придется иначе выражать. Идея проста:
Без рекурсии просто подставляется одно выражение в другое.
НС>Но это так, мелочь. Куда интереснее другое — рекурсия в SQL в 99% случаев используется для запросов по деревьям. А запросы по деревьям на линке выражаются вообще без рекурсии, потому что линк плоской моделью не ограничен. Т.е. на линке в модели дерево можно описать сразу деревом, а рекурсивные запросы пусть строит провайдер.
В линке нет готовых средств для обхода деревьев, все решается через кастомные комбинаторы. Но в SQL семантика рекурсии другая и парой комбинаторов не обойдешься.
G>>>>3) MERGE-оператор НС>>>Тоже не проблема. G>>Что значит "не проблема" ? НС>То и значит что на линке это легко выражается, просто существующие провайдеры такое не умеют.
Ох сомневаюсь что ты сможешь адекватно для Linq написать MERGE чтобы покрыть все возможности оператора.
G>>Увы в linq таких средств нет НС>Ты query comprehension с linq не путаешь? В QC и DML нет, а в linq провайдерах оно таки есть.
Не путаю, покажи ranking functions в любом провайдере.
НС>>>При этом есть несколько моментов, которые действительно несколько фигово в линке выражаются по сравнению с сиквелом. Но ни один из них ты не упомянул. G>>То что ты не видишь не значит что их нет. НС>Ну так давай, рассказывай. А то тот же PIVOT/UNPIVOT, который легко описывается extension методом явно на такое не тянет.
Покажи пример.
НС>>>Эрик? Ссылку можно? А то я немножко на эту тему с ним общался, и ничего подобного не услышал. G>>Это очень давно было, сейчас не найду даже.
НС>Я примерно такое и ожидал. Скорее всего ты просто неверно понял — наоборот, выразительные возможности линка больше, и это создает серьезные проблемы. Потому что люди, не искушенные в специфике провайдеров линка пишут вполне логичные запросы, которые нормально оттранслировать не выходит. Даже я, будучи в теме, изредка натыкаюсь на такое.
Ты куда-то в сторону ушел.
Вот что я говорил:
1) Мейер на Haskell создавал систему, которая позволяет код транслировать в SQL (это факт)
2) Мейер эту идею принес в C# (это он говорил, можно попробовать на Channel9 найти это видео)
3) Все пляски с Expression Trees и linq-comprehensions сделаны только для трансляции запросов в SQL. В других языках есть query comprehensions, которые гораздо лаконичнее с такой же выразительной силой.
У тебя есть возражения?
То что не любое дерево выражений можно перевести в SQL я и не спорил. Во-первых внутри ET можно написать любое выражение языка, например создание несериализуемых объектов. Во-вторых linq работает с последовательностям, а SQL с множествами, разница в семантике делает многие linq выражения бессмысленными в SQL. Но оба эих факта никаким образом не связаны с выразительной силой.
Фактически выразительная сила — возможность получить больше результатов выражений, используя меньше кода. Если мы рассматриваем работу с данными, то Linq, увы, в не дотягивает до SQL.
Здравствуйте, Vladek, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>Это не является ответом на вопрос зачем он нужен. Ты можешь миллион классов придумать, со своими функциями, но это не оправдывает их существования. G>>Тем более реальной выборкой данных нанимается ORM, а репозиторий только обертка, которая ничего положительного не приносит в код.
V>Скрыть механизм хранения данных от других слоёв приложения.
Какая от этого польза? Вред мы уже видели, а польза где?
V> Репозиторий оперирует коллекциями объектов, описывающих предметную область программы.
Этими же коллекциями оперирует все остальное приложение. Иначе model binding не будет работать.
V>Его контракт свободен от деталей того, какая технология используется внутри него. Это позволяет писать простой код как внутри репозитория, так и снаружи его. Простой код означает, что я быстрее закончу свою работу сейчас и быстрее внесу изменения потом. Простой код — это свободное время, которое я трачу в собственное удовольствие и не думаю о неработающем коде или хитроумном баге.
У тебя получается более сложный код. Потому что потребитель твоего репозитария вынужден формировать класс DataFetch, а внутри репозитария надо этот DataFetch разбирать и собирать Linq запросы. Так еще и статической проверки DataFetch нету.
Не веришь? так попробуй реализовать сценарии, которые я приводил:
1) Показывать посты по дате добавления
2) Показывать посты по количеству оценок за день (самые популярные)
3) Показывать посты по комментов за день (самые обсуждаемые)
Сравни с объемом кода, скоростью разработки и затратами на поддержку без репозитариев
G>>И как это онсоится к репозитарию? G>>"Здесь и сейчас" можно добиться, написав Linq прямо в контроллере. А "легко поддаваться изменениям и оставаться полезным" можно добиться сделав комбинаторы, примерно вот так: http://gandjustas.blogspot.ru/2010/05/iqueryable-generics.html?&tpwf_mode=main G>>А какая польза от репозитория?
V>
Я могу легко создать десятки интерфейсов-аспектов и комбинаторов к ним, а ты все поместишь в EntityFetch ? Прости, но такое решение будет неюзабельным совершенно. Да и какая гарантия в твоем коде что сущность вообще поддерживает нужный аспект? Никакой. Поэтому получаем больше ошибок и больше кода.
V>И простая читабельная реализация метода GetEntites. Без велосипеда IVisible и костыля к нему FixupVisitor. Хотя бы название метода Fix — не заставило задаться вопросом о целесообразности решения?
Ты комменты прочитай, нет необходимости в этом методе, достаточно написать T:class
V>>>Положительные эффекты в разделении зон ответственности кода. Если тебе надо работать с кодом доступа к бд, ты делаешь это в одном месте и не тебе не приходится лазать по всему дереву исходников. В будущем, тебе не придётся долго искать этот код и потом читать половину проекта, чтобы внести изменения и быть уверенным, что ничего не забыто. G>>Весь код работы с БД находится в ORM, а запросы "в одном месте" это фантастика, потому что в каждом контроллере нужны разные запросы. Где-то нужны сортировки, где-то проекции итп. Очень редко запросы дублируются.
V>Их конечное количество и мы не тратим время на написание универсальных велосипедов.
Ты выше показываешь как раз "универсальный велосипед" со своим EntityFetch.
V>>>Этот IEnumerable будет содержать с десяток объектов, уже готовых для отображения пользователю. Любые манипуляции с ним не будут отличаться большими накладными расходами. G>>А где гарантия что десятки? G>>Откуда репозиторий узнает что нужно для отображения пользователю?
V>
V>DataFetch.PageSize
V>
А проекция? как ты её задавать будешь? А нетривиальные фильтры?
V>А про пользователя репозиторий ничего не знает.
Вот в этом и проблема. Значит запросы будут гораздо менее эффективными от применения репозитариев. А польза в чем?
G>>С такими рассуждениями у тебя вся логика уедет в репозитории и методы репозиториев будут 1-в-1 повторять контроллеры. А проблемы никуда не денутся. V>Логика выборки данных для набора конкретных случаев, которые нужны в приложении. И, главное, код будет простой как доска.
Так покажи пример. Ты пока что показываешь только усложнения.
Я вообще не понимаю где будет упрощение, если у тебя внутри репозитариев такой же Linq, но параметры ты передаешь через дополнительный (!) класс EntityFetch, с которым ошибиться на порядок проще. Кода больше, ошибок больше, где "простой как доска"?
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
G>>SQL (на примере TSQL) умеет, а Linq нет: G>>1) CTE и рекурсию G>>2) ranking-функции и агрегаты с partition G>>3) MERGE-оператор G>>4) PIVOT\UNPIVOT
IT>Всё это реализуемо. Достаточно придумать удобную сигнатуру методов.
Теперь ждем ranking\agregation функции с partition в linq2db?
Здравствуйте, gandjustas, Вы писали:
IT>>Всё это реализуемо. Достаточно придумать удобную сигнатуру методов. G>Теперь ждем ranking\agregation функции с partition в linq2db?
Как выглядеть будет уже придумал?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, gandjustas, Вы писали:
IT>>>Всё это реализуемо. Достаточно придумать удобную сигнатуру методов. G>>Теперь ждем ranking\agregation функции с partition в linq2db?
IT>Как выглядеть будет уже придумал?
не-а, там сложности:
1) в order by надо как-то выражение сортировки генерировать, а в linq для этого только OrderBy\ThenBy, которые требуют IQueryable<T> на входе, а тип T будет зависть от джоинов.
2) надо как-то обыграть ROWS clause
Здравствуйте, gandjustas, Вы писали:
G>не-а, там сложности: G>1) в order by надо как-то выражение сортировки генерировать, а в linq для этого только OrderBy\ThenBy, которые требуют IQueryable<T> на входе, а тип T будет зависть от джоинов.
Это вообще не вопрос. В некоторых местах такое уже делается.
G>2) надо как-то обыграть ROWS clause
Думай
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Повторяю вопрос — тебе хотя бы раз такое понадобилось? Мне вот, за 18 лет стажа, большая часть которого связана с БД, не понадобилось ни разу. Но если вдруг понадобится — тоже не проблема. Придется только поправить неймспейсы и перекомпилировать, чтобы ET заменилось на лямбды.
Была SQL CE с Linq to SQL, а понадобилась хранить данные в ESENT. Ко второй бд провайдеры только экспериментальные.
Здравствуйте, gandjustas, Вы писали:
G>Какая от этого польза? Вред мы уже видели, а польза где?
Декомпозиция. Следование принципу "разделяй и властвуй".
G>У тебя получается более сложный код. Потому что потребитель твоего репозитария вынужден формировать класс DataFetch, а внутри репозитария надо этот DataFetch разбирать и собирать Linq запросы. Так еще и статической проверки DataFetch нету. G>Не веришь? так попробуй реализовать сценарии, которые я приводил: G>1) Показывать посты по дате добавления G>2) Показывать посты по количеству оценок за день (самые популярные) G>3) Показывать посты по комментов за день (самые обсуждаемые)
G>Сравни с объемом кода, скоростью разработки и затратами на поддержку без репозитариев
Наследник DataFetch всегда предельно конкретный, там не 100500 фильтров и метод выборки занимает полэкрана. И этот код легко читать и поддерживать.
G>Я могу легко создать десятки интерфейсов-аспектов и комбинаторов к ним, а ты все поместишь в EntityFetch ? Прости, но такое решение будет неюзабельным совершенно. Да и какая гарантия в твоем коде что сущность вообще поддерживает нужный аспект? Никакой. Поэтому получаем больше ошибок и больше кода.
Проблема в том, что тебе не нужны "десятки интерфейсов-аспектов" в твоём приложении. Ты тратишь впустую время на универсальные решения.
G>Ты комменты прочитай, нет необходимости в этом методе, достаточно написать T:class
Нет вообще никакой необходимости в этом коде, он лишний начиная с интерфейса. Код похож на подход "теперь я знаю лямбды" и соответственно всё можно описать с помощью лямбд.
G>Ты выше показываешь как раз "универсальный велосипед" со своим EntityFetch.
Он конкретный и простой, это просто набор параметров.
G>А проекция? как ты её задавать будешь? А нетривиальные фильтры?
А зачем они мне вообще? Я делаю конкретное приложение и все необходимые фильтры я уже описал, мне не требуется универсальный велосипед.
G>Вот в этом и проблема. Значит запросы будут гораздо менее эффективными от применения репозитариев. А польза в чем?
С чего такая уверенность? Запросы находятся в одном месте, их легко отлаживать и при необходимости изменить. Никаких IQueryable наружу не торчит и не надо постоянно глядеть как и где оно используется.
G>Я вообще не понимаю где будет упрощение, если у тебя внутри репозитариев такой же Linq, но параметры ты передаешь через дополнительный (!) класс EntityFetch, с которым ошибиться на порядок проще. Кода больше, ошибок больше, где "простой как доска"?
Кода меньше и он не тычит деталями реализации мне в лицо. "Эй, смотри! У нас есть IQueryable! Представь какие возможности открываются!"
Здравствуйте, Dair, Вы писали:
К>>Почему начинаете издалека? Лучше сразу к делу — зачем нужно ООП.
D>ООП я использую практически постоянно, вопросов "зачем" не возникает
Тут два варианта:
1) Вы не используете реляционные СУБД.
2) Вы преобразуете модель "ручками".
Здравствуйте, Крякозавр, Вы писали:
К>Тут два варианта: К>1) Вы не используете реляционные СУБД.
Использую. Реляции, т.е., зависимости, тоже использую. Не, мне далеко до топовых оперденей, но какие-то простые вещи делаю.
К>2) Вы преобразуете модель "ручками".
У меня когда-то был удобный инструмент — Sybase PowerDesigner. Сейчас меня жаба душит его покупать (потому как БД пишу для личных/хобби нужд), поэтому — да, "ручками", Есть файл sql, создающий базу, есть набор sql, эту базу меняющих.
Здравствуйте, Vladek, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>Какая от этого польза? Вред мы уже видели, а польза где?
V>Декомпозиция. Следование принципу "разделяй и властвуй".
Декомпозиция прекрасно делается без репозиториев и кучи классов.
G>>У тебя получается более сложный код. Потому что потребитель твоего репозитария вынужден формировать класс DataFetch, а внутри репозитария надо этот DataFetch разбирать и собирать Linq запросы. Так еще и статической проверки DataFetch нету. G>>Не веришь? так попробуй реализовать сценарии, которые я приводил: G>>1) Показывать посты по дате добавления G>>2) Показывать посты по количеству оценок за день (самые популярные) G>>3) Показывать посты по комментов за день (самые обсуждаемые)
G>>Сравни с объемом кода, скоростью разработки и затратами на поддержку без репозитариев
V>Наследник DataFetch всегда предельно конкретный, там не 100500 фильтров и метод выборки занимает полэкрана. И этот код легко читать и поддерживать.
Покажи код.
G>>Я могу легко создать десятки интерфейсов-аспектов и комбинаторов к ним, а ты все поместишь в EntityFetch ? Прости, но такое решение будет неюзабельным совершенно. Да и какая гарантия в твоем коде что сущность вообще поддерживает нужный аспект? Никакой. Поэтому получаем больше ошибок и больше кода.
V>Проблема в том, что тебе не нужны "десятки интерфейсов-аспектов" в твоём приложении. Ты тратишь впустую время на универсальные решения.
Если мне не нужны, то не трачу.
G>>Ты комменты прочитай, нет необходимости в этом методе, достаточно написать T:class V>Нет вообще никакой необходимости в этом коде, он лишний начиная с интерфейса. Код похож на подход "теперь я знаю лямбды" и соответственно всё можно описать с помощью лямбд.
С чего ты взял что нет необходимости? Как раз наоборот. Много сущностей имеют одинаковые аспекты — владение, видимость, права доступа, url slug, наличие имени итп.
Тебе придется все эти аспекты запихнуть в один EntityFetch и у тебя не будет проверки компилятором, в случае если сущность не поддерживает аспект. "Предельно конкретные наследники" EntityFetch у тебя не получатся, потому что одна сущность будет поддерживать аспекты владения и прав доступа, а вторая — наличие имени и url slug.
Интерфейсы комбинаторы выполняют тоже функцию, что и EntityFetch, только надежнее и меньше кода. Странно что ты утверждаешь что они лишние, тогда EntityFetch вообще не в тему, а его еще и руками разбирать надо *facepalm*
G>>Ты выше показываешь как раз "универсальный велосипед" со своим EntityFetch. V>Он конкретный и простой, это просто набор параметров.
Ага, не проверяемый компилятором, который надо вручную разобрать. И который со временем распухнет для неральных размеров. Даже если ты сделаешь по одному EntityFetch для каждой сущности, то проблему это не решат из-за повторяющихся аспектов у тебя появится копипаста. А если по одному EntityFetch на запрос, то это банально хуже обычных методов, потом что в методах компилятор проверяет наличие параметров.
G>>А проекция? как ты её задавать будешь? А нетривиальные фильтры? V>А зачем они мне вообще? Я делаю конкретное приложение и все необходимые фильтры я уже описал, мне не требуется универсальный велосипед.
Без проекций будет тормозить. Любой способ работы с базой без проекций не жизнеспособен на практике.
Как ты будешь проекции описывать со своим DataFetch? И какой тип ты при этом будешь возвращать из методов репозитариев?
G>>Вот в этом и проблема. Значит запросы будут гораздо менее эффективными от применения репозитариев. А польза в чем?
V>С чего такая уверенность?
Рецепт эффективного запроса — предикат с высокой селективностью и проекция. Ты пока не показал ни того, ни другого.
V>Запросы находятся в одном месте, их легко отлаживать и при необходимости изменить.
Расскажи нам кк легко отлаживать запросы, которые в одном месте? помоему для отладки запросов надо в SQL Profiler смотреть, а не в репозитарий.
Кроме того, если у тебя запросы на 50% повторяются, то ты не будешь применять декомпозицию linq, а будешь копипастить? Если будешь декомпозировать, то у тебя запросы перестанут быть в одном месте.
Попробуй напиши код репозиториев для сценариев, которые я уже раз десять озвучил. Сам все увидишь.
V>Никаких IQueryable наружу не торчит и не надо постоянно глядеть как и где оно используется.
А с чего ты взял что надо куда-то глядеть? Какие вообще проблемы могут быть?
G>>Я вообще не понимаю где будет упрощение, если у тебя внутри репозитариев такой же Linq, но параметры ты передаешь через дополнительный (!) класс EntityFetch, с которым ошибиться на порядок проще. Кода больше, ошибок больше, где "простой как доска"?
V>Кода меньше и он не тычит деталями реализации мне в лицо. "Эй, смотри! У нас есть IQueryable! Представь какие возможности открываются!"
Если ты повторяешь что кода меньше его меньше не становится. Ты уже придумал лишние классы, которые надо создавать и разбирать их в методах репозитария, с чего меньше кода станет? Наоборот, его больше получается. И с каждым твоим постом потенциальный объем кода растет, а надежность и производительность падает. Про детали реализации не понял какая проблема.
Здравствуйте, gandjustas, Вы писали:
НС>>Да не особо. Приведенные тобой примере это точно не доказывают. G>Ты везде сводишь к тому, что можно написать свои функции и потом их както мапить. Вот только с ranking function ничего хорошего не получается, увы.
Почему?
G>В линке нет готовых средств для обхода деревьев
В линке вообще нет готовых средств. Средства предоставляют конкретные провайдеры.
G>Ты куда-то в сторону ушел.
G>3) Все пляски с Expression Trees и linq-comprehensions сделаны только для трансляции запросов в SQL. В других языках есть query comprehensions, которые гораздо лаконичнее с такой же выразительной силой.
Это Мейер говорил? Ты точно в этом уверен? Потому что когда я с ним разговаривал, он говорил совсем иное.
G>У тебя есть возражения?
Не не не. Ты давай расскажи, где это Мейер рассказывал что выразительность у линка меньше, чем у SQL.
G>Во-первых внутри ET можно написать любое выражение языка, например создание несериализуемых объектов.
Это мелочь. Проблема не в этом. А вот то что легко написать GroupBy, который придется транслировать в килограмм запрросов — вот это уже конкретная проблема выразительности SQL.
G> Во-вторых linq работает с последовательностям
Это — в корне неверно. Последовательности для линка — лишь частный случай. И даже в рамках последовательностей — у линка свойство элемента последовательности легко и логично может быть последовательностью. А вот у SQL с этим совсем не все так просто.
G>, а SQL с множествами, разница в семантике делает многие linq выражения бессмысленными в SQL. Но оба эих факта никаким образом не связаны с выразительной силой.
Это ты так думаешь. А на самом деле это прямое следствие большей выразительности линка.
G>Фактически выразительная сила — возможность получить больше результатов выражений, используя меньше кода.
Угу. И уже одна возможность не писать в линке большую часть джойнов вполне себе наглядно демонстрирует, какой из языков выразительнее. А если к тому добавить убогость и громоздкость CTE по сравнению с простейшими способами декомпозиции в линке, то я вообще не понимаю как можно не видеть очевидного.
Скажи, кстати, а зачем приделали возможность писать хранимки на дотнете? Это тоже от очень большой выразительности SQL?
G> Если мы рассматриваем работу с данными, то Linq, увы, в не дотягивает до SQL.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
НС>>>Да не особо. Приведенные тобой примере это точно не доказывают. G>>Ты везде сводишь к тому, что можно написать свои функции и потом их както мапить. Вот только с ranking function ничего хорошего не получается, увы.
НС>Почему?
Потому что надо внутри select генерировать order by и ROWS clause. Это будет аццкий монстр в виде linq.
G>>В линке нет готовых средств для обхода деревьев НС>В линке вообще нет готовых средств. Средства предоставляют конкретные провайдеры.
После этого ты утверждаешь что linq выразительнее?
G>>3) Все пляски с Expression Trees и linq-comprehensions сделаны только для трансляции запросов в SQL. В других языках есть query comprehensions, которые гораздо лаконичнее с такой же выразительной силой. НС>Это Мейер говорил? Ты точно в этом уверен? Потому что когда я с ним разговаривал, он говорил совсем иное.
Нет, это по факту. С момента появления linq прошло более 5 лет, но до сих пор кроме трансляции в SQL достойных применений у ET практически нет.
G>>У тебя есть возражения? НС>Не не не. Ты давай расскажи, где это Мейер рассказывал что выразительность у линка меньше, чем у SQL.
Я не говорил что Мейер это рассказывал.
G>>Во-первых внутри ET можно написать любое выражение языка, например создание несериализуемых объектов. НС>Это мелочь. Проблема не в этом. А вот то что легко написать GroupBy, который придется транслировать в килограмм запрросов — вот это уже конкретная проблема выразительности SQL.
И ниже ты пишешь что linq не работает с последовательностями.
G>> Во-вторых linq работает с последовательностям НС>Это — в корне неверно. Последовательности для линка — лишь частный случай. И даже в рамках последовательностей — у линка свойство элемента последовательности легко и логично может быть последовательностью. А вот у SQL с этим совсем не все так просто.
Мы сейчас говорим об IQueryable<T>, который наследует IEnumerable<T>, который, внезнапно, обозначает последовательность. Так вот GroupBy, возвращает специальный вид последовательности — IGrouping, а SQL не знает о таком, у него на выходе всегда реляция (таблица). Но это совершенно не значит, что SQL обладает меньшей мощностью, он умудряется без специальных типов последовательностей реализовывать то же самое. Только для этого используются как раз ranking fucntions, которые ни один провайдер не поддерживает.
Повторяю еще раз чтобы ты понял — в Linq придуман специальный тип последовательности, когда SQL обходится несколькими дополнительными функциями.
G>>, а SQL с множествами, разница в семантике делает многие linq выражения бессмысленными в SQL. Но оба эих факта никаким образом не связаны с выразительной силой. НС>Это ты так думаешь. А на самом деле это прямое следствие большей выразительности линка.
То есть обосновать ты не можешь.
G>>Фактически выразительная сила — возможность получить больше результатов выражений, используя меньше кода.
НС>Угу. И уже одна возможность не писать в линке большую часть джойнов вполне себе наглядно демонстрирует, какой из языков выразительнее.
О да, неявное вписывание left join по ключу это конечно выразительной силы добавляет. Это наверное единственное преимущество выразительности linq перед sql.
НС>А если к тому добавить убогость и громоздкость CTE по сравнению с простейшими способами декомпозиции в линке, то я вообще не понимаю как можно не видеть очевидного.
Тем не менее CTE позволят делать рекурсивные запросы, а linq нет. И даже хорошего синтакиса для рекурсивных запросов в linq нету.
НС>Скажи, кстати, а зачем приделали возможность писать хранимки на дотнете? Это тоже от очень большой выразительности SQL?
Нет, это от неумения пользоваться SQL. Кстати крайне не рекомендуется делать CLR-хранимки для выборки данных
Здравствуйте, gandjustas, Вы писали:
НС>>Почему? G>Потому что надо внутри select генерировать order by и ROWS clause.
Это не проблема.
G> Это будет аццкий монстр в виде linq.
Не думаю.
НС>>В линке вообще нет готовых средств. Средства предоставляют конкретные провайдеры. G>После этого ты утверждаешь что linq выразительнее?
Да.
НС>>Это Мейер говорил? Ты точно в этом уверен? Потому что когда я с ним разговаривал, он говорил совсем иное. G>Нет, это по факту.
G> С момента появления linq прошло более 5 лет, но до сих пор кроме трансляции в SQL достойных применений у ET практически нет.
Тебе так кажется. Тот же МСовский клиент к odata. У полнотекстовых движков и поисковиков провайдеры бывают. У NoSQL, опять же, без этого обычно не обходится. Просто задача общения с РСУБД настолько огромная, что затмевает все остальное.
НС>>Не не не. Ты давай расскажи, где это Мейер рассказывал что выразительность у линка меньше, чем у SQL. G>Я не говорил что Мейер это рассказывал.
G>>> Linq создавался как раз чтобы не сильно отставать по выразительности от SQL.
НС>>Это ты сам придумал?
G>Нет, об этом Мейер говорил.
НС>>Это мелочь. Проблема не в этом. А вот то что легко написать GroupBy, который придется транслировать в килограмм запрросов — вот это уже конкретная проблема выразительности SQL. G>И ниже ты пишешь что linq не работает с последовательностями.
Прочти внимательнее что я пишу. Вот ключевая фраза: "Последовательности для линка — лишь частный случай."
G>Мы сейчас говорим об IQueryable<T>
С чего ты взял?
G>Так вот GroupBy, возвращает специальный вид последовательности — IGrouping,
IGrouping это не просто последовательность, это дерево.
G> а SQL не знает о таком, у него на выходе всегда реляция (таблица)
Ну вот, ты и сам все по поводу выразительности SQL понимаешь.
G>. Но это совершенно не значит, что SQL обладает меньшей мощностью
Именно это это и значит. Средства SQL не позволяют удобно работать с деревьями, даже совсем простыми.
G>, он умудряется без специальных типов последовательностей реализовывать то же самое
В том то и проблема, что не умудряется. Только совсем примитивные случаи, когда вложенная последовательность сворачивается в небольшой набор агрегатов. Если же дерево свернуть не удается, то все, приплыли, выразительность SQL закончилась.
G>, когда SQL обходится несколькими дополнительными функциями.
Ну давай, продемонстрируй выразительность SQL на простеньком запросике:
db
.Messages
.Select(
m =>
new
{
m.Id,
Rates = m.Rates.Where(r => r.MessageId = m.Id && r.Type == RateType.Positive),
Replies = db.Messages.Where(sm => sm.ParentId = m.Id)
})
НС>>Это ты так думаешь. А на самом деле это прямое следствие большей выразительности линка. G>То есть обосновать ты не можешь.
Я уже обосновал.
НС>>Угу. И уже одна возможность не писать в линке большую часть джойнов вполне себе наглядно демонстрирует, какой из языков выразительнее. G>О да, неявное вписывание left join по ключу это конечно выразительной силы добавляет.
Почему обязательно left join? И да, добавляет. Некоторые запросы сокращает в разы. Если это не выразительность, то я даже и не знаю что ты за нее принимаешь.
G> Это наверное единственное преимущество выразительности linq перед sql.
Не единственное. Но ты согласен что линк выразительнее хотя бы в этом?
НС>>А если к тому добавить убогость и громоздкость CTE по сравнению с простейшими способами декомпозиции в линке, то я вообще не понимаю как можно не видеть очевидного. G>Тем не менее CTE позволят делать рекурсивные запросы, а linq нет.
Потому что линку это ненужно.
НС>>Скажи, кстати, а зачем приделали возможность писать хранимки на дотнете? Это тоже от очень большой выразительности SQL? G>Нет, это от неумения пользоваться SQL.
НС>>>Не не не. Ты давай расскажи, где это Мейер рассказывал что выразительность у линка меньше, чем у SQL. G>>Я не говорил что Мейер это рассказывал.
НС>
G>>>> Linq создавался как раз чтобы не сильно отставать по выразительности от SQL.
НС>>>Это ты сам придумал?
G>>Нет, об этом Мейер говорил.
Ты в демагогии подкован.
То что выразительность linq меньше SQL — я сказал, а то что linq делали похожим на SQL — Мейер. Ищи на Channel в записях 2007-2009 года. Там же Мейер рассказывал что он делал на хаскеле. Сложить 1 и 1 и получить 2 ты и сам сможешь.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, gandjustas, Вы писали:
G>> С момента появления linq прошло более 5 лет, но до сих пор кроме трансляции в SQL достойных применений у ET практически нет.
НС>Тебе так кажется. Тот же МСовский клиент к odata. У полнотекстовых движков и поисковиков провайдеры бывают. У NoSQL, опять же, без этого обычно не обходится. Просто задача общения с РСУБД настолько огромная, что затмевает все остальное.
Что мне кажется? Odata использует как раз Iqueryable, который в 99,9% случаев отдается ORMом.
G>>Мы сейчас говорим об IQueryable<T> НС>С чего ты взял?
Мы говорили про ORM, это ты начал расширять тему до полной бесполезности. ORM это IQueryablr<T>
G>>Так вот GroupBy, возвращает специальный вид последовательности — IGrouping, НС>IGrouping это не просто последовательность, это дерево.
В каком месте оно дерево? Это IEnumerable+Key. Для дерева нужно как минимум иметь список дочерних элементов или ссылку на родителя.
G>> а SQL не знает о таком, у него на выходе всегда реляция (таблица) НС>Ну вот, ты и сам все по поводу выразительности SQL понимаешь.
Да, а ты не понимаешь. SQL может больше выборок описать используя меньше понятий.
G>>. Но это совершенно не значит, что SQL обладает меньшей мощностью НС>Именно это это и значит. Средства SQL не позволяют удобно работать с деревьями, даже совсем простыми.
Что ты понимаешь под "удобно работать с деревьями" ? hierarchyid это не удобно?
G>>, он умудряется без специальных типов последовательностей реализовывать то же самое НС>В том то и проблема, что не умудряется. Только совсем примитивные случаи, когда вложенная последовательность сворачивается в небольшой набор агрегатов. Если же дерево свернуть не удается, то все, приплыли, выразительность SQL закончилась.
Ты пытаешся свое незнание показать? hierarchyid не пробовал? Работа с деревьями в SQL пройдена уже столько раз, что даже лень перечислять все способы.
А то что в отсуствие навигационного доступа и кучи других понятий SQL умудряется делать более сложные выборки, конечно не говорит о его выразительности.
G>>, когда SQL обходится несколькими дополнительными функциями.
НС>Ну давай, продемонстрируй выразительность SQL на простеньком запросике: НС>
Запрос получает все сообщения с всеми положительными оценками и ответами. то есть тянешь всю таблицу ответов и все положительные оценки.
Эквивалентный SQL:
select r.* from Rates r where r.Type = 1
select r.* from Replies r
И все. message даже трогать не надо, так как m.Id есть в обоих таблицах.
Потом DataReader в dictionary мапишь и все.
НС>>>Это ты так думаешь. А на самом деле это прямое следствие большей выразительности линка. G>>То есть обосновать ты не можешь. НС>Я уже обосновал.
"Это ты так думаешь." (с)
НС>>>Угу. И уже одна возможность не писать в линке большую часть джойнов вполне себе наглядно демонстрирует, какой из языков выразительнее. G>>О да, неявное вписывание left join по ключу это конечно выразительной силы добавляет. НС>Почему обязательно left join? И да, добавляет. Некоторые запросы сокращает в разы. Если это не выразительность, то я даже и не знаю что ты за нее принимаешь.
В редких случаях inner join. Сокращает в разы по сравнению с чем? Обычно SQL код более компактный, только очень неудобный для программиста.
G>> Это наверное единственное преимущество выразительности linq перед sql. НС>Не единственное. Но ты согласен что линк выразительнее хотя бы в этом?
Только в этом. Но я уже приводил список чего linq не умеет.
НС>>>А если к тому добавить убогость и громоздкость CTE по сравнению с простейшими способами декомпозиции в линке, то я вообще не понимаю как можно не видеть очевидного. G>>Тем не менее CTE позволят делать рекурсивные запросы, а linq нет. НС>Потому что линку это ненужно. Демагогия 80 уровня.
Вижу что аргументы у тебя так и не появились.
Здравствуйте, gandjustas, Вы писали:
G>Что мне кажется? Odata использует как раз Iqueryable, который в 99,9% случаев отдается ORMом.
Это неважно откуда он отдается. Главное — это другое применение. И обрабатывается ЕТ там по другому.
НС>>С чего ты взял? G>Мы говорили про ORM, это ты начал расширять тему до полной бесполезности. ORM это IQueryablr<T>
Мы говорили про выразительность. И это просто еще один пример того, что выразительность линка неизверимо выше чем у SQL.
G>>>Так вот GroupBy, возвращает специальный вид последовательности — IGrouping, НС>>IGrouping это не просто последовательность, это дерево. G>В каком месте оно дерево? Это IEnumerable+Key.
Это IEnumerable<IEnumerable>. SQL такое не умеет.
G> Для дерева нужно как минимум иметь список дочерних элементов или ссылку на родителя.
IGrouping и есть список дочерних элементов. И в линке GroupBy может быть вложенным, с чем в SQL вообще полный швах.
НС>>Именно это это и значит. Средства SQL не позволяют удобно работать с деревьями, даже совсем простыми. G>Что ты понимаешь под "удобно работать с деревьями" ?
То и понимаю. Неудобно и многословно, с привлечением мозголомсной рекурсии.
G> hierarchyid это не удобно?
Нет.
G>Ты пытаешся свое незнание показать?
Нет, это ты, как обычно, считаешь других за дураков.
G>Запрос получает все сообщения с всеми положительными оценками и ответами. то есть тянешь всю таблицу ответов и все положительные оценки.
Это пример. Неужели не дошло.
G>Эквивалентный SQL: G>
G>select r.* from Rates r where r.Type = 1
G>select r.* from Replies r
G>
G>И все.
Не все. Ты даже внимательно на запрос посмотреть не смог. Линк запрос возвращает оценки сгруппированные по сообщениям, а твой просто простыню.
Это я еще не говорю о том, что на линке у нас одно выражение, а у тебя три, да еше и руками потом результат раскладывать надо.
G> message даже трогать не надо, так как m.Id есть в обоих таблицах.
Ты же понимаешь что это пример? Если нет — ну допиши туда еще m.Subject.
G>Потом DataReader в dictionary мапишь и все.
Ишь какой хитрый. Мы ж про выразительность, не так ли? Так вот будь добр меппинг тоже выразить на SQL.
НС>>Почему обязательно left join? И да, добавляет. Некоторые запросы сокращает в разы. Если это не выразительность, то я даже и не знаю что ты за нее принимаешь. G>В редких случаях inner join.
Почему в редких? Обычно inner намного чаще присутствует, чем outer. А если у EF с этим проблемы — это вовсе не из-за линка, а из-за кривости EF.
G> Сокращает в разы по сравнению с чем?
С явным расписыванием джойнов.
G> Обычно SQL код более компактный, только очень неудобный для программиста.
Ну давай, распиши на сиквеле компактно, сравним. Можно без джойнов.
Здравствуйте, gandjustas, Вы писали:
G>Ты в демагогии подкован.
G>То что выразительность linq меньше SQL — я сказал, а то что linq делали похожим на SQL — Мейер. Ищи на Channel в записях 2007-2009 года. Там же Мейер рассказывал что он делал на хаскеле. Сложить 1 и 1 и получить 2 ты и сам сможешь.
Тут в целом хорошо видно, кто в демагогии подкован )
"похожим" и "не сильно отставать по выразительности" — это не одно и тоже. И я тоже не помню, чтобы Мейер жаловался на выразительность linq.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, Vladek, Вы писали:
НС>>>Ничего не понял. А как же репозиторий и абстрагируемость?
V>>Ну раз они тебе за 18 лет ни разу не понадобились...
НС>То есть ответить на вопрос ты не можешь. ЧТД.
извиняюсь, что встрал.
меня интересует, в случае, когда репозиторий отдаёт IQueryable, то на чьей совести управление подключением к бд? получается, контроллер должен заниматься этим?
Здравствуйте, evilbloodydemon, Вы писали:
E>извиняюсь, что встрал. E>меня интересует, в случае, когда репозиторий отдаёт IQueryable, то на чьей совести управление подключением к бд? получается, контроллер должен заниматься этим?
Что ты понимаешь под управлением? Инициировать открытие соединения или начало транзакции, разумеется, должен контроллер. Больше просто некому. А вот непосредственно конфигурированием подключения и созданием экземпляра коннекшена должна заниматься инфраструктура.
Улыбался с каждой строчки этого твоего поста.
Могу ответить попунктно на все твои непонимания.
Опыт общения с тобой показывает, что ты можешь переваривать не более одного вопроса в единицу поста. Поэтому сначала пройдемся по WPF, Студии и Калькулятору.
V>>>>А я говорил, что ты не понимаешь нифига. Visual Studio вышла до выхода WinRT. Более того, она должна работать даже на тех версиях виндов, где WinRT не поддерживается. Более того, запуск студии в 5-15 секунд никого не волнует. Это же утилитное приложение. Вот если бы виндовый калькулятор запускался 5-15 секунд, то никто бы его не использовал. Вот почему в коробочных продуктах фактически нет WPF.
G>>>Действительно не понимаю как это связано. Похоже что связь у тебя в голове только существует.
V>>Я же сразу сказал — не понимаешь нифига. Не понимаешь, почему студия написана на WPF, а не на WinRT. Не понимаешь, почему виндовый калькулятор на WPF не написан, хотя (я уверен) будет переписан на winRT (или уже полно аналогов с аналогичным временем запуска, как у старого).
G>Я не понимаю к чему ты это пишешь. Калькулятор в W8 кстати есть в виде app на JS.
Что именно тебе не понятно из написанного? Какую строку или какое слово тебе показалось непонятным? В какой момент тебе стал непонятен ход беседы и логическая цепочка из выдвигаемых аргументов. Я не против подняться выше по ветке и пройтись более подробно в том месте, а каком стало непонятно.
Здравствуйте, vdimas, Вы писали:
G>>Я не понимаю к чему ты это пишешь. Калькулятор в W8 кстати есть в виде app на JS.
V>Что именно тебе не понятно из написанного? Какую строку или какое слово тебе показалось непонятным? В какой момент тебе стал непонятен ход беседы и логическая цепочка из выдвигаемых аргументов. Я не против подняться выше по ветке и пройтись более подробно в том месте, а каком стало непонятно.
См выделенное. Слова прекрасно понимаю, а мысль, которую ты хочешь донести, потерялась в бесконечном вранье, выдумках и бравировании знанием незначительных фактов.
We’re not trying to hide the fact that EF7 is a big change from EF6.x. We’re keeping the concepts and many of the top level APIs from past versions, but under the covers there are some big changes.