Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Базы данных
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 06.04.2007, 14:51
Holy Holy вне форума
Новичок
 
Регистрация: 31.07.2006
Сообщения: 55
Репутация: 10
По умолчанию ClientDataSet и 'Key violation'

Ситуация:
Я выбираю данные из таблицы, с двумя полями ID (ключевое Integer) и Name (Char(15)), используя компонент TClientDataSet.

Код:
cdsSelect: TClientDataSet;
...
with cdsSelect do
begin
  if Active then
    cdsSelect.Close;
  CommandText := 'Select ID, Name from TestTable';
  Open;
end;

Данные помещаю в локальный набор данных на форме:

Код:
cdsLocal.Data := cdsSelect.Data;

В определенный момент я вставляю новую запись:

Код:
with cdsLocal do
begin
  Insert;
  FieldByName('ID').AsInteger := 1;
  Post;
end;

На Post возникает ошибка EDBClient 'Key violation'.

Хочу обратить внимание, что я работаю именно с локальным набором, не имеющим связи с БД (портфель).
Я пытался менять совойства:
Код:
FieldDefs[0].Attributes := [];
FieldDefs[0].Required;
Fields[0].Required := False;
Fields[0].ProviderFlags := [];
Ошибка осталась.

Кто знает, в чем может быть проблема?
Ответить с цитированием
  #2  
Старый 06.04.2007, 18:37
Аватар для mav_c
mav_c mav_c вне форума
Активный
 
Регистрация: 26.03.2007
Адрес: Москва
Сообщения: 287
Репутация: 30
По умолчанию

Цитата:
Сообщение от Holy
Ситуация:
Я выбираю данные из таблицы, с двумя полями ID (ключевое Integer) и Name (Char(15)), используя компонент TClientDataSet.

Код:
cdsSelect: TClientDataSet;
...
with cdsSelect do
begin
  if Active then
    cdsSelect.Close;
  CommandText := 'Select ID, Name from TestTable';
  Open;
end;

Данные помещаю в локальный набор данных на форме:

Код:
cdsLocal.Data := cdsSelect.Data;

В определенный момент я вставляю новую запись:

Код:
with cdsLocal do
begin
  Insert;
  FieldByName('ID').AsInteger := 1;
  Post;
end;

На Post возникает ошибка EDBClient 'Key violation'.

Хочу обратить внимание, что я работаю именно с локальным набором, не имеющим связи с БД (портфель).
Я пытался менять совойства:
Код:
FieldDefs[0].Attributes := [];
FieldDefs[0].Required;
Fields[0].Required := False;
Fields[0].ProviderFlags := [];
Ошибка осталась.

Кто знает, в чем может быть проблема?
А у тебя айди 1 нет в этом датасэте??? Ты даже в локальном ДС не добавиш запись с существующим ID. При условии конечно что это поле PK
__________________
---------------------------------------------
Программирование - не профессия, а стиль жизни
Ответить с цитированием
  #3  
Старый 07.04.2007, 11:48
Holy Holy вне форума
Новичок
 
Регистрация: 31.07.2006
Сообщения: 55
Репутация: 10
По умолчанию

Конечно есть. Собственно из-за этого он и ругается.
Но у меня задача клонировать в наборе запись вместе с ее ключом. Сохранять в базу я это дело не буду.

"Быстрым" решением стало, заменить присвоение Data := Date на тупую пробежку по всему набору источнику и вставку записей в приемник Insert, Post. Структура приемника идентична, но формируется ручками:

Код:
for i := 0 to Source.FieldDefs.Count - 1 do
    Dest.FieldDefs.Add(Source.FieldDefs[i].Name,
      Source.FieldDefs[i].DataType,
      Source.FieldDefs[i].Size);

Dest.CreateDataSet;

with Source do
begin
  Source.First;
  while not Eof do
  begin
    Dest.Insert;
    
    for i := 0 to Fields.Count - 1 do
      Dest.Fields[i].Value := Fields[i].Value;
    
    Dest.Post;
    
    Source.Next;
  end;
end;

Работает это процентов на 80 медленнее, а быстрым называется только потому, что воткнуто быстро. =)

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

Есть мнения?
Ответить с цитированием
  #4  
Старый 09.04.2007, 18:14
Аватар для mav_c
mav_c mav_c вне форума
Активный
 
Регистрация: 26.03.2007
Адрес: Москва
Сообщения: 287
Репутация: 30
По умолчанию

Цитата:
Сообщение от Holy
Конечно есть. Собственно из-за этого он и ругается.
Но у меня задача клонировать в наборе запись вместе с ее ключом. Сохранять в базу я это дело не буду.

"Быстрым" решением стало, заменить присвоение Data := Date на тупую пробежку по всему набору источнику и вставку записей в приемник Insert, Post. Структура приемника идентична, но формируется ручками:

Код:
for i := 0 to Source.FieldDefs.Count - 1 do
    Dest.FieldDefs.Add(Source.FieldDefs[i].Name,
      Source.FieldDefs[i].DataType,
      Source.FieldDefs[i].Size);

Dest.CreateDataSet;

with Source do
begin
  Source.First;
  while not Eof do
  begin
    Dest.Insert;
    
    for i := 0 to Fields.Count - 1 do
      Dest.Fields[i].Value := Fields[i].Value;
    
    Dest.Post;
    
    Source.Next;
  end;
end;

Работает это процентов на 80 медленнее, а быстрым называется только потому, что воткнуто быстро. =)

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

Есть мнения?
Опиши полностью задачу. Может быть можно обойтись без локального датасэта
__________________
---------------------------------------------
Программирование - не профессия, а стиль жизни
Ответить с цитированием
  #5  
Старый 10.04.2007, 10:47
Holy Holy вне форума
Новичок
 
Регистрация: 31.07.2006
Сообщения: 55
Репутация: 10
По умолчанию

Решил проблему следующим образом:
Создал локальный набор данных с заранее определенными полями. Настроил как мне надо. Данные присваиваю так:

Код:
if cdsDest.Active then
  cdsDest.EmptyDataSet;
cdsDest.Open;
cdsDest.AppendData(cdsSource.Data, True);

Копируются только данные, а свойства полей остаются нетронутыми.
Ответить с цитированием
  #6  
Старый 10.04.2007, 18:13
Аватар для mav_c
mav_c mav_c вне форума
Активный
 
Регистрация: 26.03.2007
Адрес: Москва
Сообщения: 287
Репутация: 30
По умолчанию

Цитата:
Сообщение от Holy
Решил проблему следующим образом:
Создал локальный набор данных с заранее определенными полями. Настроил как мне надо. Данные присваиваю так:

Код:
if cdsDest.Active then
  cdsDest.EmptyDataSet;
cdsDest.Open;
cdsDest.AppendData(cdsSource.Data, True);

Копируются только данные, а свойства полей остаются нетронутыми.
Отлично.!!!
__________________
---------------------------------------------
Программирование - не профессия, а стиль жизни
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 08:36.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter