C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

стр.: (4) < 1 2 [3] 4 >
как оседлать DBGridEh? (sql server+ado+dbgrideh), редактирование записей в гриде вручную
greyich
Отправлено: 12.08.2005, 08:41


Дежурный стрелочник

Группа: Участник
Сообщений: 45



QUOTE (olegenty @ 12/08/2005, 08:36)
возможно, тебе поможет какая-то из этих строк (или их комбинация):
CODE

MemTable->FieldDefs->Update();
MemTable->FieldDefList->Update();
MemTable->FieldList->Update();


Persistent полей, я надеюсь, у тебя там нет?

написал даже все три сразу — непомогло. конечно попробую комбинации но боюсь вряд ли поможет

перепробовал все 7 комбинаций smile.gif тоже не помогло

Отредактировано greyich — 12/08/2005, 08:46
AVC
Отправлено: 12.08.2005, 08:54


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (greyich @ 12/08/2005, 07:35)

1. а еще лучше на FindField
а) несколько не понял что значит "обернуть sql_text в еще один select". не могли бы вы пояснить подробнее
б) другими словами adoquery не рулит и рекомендуется пользоваться хранимыми?

1. В приведенном вами коде не лучше, так как вы все равно получите исключение при доступе к Value. Это лучше когда создаются переменные под поля.
А с учетом 2 это вообще безразлично.

а) Select * From (+ sql_text + ) Where id = :id
б) Это проверять вам. Лично я пользуюсь запросами а не SP.

QUOTE (greyich @ 12/08/2005, 07:35)

кстати текст записанный в
ADODataDriverEh1->GetrecCommand->CommandText->Text сработал только после вызова RefreshRecord. на все остальные попытки, как например закрыти и открытие набора данных и сетки, он молчал в тряпочку.

Судя по названию свойство GetRecCommand именно для этого и предназначено (RefreshRecord). И молчал в тряпочку в остальных случаях он вполне справедливо.

PS.
Замечания были общего характера, безотносительно к MemTable и EhLib (ну не пользуюсь я ими, своего хватает smile.gif ). Но мне кажется, что у вас где-то ошибка в логике. В конце концов пройдитесь по шагам, посмотрите протокол обмена с сервером.
olegenty
Отправлено: 12.08.2005, 09:18


Ветеран

Группа: Модератор
Сообщений: 2412



вот и я думаю — что где-то ошибка в логике. у меня же работает, как мне хочется smile.gif
greyich
Отправлено: 12.08.2005, 09:26


Дежурный стрелочник

Группа: Участник
Сообщений: 45



QUOTE (olegenty @ 12/08/2005, 09:18)
вот и я думаю — что где-то ошибка в логике. у меня же работает, как мне хочется smile.gif

как в старом анекдоте:
- Где у меня ошибка?
- В ДНК!

ладно будем укрощать. может ли это из-за того что не все commandEh заполнены? (за ненадобностью).
olegenty
Отправлено: 12.08.2005, 09:31


Ветеран

Группа: Модератор
Сообщений: 2412



нет, не может. если требуется некий Command, SQL которого пуст, возникает вполне конкретное сообшение об ошибке, которое и вещает — "мне надо, а нету... разберитесь..."
greyich
Отправлено: 12.08.2005, 09:54


Дежурный стрелочник

Группа: Участник
Сообщений: 45



QUOTE (olegenty @ 12/08/2005, 09:31)
нет, не может. если требуется некий Command, SQL которого пуст, возникает вполне конкретное сообшение об ошибке, которое и вещает — "мне надо, а нету... разберитесь..."

хм. еще раз прочитав справку узрел я, что наверное обработчик события onRefreshRecord надо писать мне. и куда я раньше смотрел?
осталось понять что туда писать и чем оно отличается от первичного заполнения даными
olegenty
Отправлено: 12.08.2005, 10:00


Ветеран

Группа: Модератор
Сообщений: 2412



стоп!!! так ты в GetrecComand хотел поле добавить??? не-е-е-е-е... поле можtn быть добавлено только посредством SelectComand.

далее. если написать OnRefreshRecord, то GetrecCommand и обновление по умолчанию будут игнорироваться нафиг. (хотя ты легко сможешь ими воспользоваться самостоятельно). проинициировав событие, ты и сам увидишь, что там всё просто, как дверная ручка. пример надо?
greyich
Отправлено: 12.08.2005, 10:07


Дежурный стрелочник

Группа: Участник
Сообщений: 45



QUOTE (olegenty @ 12/08/2005, 10:00)
стоп!!! так ты в GetrecComand хотел поле добавить??? не-е-е-е-е... поле можtn быть добавлено только посредством SelectComand.

далее. если написать OnRefreshRecord, то GetrecCommand и обновление по умолчанию будут игнорироваться нафиг. (хотя ты легко сможешь ими воспользоваться самостоятельно). проинициировав событие, ты и сам увидишь, что там всё просто, как дверная ручка. пример надо?

???? обана. поле я добавляю вообще без обработчиков событий dbgrideh! на кнопке у меня висит добавление поля. а потом я уже пытаюсь проадейтить datadrivereh и memtableEh. а что неправильно???

надо спровоцировать в обработчике нажатия кнопки какое-то событие?
olegenty
Отправлено: 12.08.2005, 10:36


Ветеран

Группа: Модератор
Сообщений: 2412



ну ты перец!!! поле надо добавлять в TMemTableEh, грид-то тут при чём?
greyich
Отправлено: 12.08.2005, 10:54


Дежурный стрелочник

Группа: Участник
Сообщений: 45



QUOTE (olegenty @ 12/08/2005, 10:36)
ну ты перец!!! поле надо добавлять в TMemTableEh, грид-то тут при чём?

блин да не перец я не перец! smile.gif

поле добавляю в базу! так давайте еще раз но пошагово:

главные герои: форма, на ней DBGridEh, к нему присоединены Datasource, MemTableEh и наконецто DAtaDriverEh.

сцена первая:
формирую sql запрос текстовой строкой и кидаю в
ADODataDriverEh1->SelectCommand->CommandText->Text = sql_text;
потом
MemTableEh1->Active = true;
и после
ADODataDriverEh1->GetrecCommand->CommandText->Text = sql_text + " where id_p = '" + MemTableEh1->FieldByName("id_p")->asString;

на форме видим заполнение сетки данными(что вполне логично smile.gif)

сцена вторая: наступает после попыток юзверя ввести что-нибудь в ячейку
на сцену вызывается DODataDriverEh1UpdateRecord
к которому у меня приписана хранимая процедура

dm_ado->gr_update_exams_sp->Close();
dm_ado->gr_update_exams_sp->Parameters->operator [](1)->Value = val;
dm_ado->gr_update_exams_sp->Parameters->operator [](2)->Value = fio;
dm_ado->gr_update_exams_sp->Parameters->operator [](3)->Value = subj;
dm_ado->gr_update_exams_sp->Prepared = true;
dm_ado->gr_update_exams_sp->ExecProc();
(в данный момент помидоры летящие из зала в убогую процедуру прошу не кидать)

прошло. данные обновились. перед занавесом делаю
void __fastcall Tfrm_main_gr::MemTableEh1AfterPost(TDataSet *DataSet)
{
AnsiString val = DBGridEh2->SelectedField->Value;
if (Trim(val) == "5") val = "îòë";
if (Trim(val) == "4") val = "õîð";
DBGridEh2->SelectedField->Value = val;
}
в надежде перевести данные из цифровой формы в символьную но тщетно — на сетке только то что ввел пользователь.

сцена 3: пользователь нажал кнопку добавить поле и ввелд данные.
у меня повешен след код
dm_ado->add_subj->Close();
AnsiString sql_text = "insert into exams (date_exam, id_p , id_sub) values ('"+ DateTimePicker1->Date +"','" + dm_ado->sel_id_pup_from_group->FieldByName("id_p")->Value + "','"+ dm_ado->sel_id_subj->FieldByName("id_sub")->Value+ "')";
dm_ado->add_subj->SQL->Text = sql_text;
dm_ado->add_subj->Prepared = true;
dm_ado->add_subj->ExecSQL();

изменения отразились в базе!!! но не в сетке. если сделать переключение с форму куда-либо а потом обратно, то тогда он отобразится на форме.
как сделать так чтобы он отображался сразу и в ячейках таблицу отображалась актуальная инфа — непонятно. все занавес. полетели помидоры...
olegenty
Отправлено: 12.08.2005, 11:12


Ветеран

Группа: Модератор
Сообщений: 2412



ну, мил человек, теперь объясни мне на пальцах, зачем тебе при таком подходе MemTableEh, если ты всё делаешь по-старинке. столько кода вместо того, чтобы (ВСЕГО ЛИШЬ) заполнить соответствующие св-ва компонента TADODataDriverEh. ты ж фичами-то и не пользуешься.

резюме — переделай. св-ва заполни просто. ты удивишься, но это работатет лучше. там же параметры есть. приврати всё в параметрические запросы. оперируй ТОЛЬКО св-вами TADODataDriverEh. и никаких ещё дополнительных компонентов, кроме TADODataDriver и TMemTableEh не используй при этом. для одного набора данных по одной штуке. если селекты генерит пользователь — наздоровье, тогда перегенеривай и св-ва TADODataDriver. и будет тебе аналог счастья в цвете.
greyich
Отправлено: 12.08.2005, 12:03


Дежурный стрелочник

Группа: Участник
Сообщений: 45



QUOTE (olegenty @ 12/08/2005, 11:12)
ну, мил человек, теперь объясни мне на пальцах, зачем тебе при таком подходе MemTableEh, если ты всё делаешь по-старинке. столько кода вместо того, чтобы (ВСЕГО ЛИШЬ) заполнить соответствующие св-ва компонента TADODataDriverEh. ты ж фичами-то и не пользуешься.

резюме — переделай. св-ва заполни просто. ты удивишься, но это работатет лучше. там же параметры есть. приврати всё в параметрические запросы. оперируй ТОЛЬКО св-вами TADODataDriverEh. и никаких ещё дополнительных компонентов, кроме TADODataDriver и TMemTableEh не используй при этом. для одного набора данных по одной штуке. если селекты генерит пользователь — наздоровье, тогда перегенеривай и св-ва TADODataDriver. и будет тебе аналог счастья в цвете.

так. почему я перешел на memtableeh и datadrivereh (кстати может пора уже както назвать эту технологию или узнать у разработчика как она называется) было обсуждено выше.

ничего кроме этого я и не использую (разве что datasource — но куда без него?)

подскажите мне как найти информацию по параметрическим запросам. в билдеровском хелпере описывалось через заполнение вручную (как я и сделал) и поиск по форумам не дал ничего вразумительного.

и зачем перегенерировать свойства tadodatadriver?
olegenty
Отправлено: 12.08.2005, 12:19


Ветеран

Группа: Модератор
Сообщений: 2412



перегенерировать св-ва TADODataDriver нужно только в том случае, если SelectSQL формируется пользователем, при этом меняется количество параметров, либо количество параметров неизменно, но изменилось количество полей ОДНОЙ таблицы, которую при этом хочется одновлять. во всех остальных случаях (т.е. количество параметров SelectSQL одно и то же и количество полей — величина постоянная), никакие компоненты, кроме ОДНОГО TADODataDriver и ОДНОГО TMemTableEh — не нужны. эта пара приспокойно справится с любой работой.

SQL
create table dbo.test (
id int primary key
, name varchar (50)


SelectCommand
CommandText
SQL
select id, name from dbo.test where name like :NameParam

Parameters — 1 штука:
Name = NameParam
DataType = ftString
Derection = pdInput
Size = 50
UpdateCommand
CommandText
SQL
update dbo.test set name = :name where id = :id

Parameters — 2 штуки. их НЕОБХОДИМО ОПИСАТЬ, но не надо заполянть вручную. в случае. когда имя параметра совпадает с именем поля, его значение и берётся из поля.
Item 0 (параметр 1)
Name = id
DataType = ftInteger
Derection = pdInput
Item 1 (параметр 2)
Name = name
DataType = ftString
Derection = pdInput
Size = 50

и ВСЁ!!! никаких ручных заполнений св-в в рантайме!!! TADODataDriver сам всё сделает. И только когда его стандартное поведение чем-то не устраивает, надо писать обработчики событий. Например, если делаешь вставку, а в таблице есть поле identity, то тогда вставку надо делать уже с помощью хранимой процедуры, которая будет возвращать значение этого поля, а ты РУКАМИ подсунешь его в MemoryTable в обработчике OnGetBackUpdatedValues. И это, пожалуй, единственное, что там надо делать руками.
olegenty
Отправлено: 12.08.2005, 12:22


Ветеран

Группа: Модератор
Сообщений: 2412



да и то, не отдельным компонентом, а всё тем же TADODataDriver — после выполнения хранимки он корректно вернёт прямо в обработчик выходные параметры.
greyich
Отправлено: 12.08.2005, 13:27


Дежурный стрелочник

Группа: Участник
Сообщений: 45



ладно. буду учится. создам новый проект и попробую нарисовать. кстати www.nigma.ru на запрос о параметризованных запросах отсылает на этот форум к постам olegenty и avc smile.gif
olegenty
Отправлено: 12.08.2005, 13:35


Ветеран

Группа: Модератор
Сообщений: 2412



Ну нету у меня времени на статью, честно. На работе — работа. Дома — жена и сын smile.gif (такую, чтоб с картинками)

кстати, а примеры тебе чем не глянулись, те, что в MTDEMOS?
greyich
Отправлено: 15.08.2005, 16:18


Дежурный стрелочник

Группа: Участник
Сообщений: 45



хотя наверно вопрос не сюда, но все-таки попробую продолжить ветку...

к вопросу о параметрическим запросах

я конечно опять всё не так делаю, но если я сам хочу заполнить параметры command в рантайме? скажем часть не совпадает с полями,а часть нужно вручную подготовить

olegenty
Отправлено: 16.08.2005, 06:55


Ветеран

Группа: Модератор
Сообщений: 2412



тогда
1. Да, создаёшь параметры руками
2. Заволняешь несовпадающие параметры либо
2.1 Перед открытием запроса
либо
2.2 в событии OnAssignComandParameter
в случае 2.2 надо быть внимательным: когда есть обработчик этого события, все заполнения параметров по умолчанию уже не работают, поэтому для несовпадающих с именами полей параметров надо заполнять их вручную, а для совпадвющих вызывать DefaultAssignComandParameter
olegenty
Отправлено: 23.08.2005, 08:34


Ветеран

Группа: Модератор
Сообщений: 2412



для тех, кто работает с MemTableEh + ADODataDriverEh
при вынесении в отдельный поток метода Open() компонента MemTableEh на длинных выборках ГАРАНТИРОВАННО наступает Command Timeout через 30 секунд.
править так:
CODE

case Command.CommandType of
     cthSelectQuery, cthUpdateQuery:
       begin
         ACursor := TADOQuery.Create(nil);
         with ACursor as TADOQuery do
         begin
           Connection := ADOConnection;
           ConnectionString := ConnectionString;
           ////////////////////////////
           if Assigned(Connection) then CommandTimeout :=Connection.CommandTimeout;

т.е. надо ручками выставить CommandTimeout.

Большакову уже сказал, думаю, исправит.
greyich
Отправлено: 23.08.2005, 12:45


Дежурный стрелочник

Группа: Участник
Сообщений: 45



QUOTE (olegenty @ 23/08/2005, 08:34)
для тех, кто работает с MemTableEh + ADODataDriverEh
при вынесении в отдельный поток метода Open() компонента MemTableEh на длинных выборках ГАРАНТИРОВАННО наступает Command Timeout через 30 секунд.
править так:
CODE

case Command.CommandType of
cthSelectQuery, cthUpdateQuery:
begin
ACursor := TADOQuery.Create(nil);
with ACursor as TADOQuery do
begin
Connection := ADOConnection;
ConnectionString := ConnectionString;
////////////////////////////
if Assigned(Connection) then CommandTimeout :=Connection.CommandTimeout;

т.е. надо ручками выставить CommandTimeout.

Большакову уже сказал, думаю, исправит.

то есть полминуты посчитывали данные а потом — фигушки smile.gif вам больше и не надо
spiller
Отправлено: 26.06.2006, 21:14


Ученик-кочегар

Группа: Участник
Сообщений: 27



Гуру, подскажите.
Я пока изучал help по Ehlib английский язык выучил, понимания технологии так и не добился... (
Скажите а как узнать значение GridEh под мышкой?

B как обстоят дела со множественным выделением?

Отредактировано spiller — 26/06/2006, 21:18
olegenty
Отправлено: 27.06.2006, 06:37


Ветеран

Группа: Модератор
Сообщений: 2412



множественное выделение есть в примере. (TDBGridEh.Selection)
Gedeon
Отправлено: 27.06.2006, 12:57


Ветеран

Группа: Модератор
Сообщений: 1742



QUOTE (spiller @ 26/06/2006, 21:14)
Скажите а как узнать значение GridEh под мышкой?

Ищите на форуме есть ветка GridUnderMouse AVC выложил очень хороший работающий пример.
Gedeon
Отправлено: 27.06.2006, 13:00


Ветеран

Группа: Модератор
Сообщений: 1742



вот нашел, юзайте
gum
spiller
Отправлено: 08.07.2006, 21:30


Ученик-кочегар

Группа: Участник
Сообщений: 27



Спасибо. Изучил.

Еще вопросик, скажите мне пожалуйста, в чем суть свойства GetRecCommand компонента TADODataDriver? Я что-то читал, что запрос на изменение данных на клиенте, но, скажите пожалуйста, зачем тогда UpdateCommand?

И еще, есть ли метод, который перезапрашивает данные с сервера?
Пока делаю так:
CODE

MemTable->Close();
MemTable->Open();



Cпасибо!

Отредактировано spiller — 08/07/2006, 21:30
olegenty
Отправлено: 09.07.2006, 06:14


Ветеран

Группа: Модератор
Сообщений: 2412



перезапрашиваются данные именно так, как ты это делаешь, если речь идёт о ВСЕЙ ВЫБОРКЕ.

в свою очередь, GetRecCommand перезапрашивает даннык об одной ТЕКУЩЕЙ (ВЫБРАННОЙ) записи, посредством вызова метода RefreshRecord
Guest
Отправлено: 09.07.2006, 09:59


Не зарегистрирован







МММ, понятно!
Можно еще вопрос?)
ADO-MySQL

Допустим у меня таблица типа словарь:
ID- типа autoIncrement
Name — varchar(200)

Вот. Есть у меня вся связка для работы с "живым" набором данных:
ADoDataDriverEh  — MEmTableEh — DataSourseEh — GridEh

Вот. Свойство SelectSQL просто выбирает все Name и отображает в гриде.
Но мне очень желательно, чтобы в гриде был еще один столбец- просто числа от 1 до числа всех этих Name. Как мне их правильно проставить?

Спасибо заранее!
Прошу прощение за нескромность;)
olegenty
Отправлено: 09.07.2006, 12:51


Ветеран

Группа: Модератор
Сообщений: 2412



в смысле, не ID из базы, а просто локально от 1 и до последней записи? просто создаёшь Calculated поле, например RecNo, и в OnCalcFields пишешь:
CODE

YourMemTableRecNo->AsInteger = YourMemTable->RecNo;


для корректной работы сей штуки надо выставлять FetchAllOnOpen в true. (а может и не надо — не помню)
spiller
Отправлено: 09.07.2006, 19:06


Ученик-кочегар

Группа: Участник
Сообщений: 27



благодарче, все получилось

Отредактировано spiller — 10/07/2006, 19:20
spiller
Отправлено: 10.07.2006, 19:21


Ученик-кочегар

Группа: Участник
Сообщений: 27



Добрый день всем обитателям этого форума!
Попробую и я задать вопросик к знатокам
У господина большакова в примерах нашел процедуру "живого удаления записей":

Код:
CODE

procedure TForm1.ppmDeleteClick(Sender: TObject);
begin
 if (ActiveControl is TDBGridEh) then
   with TDBGridEh(ActiveControl) do
     if CheckDeleteAction and (geaDeleteEh in EditActions) then
       DBGridEh_DoDeleteAction(TDBGridEh(ActiveControl),False);

end;



Привильно ли я понял, что можно проссто выделить определенные ячейки и они удалятся в самой БД, если все это хозяйство висит на TXXXDataDrivere c прописанным DeleteSQL?

Ие еще не получается у применить DBGridEh_DoDeleteAction . РУгается что это не член класса. Я тоже такого метода не припомню. Найти в других файлах так и не удалось[CODE]

Отредактировано spiller — 10/07/2006, 19:21
стр.: (4) < 1 2 [3] 4 >
Вернуться в Работа с базами данных в C++Builder