Здравствуйте, 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 в запрос, ибо без этого можно получить хреновый план. Короче проще проверить, а не гадать или "математически доказывать".