сохранение record-переменной в БД
От: axiv  
Дата: 23.03.10 14:41
Оценка:
Здравствуйте. Помогите, измучился уже весь.
Есть TMyRec=record состоящий из полей типов integer, record, set и перечислений. Итого sizeof(TRec)=48
Вопросы в следующем:
1. Как запихнуть переменную такого типа в таблицу?
Пробовал так:
var oc:TMyRec;
    with ADOQuery1 do
    begin
      Active:=false;
      SQL.clear;
      SQL.add('INSERT INTO tmpTable (col1) VALUES(:col1)');      
      fs:=TMemoryStream.create;
      fs.WriteBuffer(oc,sizeof(oc));
      parameters.parambyname('col1').loadfromStream(fs,smReadWrite);      
      ExecSQL;
      fs.free;
    end;

Сохраняет, но как выдернуть обратно
2. Какой тип данных использовать для поля таблицы(MSSQLServer2005)?
Использовал и varbinaries, ntext, varchar, но результат один и тот же
3. Как извлечь из БД данные и запихнуть её опять в переменную?
Пробовал так:
with ADOQuery1 do
    begin
      Active:=false;
      SQL.clear;
      SQL.add('select * from tmp'); --На самом деле там пока одна запись
      active:=true;
      GetMem(buff,sizeof(oc)+1);
      ADOQuery1.Fields[0].GetData(buff,true);
      fs:=TMemoryStream.create;
      fs.WriteBuffer(buff,sizeof(oc));
      fs.seek(0,soFromBeginning);
      fs.readBuffer(oc,sizeof(oc));
      fs.free;      
    end;
record loadfromstream
Re: сохранение record-переменной в БД
От: BlackEric http://black-eric.lj.ru
Дата: 23.03.10 14:53
Оценка:
Здравствуйте, axiv, Вы писали:

Используйте packed record. И для вложенной записи тоже.
И заливайте в binary/varbinary via stream.
https://github.com/BlackEric001
Re[2]: сохранение record-переменной в БД
От: axiv  
Дата: 24.03.10 07:24
Оценка:
Здравствуйте, BlackEric, Вы писали:
BE>Используйте packed record. И для вложенной записи тоже.
BE>И заливайте в binary/varbinary via stream.

В жизни не думал что это доставит такой гемор.
Не получается Посмотрите пожалуйста, что и где неправильно делаю

  TOcur = (oNone,oDayly,oWeekly,oMounthly,oYaerly);
  TVarOcur = (vCount,vFinishDate);
  TMount = (mJan,mFeb,mMar,mApr,mMay,mJun,mJul,mAug,mSep,mOct,mNov,mDec);
  TMounts = set of TMount;
  TDay = ( dMonday, dTuesday, dWednesday, dThursday, dFriday, dSaturday,dSunday);
  TDays = set of TDay;
  TOcurDate= array of TDate;
  TOcurYearVar = (oDayEvery,oDayWeekEvery,oDay,oDayWeek);

  TOccurenceDay = packed record
    WorkDay:Boolean;
    DaysCount:Shortint;
  end;

  TOccurenceWeek = packed record
    Days:TDays;
    DaysCount:Shortint;
  end;

  TOccurenceMounth = packed record
    week:boolean;  
    Day:Shortint;
    month:Shortint;
    WeekDay:TDay;
  end;

  TOccurenceYear = packed record
    OcurVar:TOcurYearVar;
    MonthEvery:TMount;
    Day:shortint;
    WeekDay:TDay;
    month:TMounts;
  end;

  TOccurence  = packed record
    VarOcurCount:TVarOcur;
    StartDate:TDate;
    FinishDate:TDate;
    OcurCount:smallint;
    OcurVariant:TOcur;
    ocDay: TOccurenceDay;
    ocWeek: TOccurenceWeek;
    ocMonth: TOccurenceMounth;
    ocYear: TOccurenceYear;
  end;
  POccurence=^TOccurence;

var oc:TOccurence;

procedure TForm1.Save;
var fs:TMemoryStream;
begin
  with ADOQuery1 do
    begin
      Active:=false;
      SQL.clear;
      SQL.add('delete from tmp ');
      execsql;
      Active:=false;
      SQL.clear;
      SQL.add('insert into tmp (col1) values(:col)');
      fs:=TMemoryStream.Create;
      fs.WriteBuffer(oc,sizeof(oc));
      parameters.parambyname('col').LoadFromStream(fs,ftVarBytes);      
      ExecSQL;
      fs.free;
    end;
end;

procedure TForm1.Load;
var  o:POccurence;
begin
  with ADOQuery1 do
    begin
      Active:=false;
      SQL.clear;
      SQL.add('select * from tmp');
      active:=true;
      GetMem(o,sizeof(oc));
      ADOQuery1.Fields[0].GetData(o,true);
      oc:=TOccurence(o^);
    end;
end;


В базе данных поле для этой переменной использую типа VarBytes
Коннект с помощью ADO
Re[2]: сохранение record-переменной в БД
От: hattab  
Дата: 24.03.10 08:03
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE> Используйте packed record. И для вложенной записи тоже.


Вообще параллельно, в данном случае.
avalon 1.0rc2 rev 272
Re[3]: сохранение record-переменной в БД
От: DarkMaster Украина http://www.bdslib.at.ua
Дата: 24.03.10 08:52
Оценка: +1
Здравствуйте, axiv, Вы писали:

BE>>Используйте packed record. И для вложенной записи тоже.

BE>>И заливайте в binary/varbinary via stream.

A>В жизни не думал что это доставит такой гемор.

A>Не получается Посмотрите пожалуйста, что и где неправильно делаю

[...skipped...]

A>В базе данных поле для этой переменной использую типа VarBytes

A>Коннект с помощью ADO

А вам не кажется, что вообще сохранять запись как одну сущность не совсем верно? Что с ней потом делать-то будете — ни отсортировать, ни условие наложить на набор записей не получится — смысла использования БД и SQL я вообще не вижу.

P.S. Я бы создал таблицу со структурой, аналогичной вашей записи и писал бы отдельные поля, а не запись целиком.
WBR, Dmitry Beloshistov AKA [-=BDS=-]
Re: сохранение record-переменной в БД
От: FilosOFF Россия  
Дата: 24.03.10 11:05
Оценка:
Ну собственно вот:

    TMyRec = Record
          Str1 : string[50];
          Str2 : string[50];
          ID   : integer;
    End;



Var
   MR : TMyRec ;
   MR2: TMyRec ;
   ms : TMemoryStream;
   bs : TStream;
   Q  : TADOQuery;
begin
   MR.Str1:=Edit1.Text;
     MR.str2:=Edit2.Text;
     Randomize;
     MR.ID:=RANDOM(1000);

     ms:=TMemoryStream.Create;
     ms.WriteBuffer(MR,SizeOf(MR));

     Q:=TADOQuery.Create(self);
     Q.Connection:=ADOConnection1;
     Q.SQL.Text:='Insert into testData(VarData) VALUES ( :Data )';
     Q.Parameters.ParseSQL(Q.SQL.Text,true);
     Q.Parameters.ParamByName('Data').LoadFromStream(ms,ftBlob);
     Q.ExecSQL;

     FreeAndNil(ms); 


     Q.SQL.Clear;
     Q.SQL.Add('Select VarData from Testdata');
     Q.Open;

     while NOt Q.Eof do
     Begin
          bs:=Q.CreateBlobStream(Q.FieldByName('VarData'),bmRead);
          bs.ReadBuffer(MR2,bs.Size);
          FreeAndNil(bs);
          ShowMessage(MR2.Str1+#10#13+MR2.Str2+#10#13+IntToStr(MR2.ID));
          Q.Next;
     End;
     Q.Close;
     FreeAndNil(Q);
end;


Тип поля Image.
... << RSDN@Home 1.2.0 alpha 4 rev. 1231>>
Re[2]: сохранение record-переменной в БД
От: axiv  
Дата: 24.03.10 11:20
Оценка:
Здравствуйте, FilosOFF, Вы писали:

FOF>Тип поля Image.


Спасибо, именно так(s:=CreateBlobStream(Fields[0],bmRead), сам уже нашел путь.
А тип поля может быть и Text и Image, т.е. тот что IsBlob=true
Почему именно так, не пойму.
По сути CreateBlobStream делает чтение данных используя TCustomADODataSet.GetFieldData, в котором есть дополнительные преобразования, но если Native делаешь false, эти преобразования не должны выполняться.
Так что, почему именно так и только с BLOB полями это происходит не понял.
Re: сохранение record-переменной в БД
От: Dimonka Верблюд  
Дата: 24.03.10 15:16
Оценка:
Здравствуйте, axiv, Вы писали:

A>Здравствуйте. Помогите, измучился уже весь.

A>Есть TMyRec=record состоящий из полей типов integer, record, set и перечислений. Итого sizeof(TRec)=48
A>Вопросы в следующем:
A> Как запихнуть переменную такого типа в таблицу?
Можно сделать TMyRec=class, затем добавить этому классу методы .Serialize и DeSerialize, которые сохранять/восстанавливать данные в/из текста. В качестве формата можно взять XML.

Альтернативный вариант, как подсказал DarkMaster, сделать тоже из записи класс, добавить в него методы SaveToDataset/LoadFromDataset и реализовать загрузку/восстановление полей из текущей записи датасета.
Re: сохранение record-переменной в БД
От: __Azeroth__ Россия  
Дата: 01.04.10 17:55
Оценка:
Почему бы не сделать следующее:


const len=<Длина то известна заранее>;
type
  TOccurence  = packed record
   case boolean of
     True: (
           dummy:byte; // для AllInString[0]
           VarOcurCount:TVarOcur;
           StartDate:TDate;
           FinishDate:TDate;
           OcurCount:smallint;
           OcurVariant:TOcur;
           ocDay: TOccurenceDay;
           ocWeek: TOccurenceWeek;
           ocMonth: TOccurenceMounth;
           ocYear: TOccurenceYear;
           );
    False:(
           AllInString:shortstring[len];
           );
  end;

  POccurence=^TOccurence;
...
var o:TOccurence;
begin
 ADOQuery1.edit;
 ADOQuery1.Fields[0].asstring:=o.AllInString;
 ADOQuery1.post;
end;


длина записи нам известна, она меньше 255, можно использовать вариантную запись.
старый проверенный способ , а в базе хранить всё в binary char, дабы не потерять информацию ненароком.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.