Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Копирование данных из датасета в поля класса/записи / 23 сообщений из 23, страница 1 из 1
12.11.2019, 10:58
    #39887921
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
Всем добрый день. Написал код копирования данных из любого датасета в поля любых записей или классов. Возможно кому-то будет интересно. В плане возможных доработок, можно было бы обобщить для работы со свойствами и попробовать избавится от var при передаче параметров.

Код: 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.
104.
105.
106.
107.
108.
109.
110.
111.
unit MakhDBCommon;
//(c) 2019 Makhaon Software

interface

uses
Data.DB,
System.Classes,
System.SysUtils,
System.Rtti;

type
DBFieldAttribute = class(TCustomAttribute)
strict private
FFormatParam: string;
FFieldName: string;
public
constructor Create; overload;
constructor Create(const AFieldName: string); overload;
constructor Create(const AFieldName, AFormatParam: string); overload;
property FieldName: string Read FFieldName;
property FormatParam: string Read FFormatParam;
end;

type
TDSHelper<T> = class
class procedure DataSetToVar(DataSet: TDataSet; var Variable: T; ClearRec: boolean = True);
class function DataSetToRecords(DataSet: TDataSet; OnFoundRec: TNotifyEvent = nil): TArray<T>;
end;

implementation

class procedure TDSHelper<T>.DataSetToVar(DataSet: TDataSet; var Variable: T; ClearRec: boolean = True);
var
Context: TRttiContext;
Fields: TRttiType;
Field: TRttiField;
Attr: TCustomAttribute;
AttrAs: DBFieldAttribute;
DBField: TField;
begin
if ClearRec then
Variable := Default(T);
Context := TRttiContext.Create;
try
Fields := Context.GetType(TypeInfo(T));
for Field in Fields.GetFields do
for Attr in Field.GetAttributes do
if Attr is DBFieldAttribute then
begin
AttrAs := DBFieldAttribute(Attr);
DBField := DataSet.FindField(AttrAs.FieldName);
if Assigned(DBField) then
if (Field.FieldType is TRttiStringType) then
if AttrAs.FormatParam.IsEmpty then
Field.SetValue(@Variable, TValue.From(DBField.AsString.TrimRight))
else
Field.SetValue(@Variable, TValue.From(Format(AttrAs.FormatParam, [DBField.AsString.TrimRight])))
else if Field.FieldType.Handle = TypeInfo(boolean) then
Field.SetValue(@Variable, TValue.From(DBField.AsString.StartsWith('+')))
else
Field.SetValue(@Variable, TValue.From(DBField.AsVariant));
end;
finally
Context.Free;
end;
end;

class function TDSHelper<T>.DataSetToRecords(DataSet: TDataSet; OnFoundRec: TNotifyEvent = nil): TArray<T>;
var
i: integer;
begin
with Dataset do
begin
First;
SetLength(Result, RecordCount);
i := 0;
while not Eof do
begin
TDSHelper<T>.DataSetToVar(Dataset, Result[i]);
if Assigned(OnFoundRec) then
OnFoundRec(DataSet);
Inc(i);
Next;
end;
end;
end;

{ DBFieldAttribute }

constructor DBFieldAttribute.Create;
begin
inherited Create;
FFieldName := '';
end;

constructor DBFieldAttribute.Create(const AFieldName: string);
begin
inherited Create;
FFieldName := AFieldName;
FFormatParam := '';
end;

constructor DBFieldAttribute.Create(const AFieldName, AFormatParam: string);
begin
inherited Create;
FFieldName := AFieldName;
FFormatParam := AFormatParam;
end;

end. 

...
Рейтинг: 0 / 0
12.11.2019, 11:05
    #39887928
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
Использование:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
type
 TNodeParams = record
  UID:         string;
  [DBField('AE_TITLE')]
  AETitle:     string;
  [DBField('HOSTNAME')]
  HostName:    string;
  Port:        string;
  Description: string;
  IsLite:      string;
  [DBField('IS_MOST_PRIOR')]
  IsMostPrior: string;
  [DBField('ADD_HOSTNAMES')]
  AddIPs:      string;
 end;

FDataset1.FetchAll;
TDSHelper<TNodeParams>.DataSetToRecord(FDataset1, NodeParams);
...
Рейтинг: 0 / 0
12.11.2019, 11:12
    #39887934
AlexeyM123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
в догонку
DataSet Enumerator от Uwe Raabe
https://www.uweraabe.de/Blog/?s=Dataset Enumerator
...
Рейтинг: 0 / 0
12.11.2019, 11:56
    #39887981
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
У меня на XE6 не взлетел, увы. Синтаксиса не хватает. Пришлось свой делать.
...
Рейтинг: 0 / 0
12.11.2019, 12:09
    #39887997
DimaBr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
makhaon
У меня на XE6 не взлетел, увы. Синтаксиса не хватает. Пришлось свой делать.

У меня D7 и вся ваша примочка не взлетела
...
Рейтинг: 0 / 0
12.11.2019, 12:43
    #39888019
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
DimaBr,

"В Delphi 2010 появились пользовательские атрибуты, которые можно добавить к объявлениям типов и методам"

D2010 минимум. Меньше, увы, никак.
...
Рейтинг: 0 / 0
12.11.2019, 12:53
    #39888023
AlexeyM123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
я к сожалению не могу найти ссылку, но Uwe Raabe писал,
что вся его конструкция работает на >= XE8 только
...
Рейтинг: 0 / 0
12.11.2019, 16:07
    #39888133
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
Как минимум, я бы один раз сделал сопоставление поля датасета <=> поля записи, а потом бы уже в цикле вызывал
makhaon
Код: pascal
1.
TDSHelper<T>.DataSetToVar(Dataset, Result[i]);

ну и вот это
makhaon
Код: pascal
1.
SetLength(Result, RecordCount);

работать не будет. Нужно записи складывать в TList<T>, а потом делать
Код: pascal
1.
Result := List.ToArray;



Далее, код будет работать только для Record. Для объектов классов будет AV

Ну и остальное по мелочи
...
Рейтинг: 0 / 0
12.11.2019, 20:27
    #39888273
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
_Vasilisk_,

авторSetLength(Result, RecordCount);

Это работает точно. Ну а вообще правки принимаются.
...
Рейтинг: 0 / 0
12.11.2019, 22:12
    #39888297
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
makhaon
Это работает точно.
Значит (не) повезло с датасетом. Попробуй на IBX
...
Рейтинг: 0 / 0
12.11.2019, 22:43
    #39888303
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
_Vasilisk_,

IBX/UniDAC, пока все ок. А что с IBX'ом не так? Записи если отфетчить, как я в примере написал, то будет ок. Но видимо надежнее в классее Last сделать.
...
Рейтинг: 0 / 0
13.11.2019, 17:50
    #39888752
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
makhaon
Записи если отфетчить, как я в примере написал, то будет ок
Так это же читерство.
makhaon
надежнее в классее Last сделать.
И нарваться на Unidirectional.

Надежнее вот так
_Vasilisk_
Нужно записи складывать в TList<T>, а потом делать
Код: pascal
1.
Result := List.ToArray;

...
Рейтинг: 0 / 0
13.11.2019, 17:57
    #39888758
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
Вся эта возня с ORM-ом на коленке действительно способна сэкономить время при разработки
приложения? Отсюда всё выглядит так, что проще написать десяток присваиваний, чем вот так
вот прыгать с бубном.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.11.2019, 17:59
    #39888759
Мимопроходящий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
дык тут важен сам процесс.
приседания ради приседаний.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.11.2019, 20:04
    #39888794
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
Тут как обычно дело хозяйское :) Хотите юзайте, хотите дописывайте, не хотите - пишите по-старинке.
...
Рейтинг: 0 / 0
14.11.2019, 14:09
    #39889101
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
Dimitry Sibiryakov
Вся эта возня с ORM-ом на коленке действительно способна сэкономить время при разработки
приложения? Отсюда всё выглядит так, что проще написать десяток присваиваний, чем вот так
вот прыгать с бубном.
Я писал подобную систему для конвертации из/в JSON. Теперь у меня сериализация/десериализация любого объекта/рекорда выполняется одной строкой. Ну и плюс определение атрибутов. Но у меня кода побольше будет. Сильно побольше.
...
Рейтинг: 0 / 0
14.11.2019, 19:48
    #39889282
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
_Vasilisk_,

Это отдельная проблема совсем. я с помощью SuperObject решаю. Есть там, правда, одина неприятная проблема (утечки), пришлось костыль дописывать, концов быстро не нашел.
...
Рейтинг: 0 / 0
14.11.2019, 19:58
    #39889284
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
makhaon
я с помощью SuperObject решаю
У меня на стандартном System.JSON и атрибутах. Плюс возможность задать кастомную сермализацию/десериализацию для отдельных полей. Ну и поддержка Default значений
...
Рейтинг: 0 / 0
14.11.2019, 23:20
    #39889319
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
_Vasilisk_,

стандартная мне не подходит из-за непереносимости delphi <> lazarus. у нас проекты в двух средах собираются.
...
Рейтинг: 0 / 0
15.11.2019, 00:24
    #39889325
asutp2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
makhaon,

если не секрет - а для каких ОС, которын не поддерживает делфи, собирается ваш проект на лазарусе?
...
Рейтинг: 0 / 0
15.11.2019, 10:35
    #39889419
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
asutp2,

для линукса. проекты начинались тогда, когда поддержки еще не было. ну а сейчас уже нет смысла на делфи тянуть все, под лазарем работает нормально. пока три проекта по 300-700 тысяч строк.
...
Рейтинг: 0 / 0
15.11.2019, 20:47
    #39889937
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
makhaon
asutp2,

для линукса. проекты начинались тогда, когда поддержки еще не было. ну а сейчас уже нет смысла на делфи тянуть все, под лазарем работает нормально. пока три проекта по 300-700 тысяч строк.


Под все версии линукса? Или под конкретную сборку конкретного заказчика? Аппаратная платформа x86_64? Интересно, что сейчас используется в России в бизнесе кроме x86 :)
...
Рейтинг: 0 / 0
15.11.2019, 21:35
    #39889947
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование данных из датасета в поля класса/записи
DmSer
makhaon
asutp2,

для линукса. проекты начинались тогда, когда поддержки еще не было. ну а сейчас уже нет смысла на делфи тянуть все, под лазарем работает нормально. пока три проекта по 300-700 тысяч строк.


Под все версии линукса? Или под конкретную сборку конкретного заказчика? Аппаратная платформа x86_64? Интересно, что сейчас используется в России в бизнесе кроме x86 :)


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


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