![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
[D2010] Магия мыши в TSQLQuery + DateTimePicker [MySQL]
megavoid © (2010-12-14 20:13:00)Здравствуйте, Мастера!
Столкнулся с такой проблемой:
Есть форма, на ней stringgrid, sqlquery, datetimepicker. Юзеры выбирают дату в datetimepicker, в onChange конструируется select с нужной датой, выполняется через query, в цикле (query.next) читаю ответ от query и заполняю stringgrid нужными значениями. Всё вроде бы шоколадно, но есть одно но - если выбирать значение в picker'e мышью (sic!), то query при попытке интерпретировать ответ (.asString, .asInteger) выдаёт ошибку: Query: Field 'N1' not found. Не всегда выдаёт, произвольно, один раз из десяти-пятнадцати. Если же выбирать дату в пикере стрелочками, всё прекрасно, никакой ошибки. Более того, по событию FormCreate отрабатывает datetimepickerchange(self), и при запуске проги в гриде тоже всё прекрасно отображено.
Усугубляет разброд в моём мозге то, что поидее сообщения вообще выдаваться не должно бы (try..except), а оно выдаётся :)
Выглядит же этот безобразный цикл примерно так:
try
Query.Open;
for j := 0 to query.RecordCount-1 do begin
// здесь идут блоки s := fieldbyname .asstring; .asinteger; итд
try
S := query.FieldByName('N1').AsString;
except
end;
// здесь мы эти s пихаем в stringgrid
Query.Next;
Application.ProcessMessages;
end;
finally
Query.Close;
end;
При возникновении этого глюка отладчик вылетает в окно CPU, а не на строку между try..except. Стэк вызовов процедур получается такой:
KERNELBASE.RaiseException
DatabaseError
DatabaseErrorFmt
Dataset.FieldByName
стоп указывает на инструкцию leave
перед ней call dword ptr [$7555116c] - что там у меня по этому адресу - Готт его знает, перешёл туда - там jnbe, перед ней ещё пара инструкций и нули, много-много нулей :) Увы, мой ассемблер закончился в досе на уровне mov ah, 9 int 21h, так что мне это ровным счётом ничем не помогло :)
Вопрос: что же всё-таки её вызывает, ошибку эту, если мышкой выбирать дату? Пока вопрос решён чисто по-русски, то есть юзеры (~80 человек) не выбирают мышкой, но мучит меня совесть и интерес профессиональный, что ж за фигня такая :)
Плиз хелп, всем заранее спасибо!
Anatoly Podgoretsky (2010-12-15 14:41:00) [21]> sniknik (15.12.2010 14:29:04) [64]
А я и не рекомендовал, просто указал, что и это надежный метод при
правильном написание, а не при SELECT *
В контексте необходимости явного указания полей.
Ega23 (2010-12-15 14:40:00) [22]
> Не зарекаюсь, но с 99.999% вероятностью на протяжении жизни
> этого проекта админ не будет трогать бд.
А ты не допускаешь мысли, что кроме данного проекта ты в своей жизни ещё и другими будешь заниматься? Где данное разделение будет в порядке вещей?
Учись писать правильно с самого начала. Тебе не вредные советы дают, тут люди не один такой "кинозал" написали, а по десятку (если не больше).
Anatoly Podgoretsky (2010-12-15 14:39:00) [23]> sniknik (15.12.2010 14:28:03) [63]
На stringgrid можно много выиграть, очень медленный компонент.
Anatoly Podgoretsky (2010-12-15 14:38:00) [24]> megavoid (15.12.2010 14:27:02) [62]
Ты даже не преставляешь как SQL работает, да именно обязан.
Какой "Ega23 придёт и порядок полей поменяет" тебе порядок полей в твоей
программе поменяет, окстись.
Ega23 (2010-12-15 14:38:00) [25]
> Ага, укажу я поля в запросе явно, а SQL обязан мне их в
> таком же порядке вернуть?
Естественно.
Также, как и то, что сервер тебе произвольный порядок самих записей может выдать, если ты явно Order By не указал. На одинаковом запросе.
> + главный "тормоз" будет/есть не в нем а в стринггриде.
> и даже если ему поставить "дизебле" (там как то по другому
> называется)
По всей видимостиStringGrid1.Rows.BeginUpdate\EndUpdate
проверять лениво.
megavoid (2010-12-15 14:32:00) [26]>>Кроме того все ты не проконтролируешь, на нормальных фирмах это разделено между разными людьми, и первому человеку совсем не обязательно знать, что админ добавил blob поле.
Не зарекаюсь, но с 99.999% вероятностью на протяжении жизни этого проекта админ не будет трогать бд.
Ega23 (2010-12-15 14:29:00) [27]
> В данном конкретном случае администратор БД управляется
> мной же, и я просто не пропущу большой блоб. Когда это писалось,
> я закладывался на полный контроль всего комплекса со стороны
> меня, что и позволяет мне достаточно вольно писать мой говнокод,
> точно помня что, где и как расположено.
Дык нету у тебя полного контроля при *, пойми. Полный контроль - когда ты чётко выбираешь именно те поля, которые тебе нужны. В том самом порядке, который тебе нужен.
> Экономия, всё верно выше подметили. Над завести много датасетов
> - подумаю.
Ты не на том экономишь. Если аналогию провести, то ты сейчас экономишь на мусорных пакетах, выбрасывая всё что есть в один, а потом на мусорке его разгребать и по разным контейнерам складывать: туда - пищевые отходы, туда - стекло всякое и т.д.
Впрочем, это был ещё один совет. :)))
> Прописал disable/enable. На глазок по скорости выполнения
> то же самое, но глазок не профайлер, вечером замерю без
> и с disablecontrols.
Может и не дать, тут очень многое зависит непосредственно от компонента. Надо реализацию смотреть. Но в целом - надо писать, это правило хорошего тона.
> Там только ради WM_PAINT. Не 5, а 2-3 секунды :) WinSight
> у меня частенько открыт. Ну, даже если придёт LBUTTONDOWN
> или CLOSE - как это собьёт мне Query?
А ты возьми, зацепи окно мышкой и не отпускай. Потаскай его по экрану.
Screen.Cursor := crSQLWait;
try
with DataSet do
begin
Open;
........
end;
finally
Screen.Cursor := crDefault;
end;
sniknik (2010-12-15 14:29:00) [28]> Ага, укажу я поля в запросе явно, а SQL обязан мне их в таком же порядке вернуть?
да.
хотя это и "всплыло" от не рекомендованного тут метода.
sniknik (2010-12-15 14:28:00) [29]> Куда "за"? Оно потому и внутри цикла, что я получаю данные из полей в цикле.
за цикл, и не получение данных, а определение по имени. блин.
что так сложно понять, до цикла определить поле и запомнить его в переменную, в цикле использовать ее.
> Прописал disable/enable. На глазок по скорости выполнения то же самое, но глазок не профайлер, вечером замерю без и с disablecontrols.
на ста записях заметно не будет, вот сто тысяч... другое дело. + главный "тормоз" будет/есть не в нем а в стринггриде. и даже если ему поставить "дизебле" (там как то по другому называется) на обновления, это тоже будет мелочь по сравнению с тем как он сам по себе тормозит. "из принципа" (по логике с которой сделан)
megavoid (2010-12-15 14:27:00) [30]> Уверенность надо обретать в явном указание полей, а тогда
> можно и Fields[i]
Ага, укажу я поля в запросе явно, а SQL обязан мне их в таком же порядке вернуть? Я уж лучше через .FieldByName. А то и вообще Ega23 придёт и порядок полей поменяет, а с fieldbyname мне это фиолетово.
Anatoly Podgoretsky (2010-12-15 14:26:00) [31]> megavoid (15.12.2010 14:16:57) [57]
" и я просто не пропущу большой блоб."
Не зарекайся. Кроме того все ты не проконтролируешь, на нормальных фирмах
это разделено между разными людьми, и первому человеку совсем не обязательно
знать, что админ добавил blob поле. Не его это дело, его дело писать
правильные запросы, а не лениться. Молчу уж про параметры и оптимизатор.
Anatoly Podgoretsky (2010-12-15 14:22:00) [32]> Ega23 (15.12.2010 13:54:53) [53]
"Fields[Index] - это только если ты строго уверен, что НД пришёл в строго
определённом порядке полей."
Уверенность надо обретать в явном указание полей, а тогда можно и Fields[i]
megavoid (2010-12-15 14:19:00) [33]> > вынести "за" и все дела
Куда "за"? Оно потому и внутри цикла, что я получаю данные из полей в цикле.
Anatoly Podgoretsky (2010-12-15 14:19:00) [34]> Ega23 (15.12.2010 13:54:53) [53]
Ты где такие маленькие битмапы нашел.
megavoid (2010-12-15 14:16:00) [35]
> Вот теперь я, как администратор БД, беру и меняю порядок
> полей в таблице. Или, например, добавлю в данную таблицу
> блоб-поле, в которой битмап для каждой записи будет лежать.
> Метра так на 2.
В данном конкретном случае администратор БД управляется мной же, и я просто не пропущу большой блоб. Когда это писалось, я закладывался на полный контроль всего комплекса со стороны меня, что и позволяет мне достаточно вольно писать мой говнокод, точно помня что, где и как расположено.
> скажи, а зачем такой изврат нужен? Ну, в смысле, один DataSet
> на всё приложение?
Экономия, всё верно выше подметили. Над завести много датасетов - подумаю.
> Простейшая операция disable|enable controls дала прирост
> производительности то ли в 30 раз, то ли в 70.
Прописал disable/enable. На глазок по скорости выполнения то же самое, но глазок не профайлер, вечером замерю без и с disablecontrols.
> Application.ProcessMessages
Там только ради WM_PAINT. Не 5, а 2-3 секунды :) WinSight у меня частенько открыт. Ну, даже если придёт LBUTTONDOWN или CLOSE - как это собьёт мне Query? Если пришлют DESTROY - ну тут и так понятно что хана, никакой квери уже нафиг не нужен будет.
ЗЫ. А кресло у меня большое-большое, ага :) А программирование мне больше по душе :)
sniknik (2010-12-15 14:14:00) [36]> Поясни "в третьих определение по имени поля внутри цикла"
> вынести "за" и все дела
Ega23 (2010-12-15 14:11:00) [37]
> не выдумывай отсебятины... Fields[Index] я сам нигде не
> использую и другим не советую.
Тогда я тебя не понял. Поясни "в третьих определение по имени поля внутри цикла"
sniknik (2010-12-15 14:09:00) [38]> Вот тут я со sniknik не согласен. FieldByName - в целом более правильное обращение. Fields[Index] - это только если ты строго уверен
не выдумывай отсебятины... Fields[Index] я сам нигде не использую и другим не советую.
> в третьих определение по имени поля внутри цикла
где тут Fields[Index]? здесь про "внутри цикла", вынести "за" и все дела, а не менять на что то самопридуманное.
Ega23 (2010-12-15 13:54:00) [39]
> И если на следующий день заказчик захочет добавить ещё одно
> поле в базу, придётся ходить и везде его приписывать? В
> других запросах, где мне требуются только отдельные поля,
> я указываю их. Если нужны все - ставлю *.
Вот теперь я, как администратор БД, беру и меняю порядок полей в таблице. Или, например, добавлю в данную таблицу блоб-поле, в которой битмап для каждой записи будет лежать. Метра так на 2.
И теперь ты по своей * будешь тащить на каждый чих по 100 записей дополнительно 200 мегабайт картинок.
Это первое.
Второе: а тебе и так и так придётся переписывать. Добавлять fieldByName и заносить его в определённый столбец твоего StringGrid.
> это будет мне очень неудобно - sql запрос req конструируется
> разный, в разных местах, с разными параметрами
скажи, а зачем такой изврат нужен? Ну, в смысле, один DataSet на всё приложение? Заведи себе их столько, сколько нужно. Аккуратно пропиши параметры. Выстави Prepared (скомпилируй заранее).
Получишь афигенный выигрыш на скорости, проверено неоднократно.
> > в третьих определение по имени поля внутри цикла
> это из области фильмов ужасов, ага, но - работает
Вот тут я со sniknik не согласен. FieldByName - в целом более правильное обращение. Fields[Index] - это только если ты строго уверен, что НД пришёл в строго определённом порядке полей. Что сильно повышает неустойчивость в случае, если работаешь с хранимой процедурой, а её код может кто-то модифицировать.
> нет. юзеры всё равно ничего не успеют сделать, пока получаем
> данные
> сильно подозреваю, что тоже из ужастиков
Зря подозреваешь. Смотри код TDataSet. Года 2.5 -3 назад аккурат на этом форуме я вопрос поднимал. Простейшая операция disable|enable controls дала прирост производительности то ли в 30 раз, то ли в 70.
> Но извне, пока работает FillGrid, никаких сообщений не
> придёт - всё однопоточное.
Да ну? Ты, видать, плохо разбираешься, что такое Application.ProcessMessages.
простой пример.
У тебя, запрос, который выполняется 5 секунд (это только Open). За эти 5 секунд ты наделал кучу всякой разной фигни мышкой. Что будет - предлагаю тебе самому на чистом проекте испытать.
Anatoly Podgoretsky (2010-12-15 13:48:00) [40]> megavoid (15.12.2010 13:29:50) [50]
"И если на следующий день заказчик захочет добавить ещё одно поле в базу,
придётся ходить и везде его приписывать?"
Я уже говорил, что ленивым нечего делать в программирование. Тебе надо в
менеджеры и чтобы кресло пошире.