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> Есть слегка неудобный момент при написании кода.