Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как записать/ прочитать динамический массив в BLOB поле / 17 сообщений из 17, страница 1 из 1
29.11.2019, 09:15
    #39896079
FIL23
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
Добрых суток,

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

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

Код: pascal
1.
2.
3.
4.
      MasOfObjectsOfInventory = record
      ID:integer;         
      ObjectName: string;
      end;



Имеем динамический массив
Код: pascal
1.
2.
var
masObjectsOfInventoryOnStart:array of MasOfObjectsOfInventory ;



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

Пытаюсь записать в BLOB
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
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;




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

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


Пытаюсь так

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
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
---------------------------

Я так понимаю надо задать размер массива , а как это сделать? это ж надо как то вычислить размер , я не совсем догоняю
...
Рейтинг: 0 / 0
29.11.2019, 09:40
    #39896091
ёёёёё
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
FIL23,

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

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
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. Хер тебе, а не запись массива в блоб
Код: pascal
1.
2.
3.
4.
5.
6.
7.
type
      MasOfObjectsOfInventory = record
      ID:integer;         
      ObjectName: string;
      end;
var
masObjectsOfInventoryOnStart:array of MasOfObjectsOfInventory ;


Строки хранятся "совсем в другом месте", а не в самой записи. В самой записи - только указатель на строку.
Используй паскалевские строки, с указанием их размеров. А не дельфийские.
...
Рейтинг: 0 / 0
29.11.2019, 09:47
    #39896100
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
FIL23
Но вот как считать правильно?

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

Либо вручную писать каждый record, а строку писать аналогично п.1 - сначала длину строки, затем её содержимое.
...
Рейтинг: 0 / 0
29.11.2019, 09:50
    #39896104
FIL23
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
про TIBSQL кто с чем привык работать. я тут уже куча строк написал на TIBQuery, в будущих проектах попробую посмотреть в сторону TIBSQL



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

т.е. я должен писать string[255] ?
...
Рейтинг: 0 / 0
29.11.2019, 09:57
    #39896107
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
FIL23
Про string. Что там не так , можно поподробней?

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

Типа того. Чем меньше, тем лучше для базы.
...
Рейтинг: 0 / 0
29.11.2019, 10:09
    #39896114
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
FIL23
Про string. Что там не так , можно поподробней?
Расположение в памяти там не так:
...
Рейтинг: 0 / 0
29.11.2019, 10:17
    #39896121
FIL23
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
Хорошо,

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

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
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?
...
Рейтинг: 0 / 0
29.11.2019, 10:24
    #39896126
ёёёёё
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
FIL23
у меня есть написанная та же функция с записями стринг полей


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


- не?
...
Рейтинг: 0 / 0
29.11.2019, 11:10
    #39896174
FIL23
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
...
Рейтинг: 0 / 0
29.11.2019, 11:20
    #39896192
ёёёёё
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
FIL23,

в чем вопрос?
...
Рейтинг: 0 / 0
29.11.2019, 11:48
    #39896229
FIL23
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
ну там показано как с record поступать.

А с массивом как?

В цикл его разворачивать ?
...
Рейтинг: 0 / 0
29.11.2019, 11:53
    #39896232
ёёёёё
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
FIL23,

при чем тут "в цикл".

Хоть одну запись. Если у тебя структура содержит ссылку - ты должен отработать этот момент. Если, конечно, тебя интересует, на что эта ссылка указывает.
...
Рейтинг: 0 / 0
29.11.2019, 14:35
    #39896417
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
FIL23
А с массивом как?
В цикл его разворачивать ?

Если там есть ссылочные типы (строки, динамические массивы и т.п.) или записи с ними, то сначала записать количество элементов, потом элементы в цикле, при этом ссылочные типы сохраняются отдельно каждый.

Если там простые типы (или записи из простых типов), то сначала количество элементов (опционально, для удобства чтения), потом весь массив одним куском.
...
Рейтинг: 0 / 0
29.11.2019, 15:37
    #39896477
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
TMasOfObjectsOfInventory = record
  ID: integer;         
  ObjectName: string;
  procedure ReadFromStream(AStream: TStream);
  procedure WriteToStream(AStream: TStream);
end

procedure TMasOfObjectsOfInventory.ReadFromStream(AStream: TStream);
var
  LLen: Integer;
begin
  AStream.WriteBuffer(ID, SizeOf(ID));
  LLen := Length(ObjectName);
  AStream.WriteBuffer(LLen, SizeOf(LLen));
  AStream.WriteBuffer(Pointer(ObjectName)^, LLen * SizeOf(Char));
end;

procedure TMasOfObjectsOfInventory.WriteToStream(AStream: TStream);
var
  LLen: Integer;
begin
  AStream.ReadBuffer(ID, SizeOf(ID));
  AStream.ReadBuffer(LLen, SizeOf(LLen));
  SetLength(ObjectName, LLen);
  AStream.ReadBuffer(Pointer(ObjectName)^, LLen * SizeOf(Char));
end;

function insertDataInTableofBLOBField(masObjectsOfInventoryOnStart:MasOfObjectsOfInventory):BOOLEAN;

var
  per_IBQuery:TIBQuery;
  Stm: TMemoryStream;
  LLen: Integer;
  Li: Integer;
begin   
  per_IBQuery:=my_initialization_TIBQuery_insert(per_IBQuery);
  try
    per_IBQuery.Transaction.Active := True;
    try
      per_IBQuery.SQL.Text := 'insert into HISTORY_INVENTORY '
                          + '(ID_INVENTORY, '                   { ид Представителя в дереве }
                          + ' HISTORY '
                          + ')'
                          + ' values ( '
                          + ':perID_INVENTORY, '
                          + ':perHISTORY '
                          + ')';

      Stm := TMemoryStream.Create;
      try
        LLen := Length(masObjectsOfInventoryOnStart);
        Strm.WriteBuffer(LLen, SizeOf(LLen));
        for Li := 0 to LLen - 1 do
          masObjectsOfInventoryOnStart[Li].WriteToStream(Strm);

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

      if  perID_INVENTORY=0  then
        per_IBQuery.ParamByName('perID_INVENTORY').>>Clear<<
      else
        per_IBQuery.ParamByName('perID_INVENTORY').AsInteger:=perID_INVENTORY;

      per_IBQuery.ExecSQL;
    finally
      per_IBQuery.Transaction.Commit;
    end;
  finally
    per_IBQuery.Free;
  end;
end;

function GetDataFromBLOB(perID:integer): MasOfObjectsOfInventory;
var
  per_IBQuery:TIBQuery;
  stm: TStream;
  LLen: Integer;
  Li: Integer;
begin
  per_IBQuery:=my_initialization_TIBQuery_insert(per_IBQuery); //инициализируем переменную и передаем ей параметры
  try
    per_IBQuery.SQL.Text := 'select * from HISTORY_INVENTORY WHERE ID = :perID';
    if  perID=0 then
      per_IBQuery.ParamByName('perID').Clear
    else
      per_IBQuery.ParamByName('perID').AsInteger:=perID;
    per_IBQuery.Active:=true;
    stm := per_IBQuery.CreateBlobStream( per_IBQuery.FieldByName('HISTORY'), bmRead);
    try 
      Stm.ReadBuffer(LLen, SizeOf(LLen));
      SetLength(Result, LLen);
      for Li := 0 to LLen - 1 do
        Result[Li].ReadFromStream(Strm);
     finally
       Stm.Free;
     end;
  finally
    per_IBQuery.Free;
  end;
end;

А если при сохранении использовать TIBSQL, то можно обойтись без ненужного копирования
FIL23
Код: pascal
1.
per_IBQuery.ParamByName('perHISTORY').LoadFromStream( Stm, ftBlob);

...
Рейтинг: 0 / 0
29.11.2019, 18:18
    #39896565
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
_Vasilisk_,

Зачёт!

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
procedure TMasOfObjectsOfInventory.ReadFromStream(AStream: TStream);
var
  LLen: Integer;
begin
  AStream.WriteBuffer(ID, SizeOf(ID));
  LLen := Length(ObjectName);
  AStream.WriteBuffer(LLen, SizeOf(LLen));
  AStream.WriteBuffer(Pointer(ObjectName)^, LLen * SizeOf(Char));
end;

procedure TMasOfObjectsOfInventory.WriteToStream(AStream: TStream);
var
  LLen: Integer;
begin
  AStream.ReadBuffer(ID, SizeOf(ID));
  AStream.ReadBuffer(LLen, SizeOf(LLen));
  SetLength(ObjectName, LLen);
  AStream.ReadBuffer(Pointer(ObjectName)^, LLen * SizeOf(Char));
end;
...
Рейтинг: 0 / 0
29.11.2019, 20:13
    #39896600
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
alekcvp,

А потом этот код будет отсюда скопипащщен и включен в новый функционал Delphi 10.3.4.
...
Рейтинг: 0 / 0
29.11.2019, 20:30
    #39896610
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как записать/ прочитать динамический массив в BLOB поле
alekcvp
Зачёт!


Потому, что с одной стороны привычка в протоколах описывать вначале запись, потом чтение. А с другой стороны в алфавитном порядке Read идет до Write
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как записать/ прочитать динамический массив в BLOB поле / 17 сообщений из 17, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]