DICAS

Visite a biblioteca de dicas da comunidade.

Saiba mais

ARTIGOS

Abordagens detalhadas sobre assuntos diversos.

Saiba mais

INICIANTES

Aprenda a programar de um modo simples e fácil.

Saiba mais

DOWNLOADS

Acesse os materiais exclusivos aos membros.

Saiba mais
voltar

PARA QUEM GOSTA DE DELPHI

Classe que auxilia a persistência de dados com ClientDataSet

Autor: Caique Rodrigues

Muitas vezes ao utilizar ClientDataSets, esquecemos que é necessário
implementar algum código para exibir alguma mensagem quando ocorre
algum erro.

Esta classe já nos fornece alguns métodos que facilitam o nosso trabalho
com a manipulação de dados com ClientDataSets.

Confira o código abaixo:

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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
unit CDSSuppl;
 
interface
 
uses
  SysUtils, DB, DBClient;
 
type
  TCDSSuppl = class
  private
    class procedure DefaultReconcileError(DataSet: TCustomClientDataSet;
      E: EReconcileError; UpdateKind: TUpdateKind;
      var Action: TReconcileAction);
  public
    class procedure PostIfNeed(ClientDataSet: TClientDataSet);
    class procedure ApplyUpdates(ClientDataSet: TClientDataSet;
      MaxErrors: integer = 0);
    class procedure CopyDataSet(Source: TClientDataSet;
      var Target: TClientDataSet; AllRecords: boolean = True);
    class procedure CopyDataSetStruct(Source: TClientDataSet;
      var Target: TClientDataSet);
    class procedure CopyDataSetRecord(Source, Target: TClientDataSet);
    class procedure InsertRecordFromDataSet(Source, Target: TClientDataSet);
    class procedure InsertAllRecordsFromDataSet(Source, Target: TClientDataSet);
    class function SaveRunTimeIndexes(ClientDataSet: TClientDataSet)
      : TIndexDefs;
    class procedure RestoreRunTimeIndexes(ClientDataSet: TClientDataSet;
      AIndexDefs: TIndexDefs; AFreeIndexDefs: boolean = True);
  end;
 
implementation
 
{ TCDSSuppl }
 
var
  FErrorMsg: string;
 
const
  StrUpdtKind: array [TUpdateKind] of string = ('Modificação', 'Inserção',
    'Exclusão');
 
class procedure TCDSSuppl.ApplyUpdates(ClientDataSet: TClientDataSet;
  MaxErrors: integer = 0);
begin
  if not assigned(ClientDataSet.OnReconcileError) then
    ClientDataSet.OnReconcileError := TCDSSuppl.DefaultReconcileError;
  if ClientDataSet.ApplyUpdates(MaxErrors) <> 0 then
    Raise Exception.Create(FErrorMsg);
end;
 
class procedure TCDSSuppl.CopyDataSet(Source: TClientDataSet;
  var Target: TClientDataSet; AllRecords: boolean = True);
var
{$IFDEF _2010}
  bm: TBookmark;
{$ELSE}
  bm: TBookmarkStr;
{$ENDIF}
begin
  CopyDataSetStruct(Source, Target);
 
  if not AllRecords then
  begin
    CopyDataSetRecord(Source, Target);
    exit;
  end;
 
  Target.DisableControls;
 
  Source.DisableControls;
 
  bm := Source.Bookmark;
  Source.First;
  while not Source.Eof do
  begin
    CopyDataSetRecord(Source, Target);
    Source.Next;
  end;
  Source.Bookmark := bm;
  Source.EnableControls;
 
  Target.EnableControls;
end;
 
class procedure TCDSSuppl.CopyDataSetStruct(Source: TClientDataSet;
  var Target: TClientDataSet);
var
  indxField: integer;
begin
  if not assigned(Target) then
    Target := TClientDataSet.Create(nil);
 
  if Target.Active then
    Target.Close;
 
  Target.FieldDefs.BeginUpdate;
  Target.FieldDefs.Clear;
 
  with Source do
    for indxField := 0 to FieldCount - 1 do
      with Fields[indxField] do
        if (DataType = ftString) then
          Target.FieldDefs.Add(FieldName, DataType, DataSize, False)
        else if (DataType = ftFMTBcd) then
          Target.FieldDefs.Add(FieldName, DataType,
            TFMTBCDField(Fields[indxField]).Size, False)
        else
          Target.FieldDefs.Add(FieldName, DataType, 0, False);
 
  Target.FieldDefs.EndUpdate;
 
  Target.CreateDataSet;
end;
 
class procedure TCDSSuppl.CopyDataSetRecord(Source, Target: TClientDataSet);
var
  I: integer;
  Field: TField;
  InEditMode: boolean;
begin
  InEditMode := Target.State in [dsInsert, dsEdit];
 
  if not InEditMode then
    Target.Append;
 
  with Target do
  begin
    for I := 0 to FieldCount - 1 do
    begin
      Field := Source.FindField(Fields[I].FieldName);
      if assigned(Field) then
        Fields[I].Assign(Field);
    end;
  end;
 
  if not InEditMode then
    Target.Post;
end;
 
class procedure TCDSSuppl.DefaultReconcileError(DataSet: TCustomClientDataSet;
  E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction);
begin
  FErrorMsg := StrUpdtKind[UpdateKind];
  FErrorMsg := FErrorMsg + #13#10 + E.Message;
  FErrorMsg := FErrorMsg + #13#10 + intToStr(E.ErrorCode);
 
  if E.Context <> '' then
    FErrorMsg := FErrorMsg + #13#10 + 'Contexto: ' + E.Context;
 
  FErrorMsg := FErrorMsg + #13#10 + DataSet.Name;
 
  if UpdateKind = ukDelete then
    Action := raCancel
  else
    Action := raAbort;
end;
 
class procedure TCDSSuppl.InsertAllRecordsFromDataSet(Source,
  Target: TClientDataSet);
begin
  with Source do
  begin
    DisableControls;
    First;
    while not Eof do
    begin
      InsertRecordFromDataSet(Source, Target);
      Next;
    end;
    First;
    EnableControls;
  end;
end;
 
class procedure TCDSSuppl.InsertRecordFromDataSet(Source,
  Target: TClientDataSet);
begin
  Target.Insert;
  CopyDataSetRecord(Source, Target);
  Target.Post;
end;
 
class procedure TCDSSuppl.PostIfNeed(ClientDataSet: TClientDataSet);
begin
  if ClientDataSet.State in [dsInsert, dsEdit] then
    ClientDataSet.Post;
end;
 
class function TCDSSuppl.SaveRunTimeIndexes(ClientDataSet: TClientDataSet)
  : TIndexDefs;
var
  x: integer;
begin
  Result := TIndexDefs.Create(nil);
 
  if ClientDataSet.Active then
  begin
    ClientDataSet.IndexDefs.Update;
    for x := 0 to ClientDataSet.IndexDefs.Count - 1 do
      if (ixNonMaintained in ClientDataSet.IndexDefs[x].Options) then
        Result.AddIndexDef.Assign(ClientDataSet.IndexDefs[x]);
  end;
end;
 
class procedure TCDSSuppl.RestoreRunTimeIndexes(ClientDataSet: TClientDataSet;
  AIndexDefs: TIndexDefs; AFreeIndexDefs: boolean);
var
  x: integer;
begin
  if assigned(AIndexDefs) then
  begin
    for x := 0 to AIndexDefs.Count - 1 do
      with ClientDataSet.IndexDefs.AddIndexDef do
        Assign(AIndexDefs[x]);
    AIndexDefs.Update;
    if AFreeIndexDefs then
      AIndexDefs.Free;
  end;
end;
 
end.

Exemplo de uso para salvar dados:

1
2
3
4
5
procedure TForm1.BtnSalvarClick(Sender: TObject);
begin
  TCDSSuppl.PostIfNeed(ClientDataSet1);
  TCDSSuppl.ApplyUpdates(ClientDataSet1, 0);
end;
Facebook Comments Box
  • InfusTec
  • 4.854 views
  • 0 comentários
  • 2 de setembro de 2016

Está gostando do conteúdo? Considere pagar um cafezinho para nossa equipe!

Deixe um comentário

Ir ao topo

© 2024 Infus Soluções em Tecnologia - Todos os Direitos Reservados