Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2004.02.25;
Скачать: [xml.tar.bz2];

Вниз

Insert, Update, Delete своими руками   Найти похожие ветки 

 
mvg_first   (2004-01-28 09:01) [40]

denisov
Так таки и не подскажешь где поискать этот твой VirtualStringTree?


 
mvg_first   (2004-01-28 11:09) [41]

jocko
Я хочу без Экшин-листов :) Хочу просто в гриде добавить запись а датасет должен вызвать при этом мой запрос. И не дать выполнится запрос встроенному в Адошный рекодсет. И после выполнения запроса обновить грид и стать на ту же запись которую добавил или на которую должен встать в результате перемещения после добавления.
Если использовать БатчОптимистик - то как сказать что бы он все таки не делал запрос?


 
sniknik   (2004-01-28 11:27) [42]

mvg_first © (28.01.04 11:09) [41]
странный человек, ты скажи ты пробуеш чегонибудь ([36] к примеру), или продолжаеш теоретизировать?
чего до сих пор непонятно? единственное чего не обсуждали пока в этом варианте
> а датасет должен вызвать при этом мой запрос.
чем AfterPost не подходит? (в отсоедененном как раз сработает
> не дать выполнится запрос встроенному в Адошный рекодсет)

или, придумай другую причину по которой этот вариант не проходит. (пока все выдвигаемые "требования" один в один сходятся с действительностью)

> Так таки и не подскажешь где поискать этот твой VirtualStringTree?
почему думаеш что поможет левый компонент без документации если не можеш разабратся в стандартном с кучей хелпов и описаний?


 
denisov   (2004-01-28 19:43) [43]


> mvg_first © (28.01.04 09:01) [40]

В интернете, разумеется.) www.lischke-online.de де то там
http
> sniknik © (28.01.04 11:27) [42]
Левый он чуть более борландовских, к тому же документация в наличии, до безобразия в наличии


 
mvg_first   (2004-01-29 09:17) [44]

sniknik
Попробовал. Да действительно если отключать Connection := nil то данные не отсылаются, но я против этого и не спорил. Но по пунктам:
В AfterPost вставка записи не канает :) Потому как в этот момент запись в гирде уже фактически запостилась.
Поэтому написал в методе BeforePost. Следующий код
if ADOQuery1.State = dsInsert then
begin
ADOCommand1.CommandText := "INSERT TABLE1 (TestStr) VALUES(:TestStr) SELECT :ID = SCOPE_IDENTITY()";
ADOCommand1.Parameters.ParamByName("TestStr").Value := DataSet.FieldByName("TestStr").Value;
ADOCommand1.Parameters.ParamByName("id").Direction := pdOutput;
ADOCommand1.Parameters.ParamByName("Id").DataType := ftInteger;
ADOCommand1.Execute;
ADOQuery1.FieldByName("Id").ReadOnly :=false;
ADOQuery1.FieldByName("Id").Value := ADOCommand1.Parameters.ParamByName("Id").Value;
end;

При этом записи добавляются конечно, но в гриде поле ID не обновляется.
Так что даже в этом случае - слегка...
И тут же следующий вопрос а если у меня при добавлении 1-го поля в таблицу происходит заполнение других полей (например триггер срабатывает) как мне эти поля тоже в ручную обрабатывать? А не слишком ли это накладно - эфеект использования DBGrida как таковго теряет смысл :(


 
mvg_first   (2004-01-29 09:38) [45]

В догонку (предыдущий пост написал вчера но почему то сайт лежал что ли вообще отправить немог) дома попробовал больше поиграться с вышеописанным алгоритмом. Понял почему не обновляется поле ID - оно автоинкрементное и по определению обновлятся не может. Но все равно проблемы это не решает. Если у меня после инсерта сделанного самостоятельно - кроме измененных пользователем полей меняются еще и другие поля (например заполняется поле PostDateTime в триггере) - то при таком подходе они не обновляются в гриде (вернее мне придется заново, получать это все из грида и полностью переприсваивать все поля отображаемые в гриде руками - объясните мне полезность такого метода?


 
mvg_first   (2004-01-29 09:43) [46]

/denisov (28.01.04 19:43) [43]/
Ну а насчет VirtualStringTree - то я к этому времени уже сам нашел, вчера дома поковырял (мощнейшая штука ничего не скажешь) особенно если вкурить во все ее тонкости. Но непонравилось две вещи. Когда к ней подключаются эдиты - они выглядят наложенными сверху а не встроенными в компонент :( Даже не попадают в рамки редактируемого нода. (я это вкорне не приветствую) И второе так и не разобрался как же сделать там возможность начинать редактирование без клика мышью по ноду или без нажатия кнопки F2/ Так как это делается в ДБГриде. Нажимаешь Энтер и начинаешь редактировать еще раз Энтер - заканчиваешь редактировать поле???


 
mvg_first   (2004-01-29 09:50) [47]

Насчет использования VIEW c INSTEAD OF триггерами.
Вчера же опять попробовал создать вьюшку но уже с опцией WITH VIEW_METADATA, теперь действительно начали срабатывать триггеры на добавление. Но тут же наткнулся на одну интересную вещь. Использовал стандартные компоненты. В тригере вместо вставки добавляемых значений сделал вставку простой текствой строки в текстовое поле (строка точно не соответствовала добавляемым из грида значениям)
ПОсле этого при попытка добавить в гриде запись добавление происходило но в гриде оставались значения занесенные туда пользователем, а те данные которые реально попадают в таблицу с использованием INSTEAD OF триггера - неотображались - пока не переоткроешь таблицу :( Именно этот факт и вызывает неудовольствие с моей стороны.


 
DenK_vrtz   (2004-01-29 10:03) [48]

>ПОсле этого при попытка добавить в гриде запись добавление происходило но в гриде оставались значения занесенные туда пользователем, а те данные которые реально попадают в таблицу с использованием INSTEAD OF триггера - неотображались - пока не переоткроешь таблицу :(

а ты чуда ждал? :)
а refresh, если сделать?


 
Polevi   (2004-01-29 10:07) [49]

>mvg_first
ну и каша у тебя в голове :)


 
sniknik   (2004-01-29 10:20) [50]

mvg_first © (29.01.04 09:17) [44]

> При этом записи добавляются конечно, но в гриде поле ID не обновляется.
как это? должно.
вот так сделай
ADOQuery1.FieldByName("Id").ReadOnly :=false;
ADOQuery1.FieldByName("Id").Value := 30;
обновилось?
даже если оно автоинкрементное, оно такое в базе/таблице а тут ты уже с рекордсетом работаеш. и т.д. ...
извини, на остальное реагировать не буду, больно много у тебя "нестыковок" в связках желания-знания. опровергать/доказывать все лень.
но вопрос похоже решон? все что изначально описано выполнилось. другое дело хотел ты оказывается не того.


 
mvg_first   (2004-01-29 11:48) [51]

sniknik © (29.01.04 10:20) [50]
Именно так неработает - поле в таблице (MSSQL2000) описано как IDENTITY, и именно снимал флаг только для чтения и именно проставлял значение - нихрена, хотя другие поля по такому же принципу в гриде обновляются.

Вопрос решил
Все таки написал свой компонент потомок TCustomADODataset и в нем вызывал Requery после чего позиционировался на записи по ключевому полю (ID) используюя LOCATE


 
sniknik   (2004-01-29 12:03) [52]

> Именно так неработает - поле в таблице (MSSQL2000) описано как IDENTITY, и именно снимал флаг только для чтения и именно проставлял
> значение - нихрена, хотя другие поля по такому же принципу в гриде обновляются.

надеюсь говорим про тот ADOQuery1 у которого коннекшн отключен, и про изменения в рекордсете а не в базе->таблице.
счас проверю, я так делал для аксесной базы у которой тоже ID IDENTITY(1,1), может MSSQL чтото еще в настройку передает.

> Вопрос решил
поздравляю. ;о)) (но проверю все одно, просто для себя)


 
Polevi   (2004-01-29 12:12) [53]

>sniknik © (29.01.04 12:03) [52]
у меня не получалось в отсоединенном рекордсете присвоить значение AutoInc полю, ReadOnly:=false не помогало, а подменить метаданные я не нашел способа, кроме парсинга XML


 
sniknik   (2004-01-29 12:27) [54]

Polevi © (29.01.04 12:12) [53]
странно. у меня и для MSSQL также работает. пример могу прислать. (???) хотя чего там, 3 строчки всего, но все одно чтото значит не так.
курсор локальный?
данные остались посде отсоеденения?
в гриде меняются/добавляются?


 
mvg_first   (2004-01-29 12:32) [55]

Может у нас весрии ADO разные?
Все то что ты писал - я делал на стандартном ADQQuery, Delphi7


 
sniknik   (2004-01-29 12:57) [56]

в общем высылаю обоим, если у вас не работает то значит адо версия виновата. (хз. у меня вроде не последняя версия, что там в SP4 для w2k. стоит, после ного обновлений не качал)

там переделано, надо открыть и кнопку нажать, увидите какую ;о)), после можно и в гриде автонкремент править и так (первая запись сразу должна последней стать, меняется и индекс по нему).

зы... а ящика то я не нашол, ну чтож после.


 
Polevi   (2004-01-29 12:59) [57]

>sniknik © (29.01.04 12:27) [54]
у меня 3-звенка
на среднем звене делается выборка, курсор локальный, рекордсет отсоединятеся и возращается клиенту как результат вызова фасадной ф-ии
на клиенте это выглядит как
MyAdoDataset.RecordSet:=Facade.SelectSomeData;

и после этого
MyAdoDataset.Insert;
MyAdoDataset.FieldByName("AutoIncField").ReadOnly:=false;
MyAdoDataset.FieldByName("AutoIncField").AsInteger:=666;
MyAdoDataset.Post;
не работало, может тупил конечно, но вопрос я изучал конкретно, так что ???
в результате перешел на CLientDataset и не жалею


 
sniknik   (2004-01-29 13:12) [58]

вот мое проверочное, без трехзвенки

ADODataSet1.Open;
ADODataSet1.Connection:= nil;
ADODataSet1.Sort:= "AUTOID";
ADODataSet1.FieldByName("AUTOID").ReadOnly:= false;
ADODataSet1.Edit;
ADODataSet1.FieldByName("AUTOID").AsInteger:= 201; //первую запись на последнее место
ADODataSet1.Post;

AUTOID создан с AUTOID INT IDENTITY (1,1)
и после прям в базе назначен ключом.
не знаю, все вроде похоже может только
MyAdoDataset.FieldByName("AutoIncField").ReadOnly:=false;
MyAdoDataset.Insert;
???

треззвенка вроде бы влиять не должна.


 
sniknik   (2004-01-29 13:16) [59]

отперестановки мест слагеемых сумма не меняется... ;о)

Polevi © (29.01.04 12:59) [57]
а если явно
MyAdoDataset.Connection:= nil; прописать?
или уже ломает менять чегонибудь? CLientDataset тоже неплохо :о), жаль только *.cds сохраненный из ADODataSet не открывает. :(


 
Polevi   (2004-01-29 14:06) [60]

>sniknik © (29.01.04 13:16) [59]
>а если явно
>MyAdoDataset.Connection:= nil; прописать?
на клиенте Connection не определен вообще за ненадобностью, как на форму бросили его так там нил с тех пор и лежит :)


 
sniknik   (2004-01-29 14:19) [61]

> на клиенте Connection не определен вообще за ненадобностью, как на форму бросили его так там нил с тех пор и лежит :)
это понятно, но разница то есть, может она в методе отсоеденения от базы (которая у тебя впрочем не выполнится
там код

procedure TCustomADODataSet.SetConnection(const Value: TADOConnection);
begin
if Connection <> Value then
begin
.....

)

даже скорее всего именно изза этого, вот переделал немного, перестало работать!!! (в смысле редактироватся ID)

ADODataSet2.Clone(ADODataSet1);
ADODataSet2.Sort:= "AUTOID";
ADODataSet2.FieldByName("AUTOID").ReadOnly:= false;
ADODataSet2.Edit;
ADODataSet2.FieldByName("AUTOID").AsInteger:= 201; //первую запись на последнее место
ADODataSet2.Post;
DataSource1.DataSet:= ADODataSet2;


ADODataSet2 также просто бросил на форму, без подключений и т.д.


 
Polevi   (2004-01-29 14:25) [62]

ну вот, я же говорил !
:-)


 
lmatveev   (2004-01-29 14:36) [63]

Вот так это работает:

TAEMADOQuery = class(TADOQuery)
private
FKeyField: string;
FInsertSQL: TStrings;
FUpdateSQL: TStrings;
FDeleteSQL: TStrings;
FKeyValue: variant;
function GetKeyFieldValue: variant;
function DoExecSQL(aSQL: string): variant;
procedure SetInsertSQL(Value: TStrings);
procedure SetUpdateSQL(Value: TStrings);
procedure SetDeleteSQL(Value: TStrings);
protected
procedure DoAfterOpen; override;
procedure DoBeforeClose; override;
procedure InternalPost; override;
procedure InternalDelete; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure RefreshDataSet; // Делает DisableControls, затем переоткрывается и делает EnableControls
property KeyFieldValue: variant read GetKeyFieldValue;
published
property SQLInsert: TStrings read FInsertSQL write SetInsertSQL; // Пользовательская команда на Insert. Если не указана - выполняется стандартная
property SQLUpdate: TStrings read FUpdateSQL write SetUpdateSQL; // Пользовательская команда на Insert. Если не указана - выполняется стандартная
property SQLDelete: TStrings read FDeleteSQL write SetDeleteSQL; // Пользовательская команда на Insert. Если не указана - выполняется стандартная
property KeyField: string read FKeyField write FKeyField; // Название ключевого поля. Если указано, то после открытия позиционируется на значение, которое было до закрытия
end;

implementation

constructor TAEMADOQuery.Create;
begin
inherited Create(AOwner);
FInsertSQL := TStringList.Create;
FUpdateSQL := TStringList.Create;
FDeleteSQL := TStringList.Create;
end;

destructor TAEMADOQuery.Destroy;
begin
FInsertSQL.Free;
FUpdateSQL.Free;
FDeleteSQL.Free;
inherited Destroy;
end;

function TAEMADOQuery.GetKeyFieldValue: variant;
begin
if Active and (FindField(KeyField) <> nil) then Result := FieldByName(KeyField).Value else Result := null;
end;

procedure TAEMADOQuery.InternalPost;
var
id: variant;
i: integer;
begin
id := null;
if ((State = dsEdit) and (Trim(FUpdateSQL.Text) = "")) or
((State = dsInsert) and (Trim(FInsertSQL.Text) = "")) then
inherited InternalPost
else begin
for I := 0 to Fields.Count - 1 do
with Fields[I] do
if Required and not ReadOnly and (FieldKind = fkData) and IsNull then
begin
FocusControl;
DatabaseErrorFmt(SFieldRequired, [DisplayName]);
end;
if State = dsEdit then
id := DoExecSQL(FUpdateSQL.Text)
else
id := DoExecSQL(FInsertSQL.Text);
if (KeyField <> "") and not(VarIsEmpty(id) or VarIsNull(id)) then
Locate(KeyField, id, []);
end;
end;

procedure TAEMADOQuery.InternalDelete;
var
id: variant;
begin
if (Trim(FDeleteSQL.Text) = "") then
inherited InternalDelete
else begin
id := DoExecSQL(FDeleteSQL.Text);
if (KeyField <> "") and not(VarIsEmpty(id) or VarIsNull(id)) then
Locate(KeyField, id, []);
end;
end;

function TAEMADOQuery.DoExecSQL;
var
FCommand: TADOCommand;
i: integer;
begin
Result := null;
FCommand := TADOCommand.Create(Self);
try
if ConnectionString <> "" then FCommand.ConnectionString := ConnectionString
else FCommand.Connection := Connection;
FCommand.CommandText := aSQL;
for i := 0 to FCommand.Parameters.Count-1 do
if FindField(FCommand.Parameters[i].Name) <> nil then begin
FCommand.Parameters[i].Assign(FieldByName(FCommand.Parameters[i].Name));
if FieldByName(FCommand.Parameters[i].Name).IsNull then
FCommand.Parameters[i].Value := null;
if FCommand.Parameters[i].Name = KeyField then FCommand.Parameters[i].Direction := pdInputOutput;
end
FCommand.Execute;
if FCommand.Parameters.FindParam(KeyField) <> nil then
Result := FCommand.Parameters.ParamByName(KeyField).Value;
finally
FCommand.Free;
end;
RefreshDataSet;
end;

procedure TAEMADOQuery.RefreshDataSet;
begin
if not Active then exit;
DisableControls;
try
Close;
Open;
finally
EnableControls;
end;
end;

procedure TAEMADOQuery.SetInsertSQL;
begin
FInsertSQL.Assign(Value);
end;

procedure TAEMADOQuery.SetUpdateSQL;
begin
FUpdateSQL.Assign(Value);
end;

procedure TAEMADOQuery.SetdeleteSQL;
begin
FDeleteSQL.Assign(Value);
end;

procedure TAEMADOQuery.DoBeforeClose;
var
Field: TField;
begin
inherited DoBeforeClose;
Field := FindField(KeyField);
if Field <> nil then FKeyValue := Field.Value
else FKeyValue := Unassigned;
end;

procedure TAEMADOQuery.DoAfterOpen;
var
Field: TField;
begin
Field := FindField(KeyField);
if (Field <> nil) and not(VarIsEmpty(FKeyValue)) then begin
if not(VarIsNull(FKeyValue)) then
try
Locate(Field.FieldName, FKeyValue, [])
except
end
else
if Field.ReadOnly then Last;
end;
inherited DoAfterOpen;
end;


... и дальше забываем, что это не обычный DataSet. При вставке новый ID возвращаем output параметром. Заодно этот компоент после переоткрытия позиционируется на запись, которая была активна перед закрытием :))
Можно также расставить флагов и чуть-чуть модифицировать, чтобы снизить накладные расходы при переоткрывании


 
mvg_first   (2004-01-29 14:39) [64]

Извините за возможно глупый вопрос - но что такое CClientDataSet - все классы в дельфине насколько я знаю обычно начинаются с "T". А с "C" начинаются классы писанные на Visual С++. И по ходу вопрос где можно посмотреть примерчик работы трехзвенки с таким вот классом


 
sniknik   (2004-01-29 14:39) [65]

Polevi © (29.01.04 14:25) [62]
> ну вот, я же говорил !
> :-)

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

если чегото нужно то делать надо так как работает (чего и расписывал), а если понимать все по своему и под себя переделывать то и удивлятся не надо почему не работает.


 
sniknik   (2004-01-29 14:41) [66]

mvg_first © (29.01.04 14:39) [64]
описка скорее всего
ClientDataSet1: TClientDataSet;

> И по ходу вопрос где можно посмотреть примерчик работы трехзвенки с таким вот классом
в дельфях пример есть вроде


 
mvg_first   (2004-01-29 14:45) [67]

lmatveev (29.01.04 14:36) [63]
Блин - у меня такой же код (ну почти такой же) единственное что не так я при инсерте пробую получить IDENTITY используюя функцию MSSQL SCOPE_IDENTITY() и позиционирую запись именно на этом идентификаторе.
Сходу получается ограничение на использование такого компонента в том что таблица должна иметь обязательный превичный ключи (автоинкремент). Хотя это и не сильно уж трудно и тяжело (почит все таблицы в стандартных прикладных задачах его имеют)



Страницы: 1 2 вся ветка

Форум: "Базы";
Текущий архив: 2004.02.25;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.61 MB
Время: 0.034 c
14-80120
psyched
2004-02-02 17:42
2004.02.25
Исходные тексты VCL


3-79654
Lucky[ELF]
2004-01-31 01:23
2004.02.25
Как правильно настроить IB6.0 сервер и клиент


1-79768
CAHbI4
2004-02-11 21:41
2004.02.25
Содержимое DLL формы на форме вызывающего приложения


14-80156
Petr V. Abramov
2004-02-01 17:19
2004.02.25
Аргументы за переход на .NET


1-79888
suric
2004-02-10 11:26
2004.02.25
Динамическое создание объектов и ScrollBar





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский