Как записать/ прочитать динамический массив в BLOB поле

FIL23
Дата: 29.11.2019 09:15:15
Добрых суток,

Собственно сам сабж. (я не программист, я системный администратор)

Имеется класс

      MasOfObjectsOfInventory = record
      ID:integer;         
      ObjectName: string;
      end;


Имеем динамический массив
var
masObjectsOfInventoryOnStart:array of MasOfObjectsOfInventory ;


...
тут действия с массивом, установка его размера и занесение в него данных
...

Пытаюсь записать в BLOB
insertDataInTableofBLOBField(masObjectsOfInventoryOnStart);

function insertDataInTableofBLOBField(masObjectsOfInventoryOnStart:MasOfObjectsOfInventory):BOOLEAN;

var
  per_IBQuery:TIBQuery;
  Stm: TMemoryStream;
  Len1, Len2: LongInt;
  Str1, Str2: WideString;
begin   
      // процедура для записи введеных данных
      per_IBQuery:=my_initialization_TIBQuery_insert(per_IBQuery); //инициализируем переменную TIBQuery и передаем ей параметры подключения
      per_IBQuery.Active := False;
      per_IBQuery.SQL.Clear;
      per_IBQuery.SQL.Add('insert into HISTORY_INVENTORY '
                          + '(ID_INVENTORY, '                   { ид Представителя в дереве }
                          + ' HISTORY '
                          + ')'
                          + ' values ( '
                          + ':perID_INVENTORY, '
                          + ':perHISTORY '
                          + ')');


      Stm := TMemoryStream.Create;
      try

      Stm.Write(masObjectsOfInventoryOnStart, sizeof(masObjectsOfInventoryOnStart));


      Stm.Position := 0;
      per_IBQuery.ParamByName('perHISTORY').LoadFromStream( Stm, ftBlob);
      finally
      FreeAndNil(Stm)
      end;

      if  perID_INVENTORY=0         then per_IBQuery.ParamByName('perID_INVENTORY').IsNull  else  per_IBQuery.ParamByName('perID_INVENTORY').AsInteger:=perID_INVENTORY;

      per_IBQuery.ExecSQL;
      fmConnectToBase.IBTransaction2.Commit;
      FreeAndNil(per_IBQuery); //Эквивалентно: People. Free; People := nil;



Вроде записывает все ок тут

Но вот как считать правильно?


Пытаюсь так

function GetDataFromBLOB(perID:integer):MasOfObjectsOfInventory;

var
  per_IBQuery:TIBQuery;
  stm: TStream;
  Len, Len2: LongInt;
  Str, Str2: WideString;
  perParameterHistoryInventory:type_InventoryHistory;

begin
per_IBQuery:=my_initialization_TIBQuery_insert(per_IBQuery); //инициализируем переменную и передаем ей параметры
per_IBQuery.Active:=false;
per_IBQuery.SQL.Clear;
per_IBQuery.SQL.Add('select * from HISTORY_INVENTORY WHERE ID = :perID');
if  perID=0 then per_IBQuery.ParamByName('perID').IsNull else  per_IBQuery.ParamByName('perID').AsInteger:=perID;
per_IBQuery.Active:=true;
per_IBQuery.Last;


stm := per_IBQuery.CreateBlobStream( per_IBQuery.FieldByName('HISTORY'), bmRead);
   try 
   Stm.Position:=0;

   Stm.Read(masObjectsOfInventoryOnStart,                      sizeof(masObjectsOfInventoryOnStart));

   result:=masObjectsOfInventoryOnStart;
   finally
      FreeAndNil(Stm);
   end;

end;


И получаю ошибку вида:

---------------------------
Debugger Exception Notification
---------------------------
Project alladmin.exe raised exception class EAccessViolation with message 'Access violation at address 00405864 in module 'alladmin.exe'. Read of address 01DBE13C'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------

Я так понимаю надо задать размер массива , а как это сделать? это ж надо как то вычислить размер , я не совсем догоняю
ёёёёё
Дата: 29.11.2019 09:40:10
FIL23,

1. используй TIBSQL, зачем тебе эта TIBQuery.

var
  fQ : TIBSQL;
  fMS : TMemoryStream;
  faI : array of Integer;
begin
  fMS := TMemoryStream.Create;
...
  fQ.FieldByName('123').SaveToStream(fMS);
  SetLength(faI, fMS.Size div sizeOf(Integer));
  if fMS.Size > 0 then
    CopyMemory(@faI[0], fMS.Memory, Length(faI) * SizeOf(Integer));


2. Хер тебе, а не запись массива в блоб
type
      MasOfObjectsOfInventory = record
      ID:integer;         
      ObjectName: string;
      end;
var
masObjectsOfInventoryOnStart:array of MasOfObjectsOfInventory ;

Строки хранятся "совсем в другом месте", а не в самой записи. В самой записи - только указатель на строку.
Используй паскалевские строки, с указанием их размеров. А не дельфийские.
wadman
Дата: 29.11.2019 09:47:49
FIL23
Но вот как считать правильно?

п.1 Сначала нужно записать количество записей, а перед чтением прочитать это количество.
Плюс, либо
ёёёёё
Используй паскалевские строки, с указанием их размеров. А не дельфийские.

Либо вручную писать каждый record, а строку писать аналогично п.1 - сначала длину строки, затем её содержимое.
FIL23
Дата: 29.11.2019 09:50:33
про TIBSQL кто с чем привык работать. я тут уже куча строк написал на TIBQuery, в будущих проектах попробую посмотреть в сторону TIBSQL



Про string. Что там не так , можно поподробней?

т.е. я должен писать string[255] ?
wadman
Дата: 29.11.2019 09:57:56
FIL23
Про string. Что там не так , можно поподробней?

Современная строка это ссылка на кусок памяти, где символы этой строки.
FIL23
т.е. я должен писать string[255] ?

Типа того. Чем меньше, тем лучше для базы.
alekcvp
Дата: 29.11.2019 10:09:12
FIL23
Про string. Что там не так , можно поподробней?
Расположение в памяти там не так:
Картинка с другого сайта.
FIL23
Дата: 29.11.2019 10:17:12
Хорошо,

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

function insertDataInHistory_InventoryTable(perID_INVENTORY:integer; perParameterHistoryInventory:type_InventoryHistory):BOOLEAN;

    procedure WriteStringToStream(perStm:TMemoryStream;perStr:WideString);
      var
        perLen:LongInt;
      begin
      perLen := Length(perStr);
      perStm.Write(perLen, SizeOf(perLen));
      if perLen > 0 then
        perStm.Write(perStr[1], Length(perStr) * SizeOf(perStr[1]));
      end;

var
  per_IBQuery:TIBQuery;
  Stm: TMemoryStream;
  Len1, Len2: LongInt;
  Str1, Str2: WideString;
begin   
      // процедура для записи введеных данных
      per_IBQuery:=my_initialization_TIBQuery_insert(per_IBQuery); //инициализируем переменную и передаем ей параметры
      per_IBQuery.Active := False;
      per_IBQuery.SQL.Clear;
      per_IBQuery.SQL.Add('insert into HISTORY_INVENTORY '
                          + '(ID_INVENTORY, '                   { ид Представителя в дереве }
                          + ' HISTORY '
                          + ')'
                          + ' values ( '
                          + ':perID_INVENTORY, '
                          + ':perHISTORY '
                          + ')');


      Stm := TMemoryStream.Create;
      try
      Stm.Write(perParameterHistoryInventory.UserID_,     sizeof(perParameterHistoryInventory.UserID_) );//кто  //первый параметр что записываем , второй параметр сколько записываем, потом указатель сам Cдвигается


      WriteStringToStream(Stm, perParameterHistoryInventory.Path_before);       //путь до объекта до
   

      Stm.Position := 0;
      per_IBQuery.ParamByName('perHISTORY').LoadFromStream( Stm, ftBlob);
      finally
      FreeAndNil(Stm)
      end;

      if  perID_INVENTORY=0         then per_IBQuery.ParamByName('perID_INVENTORY').IsNull  else  per_IBQuery.ParamByName('perID_INVENTORY').AsInteger:=perID_INVENTORY;

      per_IBQuery.ExecSQL;
      fmConnectToBase.IBTransaction2.Commit;
      FreeAndNil(per_IBQuery); //Эквивалентно: People. Free; People := nil;
end;
//******************************************************************************
//******************************************************************************



т.е. ваш совет динамический массив заганять в цикл и записывать уже построчно в BLOB?
ёёёёё
Дата: 29.11.2019 10:24:04
FIL23
у меня есть написанная та же функция с записями стринг полей


поле.AsString := 'Колбаса'

- не?
ёёёёё
Дата: 29.11.2019 11:20:54
FIL23,

в чем вопрос?