Arreglado un error que se producía al comprobar si un DataTable sin deltas preparados ha sido modificado.
git-svn-id: https://192.168.0.254/svn/Proyectos.LuisLeon_FactuGES/trunk@199 c93665c3-c93d-084d-9b98-7d5f4a9c3376
This commit is contained in:
parent
72510f75e7
commit
e6e810c371
@ -3,7 +3,7 @@ unit uDataTableUtils;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
uDACDSDataTable, uDADataTable, uDAInterfaces;
|
uDACDSDataTable, uDADataTable, uDAInterfaces, uDADelta, uDAMemDataTable;
|
||||||
|
|
||||||
const
|
const
|
||||||
ID_NULO = -9000;
|
ID_NULO = -9000;
|
||||||
@ -19,9 +19,19 @@ function SetFieldNull(ATarget: TDADataTable; const FieldName: String): Boolean;
|
|||||||
procedure ConectarTabla (ATarget: TDADataTable);
|
procedure ConectarTabla (ATarget: TDADataTable);
|
||||||
procedure DesconectarTabla (ATarget: TDADataTable);
|
procedure DesconectarTabla (ATarget: TDADataTable);
|
||||||
|
|
||||||
|
procedure CopyDataTableDA5(ASource : TDADataTable; ATarget: TDADataTable;
|
||||||
|
const OnlySelectedRows : Boolean = False);
|
||||||
|
|
||||||
|
procedure CopyDataTableDA3(ASource : TDADataTable; ATarget : TDADataTable;
|
||||||
|
const OnlySelectedRows : Boolean = False);
|
||||||
|
|
||||||
procedure CloneDataTable(const ASource : TDACDSDataTable;
|
procedure CloneDataTable(const ASource : TDACDSDataTable;
|
||||||
var ATarget : TDACDSDataTable;
|
var ATarget : TDACDSDataTable;
|
||||||
RemoteUpdate: Boolean = True);
|
RemoteUpdate: Boolean = True); overload;
|
||||||
|
|
||||||
|
function CloneDataTable(const ASource : TDAMemDataTable;
|
||||||
|
RemoteUpdate: Boolean = True): TDAMemDataTable; overload;
|
||||||
|
|
||||||
|
|
||||||
procedure DuplicarRegistro(ASource : TDADataTable; ATarget : TDADataTable;
|
procedure DuplicarRegistro(ASource : TDADataTable; ATarget : TDADataTable;
|
||||||
Const WithKey: Boolean = False);
|
Const WithKey: Boolean = False);
|
||||||
@ -29,9 +39,6 @@ procedure DuplicarRegistros(ASource : TDADataTable; ATarget : TDADataTable;
|
|||||||
AModo : TModoDuplicarRegistros; APermitirRepetidos: Boolean = True;
|
AModo : TModoDuplicarRegistros; APermitirRepetidos: Boolean = True;
|
||||||
Const WithDeltas: Boolean = True; Const WithKey: Boolean = False);
|
Const WithDeltas: Boolean = True; Const WithKey: Boolean = False);
|
||||||
|
|
||||||
procedure CopyDataTable(ASource : TDADataTable; ATarget : TDADataTable;
|
|
||||||
const OnlySelectedRows : Boolean = False);
|
|
||||||
|
|
||||||
procedure DeleteAllTable(const ADataTable : TDADataTable);
|
procedure DeleteAllTable(const ADataTable : TDADataTable);
|
||||||
|
|
||||||
function DeltaValuesAreDifferent(const aDelta : IDADelta): boolean;
|
function DeltaValuesAreDifferent(const aDelta : IDADelta): boolean;
|
||||||
@ -48,7 +55,84 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, DB, uDAClasses, SysUtils, uDABINAdapter, uROTypes, cxControls,
|
Classes, DB, uDAClasses, SysUtils, uDABINAdapter, uROTypes, cxControls,
|
||||||
Dialogs, Variants, uDBSelectionListUtils, uROClasses;
|
Dialogs, Variants, uDBSelectionListUtils, uROClasses, uDADataStreamer, uDABin2DataStreamer;
|
||||||
|
|
||||||
|
|
||||||
|
procedure CopyDataTableDA5(ASource : TDADataTable;
|
||||||
|
ATarget: TDADataTable;
|
||||||
|
const OnlySelectedRows : Boolean);
|
||||||
|
var
|
||||||
|
AStream : Binary;
|
||||||
|
AStream2 : Binary;
|
||||||
|
AFilter : String;
|
||||||
|
AFiltered : Boolean;
|
||||||
|
AObj : ISeleccionable;
|
||||||
|
i : Integer;
|
||||||
|
begin
|
||||||
|
AFilter := '';
|
||||||
|
AFiltered := False;
|
||||||
|
|
||||||
|
if not Assigned(ASource) then
|
||||||
|
raise Exception.Create ('No se ha asignado la tabla de origen (CopyDataTable)');
|
||||||
|
|
||||||
|
if not Assigned(ATarget) then
|
||||||
|
raise Exception.Create ('No se ha asignado la tabla de destino (CopyDataTable)');
|
||||||
|
|
||||||
|
if not ATarget.Active then
|
||||||
|
ATarget.Active := True;
|
||||||
|
|
||||||
|
if OnlySelectedRows then
|
||||||
|
begin
|
||||||
|
if not Supports(ASource, ISeleccionable, aObj) then
|
||||||
|
raise Exception.Create('El origen de datos no soporta la interfaz ISeleccionable (CopyDataTable)');
|
||||||
|
|
||||||
|
if ASource.Filtered then
|
||||||
|
begin
|
||||||
|
AFiltered := True;
|
||||||
|
AFilter := ASource.Filter;
|
||||||
|
ASource.Filtered := False;
|
||||||
|
end;
|
||||||
|
|
||||||
|
ASource.Filter := '';
|
||||||
|
if ASource.Active then
|
||||||
|
ASource.Close;
|
||||||
|
|
||||||
|
for i := 0 to AObj.SelectedRecords.Count - 1 do
|
||||||
|
begin
|
||||||
|
if (i > 0) then
|
||||||
|
ASource.Filter := ASource.Filter + ' or ';
|
||||||
|
ASource.Filter := ASource.Filter + '(ID = ' + IntToStr(AObj.SelectedRecords.Items[i]) + ')';
|
||||||
|
end;
|
||||||
|
|
||||||
|
ASource.Filtered := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not ASource.Active then
|
||||||
|
ASource.Open;
|
||||||
|
|
||||||
|
AStream := Binary.Create;
|
||||||
|
DesconectarTabla(ATarget);
|
||||||
|
try
|
||||||
|
ASource.SaveToStream(AStream);
|
||||||
|
AStream2 := AStream.Clone;
|
||||||
|
|
||||||
|
// ShowMessage(AStream.ToReadableString);
|
||||||
|
ATarget.LoadFromStream(AStream2); ///->>>>>>>>>>>>>>>>>>>>>>>>>>ERRORRRR
|
||||||
|
finally
|
||||||
|
FreeAndNil(AStream);
|
||||||
|
ConectarTabla(ATarget);
|
||||||
|
// Dejar el filtro de la tabla origen como estaba
|
||||||
|
if OnlySelectedRows then
|
||||||
|
begin
|
||||||
|
ASource.Filtered := False;
|
||||||
|
ASource.Filter := AFilter;
|
||||||
|
if AFiltered then
|
||||||
|
ASource.Filtered := True;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function SetFieldNull(ATarget: TDADataTable; const FieldName: String): Boolean;
|
function SetFieldNull(ATarget: TDADataTable; const FieldName: String): Boolean;
|
||||||
begin
|
begin
|
||||||
@ -101,10 +185,11 @@ var
|
|||||||
i : integer;
|
i : integer;
|
||||||
begin
|
begin
|
||||||
bCambiado := False;
|
bCambiado := False;
|
||||||
|
|
||||||
if Assigned(ADataTable) and (ADataTable.Active) then
|
if Assigned(ADataTable) and (ADataTable.Active) then
|
||||||
begin
|
begin
|
||||||
bCambiado := (ADataTable.State = dsEdit) or
|
bCambiado :=(ADataTable.State = dsEdit) or
|
||||||
DeltaValuesAreDifferent(ADataTable.Delta);
|
(ADataTable.HasDelta and DeltaValuesAreDifferent(ADataTable.Delta));
|
||||||
|
|
||||||
if (not bCambiado) then
|
if (not bCambiado) then
|
||||||
begin
|
begin
|
||||||
@ -113,7 +198,8 @@ begin
|
|||||||
begin
|
begin
|
||||||
bCambiado := bCambiado or
|
bCambiado := bCambiado or
|
||||||
((TDADataTable(dtDetails.Items[i])).State in dsEditModes) or
|
((TDADataTable(dtDetails.Items[i])).State in dsEditModes) or
|
||||||
DeltaValuesAreDifferent((TDADataTable(dtDetails.Items[i])).Delta);
|
((TDADataTable(dtDetails.Items[i])).HasDelta and
|
||||||
|
DeltaValuesAreDifferent((TDADataTable(dtDetails.Items[i])).Delta));
|
||||||
if bCambiado then
|
if bCambiado then
|
||||||
Break;
|
Break;
|
||||||
end;
|
end;
|
||||||
@ -128,6 +214,81 @@ begin
|
|||||||
ADataTable.ClearRows;
|
ADataTable.ClearRows;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function CloneDataTable(const ASource : TDAMemDataTable;
|
||||||
|
RemoteUpdate: Boolean = True): TDAMemDataTable;
|
||||||
|
var
|
||||||
|
i : Integer;
|
||||||
|
ATarget : TDAMemDataTable;
|
||||||
|
begin
|
||||||
|
if not Assigned(ASource) then
|
||||||
|
raise Exception.Create ('No se ha asignado la tabla de origen (CloneDataTable)');
|
||||||
|
|
||||||
|
ATarget := TDAMemDataTable.Create(NIL);
|
||||||
|
with ATarget do
|
||||||
|
begin
|
||||||
|
|
||||||
|
{ ATENCIÓN !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
DA5 tiene un fallo en el cual las tablas definidas como detalle no
|
||||||
|
tienen asociados los eventos internos before... y after... por lo
|
||||||
|
que los campos AutoInc no funcionan (no pone el -1, -2...).
|
||||||
|
La forma de arreglarlo es llamar a DisableEventHandlers/EnableEventHandlers
|
||||||
|
que realiza la asociación de los eventos.
|
||||||
|
}
|
||||||
|
ATarget.DisableEventHandlers; // <--- INDISPENSABLE!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
if not Assigned(ASource.RemoteDataAdapter) then
|
||||||
|
raise Exception.Create('No está asignado RemoteDataAdapter (' + ASource.Name + ')');
|
||||||
|
|
||||||
|
LogicalName := ASource.LogicalName;
|
||||||
|
CustomAttributes.Assign(ASource.CustomAttributes);
|
||||||
|
Fields.AssignFieldCollection(ASource.Fields); // o también ATarget.LoadSchema;
|
||||||
|
Params.AssignParamCollection(ASource.Params);
|
||||||
|
|
||||||
|
RemoteDataAdapter := ASource.RemoteDataAdapter;
|
||||||
|
|
||||||
|
Randomize;
|
||||||
|
Name := ASource.Name + '_' + IntToStr(Random(MAXINT));
|
||||||
|
|
||||||
|
BusinessRulesID := ASource.BusinessRulesID;
|
||||||
|
|
||||||
|
with MasterParamsMappings do
|
||||||
|
for i := 0 to ASource.MasterParamsMappings.Count - 1 do
|
||||||
|
Add(ASource.MasterParamsMappings.Strings[i]);
|
||||||
|
|
||||||
|
with MasterRequestMappings do
|
||||||
|
for i := 0 to ASource.MasterRequestMappings.Count - 1 do
|
||||||
|
Add(ASource.MasterRequestMappings.Strings[i]);
|
||||||
|
|
||||||
|
MasterMappingMode := ASource.MasterMappingMode;
|
||||||
|
|
||||||
|
MasterFields := ASource.MasterFields;
|
||||||
|
MasterOptions := ASource.MasterOptions;
|
||||||
|
|
||||||
|
DetailFields := ASource.DetailFields;
|
||||||
|
DetailOptions := ASource.DetailOptions;
|
||||||
|
|
||||||
|
RemoteUpdatesOptions := ASource.RemoteUpdatesOptions;
|
||||||
|
StreamingOptions := ASource.StreamingOptions;
|
||||||
|
RemoteFetchEnabled := ASource.RemoteFetchEnabled;
|
||||||
|
finally
|
||||||
|
ATarget.EnableEventHandlers; // <--- INDISPENSABLE!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not RemoteUpdate then
|
||||||
|
begin
|
||||||
|
ATarget.LogChanges := False;
|
||||||
|
ATarget.RemoteFetchEnabled := False;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := ATarget;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure CloneDataTable(const ASource : TDACDSDataTable;
|
procedure CloneDataTable(const ASource : TDACDSDataTable;
|
||||||
var ATarget : TDACDSDataTable; RemoteUpdate: Boolean);
|
var ATarget : TDACDSDataTable; RemoteUpdate: Boolean);
|
||||||
var
|
var
|
||||||
@ -135,10 +296,17 @@ var
|
|||||||
begin
|
begin
|
||||||
with ATarget do
|
with ATarget do
|
||||||
begin
|
begin
|
||||||
RemoteService := ASource.GetRemoteService;
|
// ****** Inicio migración DA 5
|
||||||
Adapter := ASource.GetAdapter;
|
{RemoteService := ASource.GetRemoteService;
|
||||||
|
Adapter := ASource.GetAdapter;}
|
||||||
|
|
||||||
//BusinessRulesID := ASource.BusinessRulesID;
|
if not Assigned(ASource.RemoteDataAdapter) then
|
||||||
|
raise Exception.Create('No está asignado RemoteDataAdapter (' + ASource.Name + ')');
|
||||||
|
|
||||||
|
RemoteDataAdapter.Assign(ASource.RemoteDataAdapter);
|
||||||
|
// ****** Fin migración DA 5
|
||||||
|
|
||||||
|
BusinessRulesID := ASource.BusinessRulesID;
|
||||||
Randomize;
|
Randomize;
|
||||||
Name := ASource.Name + '_' + IntToStr(Random(MAXINT));
|
Name := ASource.Name + '_' + IntToStr(Random(MAXINT));
|
||||||
LogicalName := ASource.LogicalName;
|
LogicalName := ASource.LogicalName;
|
||||||
@ -148,6 +316,8 @@ begin
|
|||||||
if Assigned(ASource.LocalSchema) then
|
if Assigned(ASource.LocalSchema) then
|
||||||
LocalSchema := ASource.LocalSchema
|
LocalSchema := ASource.LocalSchema
|
||||||
else begin
|
else begin
|
||||||
|
// ****** Inicio migración DA 5
|
||||||
|
{
|
||||||
with SchemaCall do
|
with SchemaCall do
|
||||||
begin
|
begin
|
||||||
MethodName := ASource.SchemaCall.MethodName;
|
MethodName := ASource.SchemaCall.MethodName;
|
||||||
@ -162,9 +332,13 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
|
// ****** Fin migración DA 5
|
||||||
ATarget.Fields.AssignFieldCollection(ASource.Fields); // o también ATarget.LoadSchema;
|
ATarget.Fields.AssignFieldCollection(ASource.Fields); // o también ATarget.LoadSchema;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// ****** Inicio migración DA 5
|
||||||
|
{
|
||||||
with DataUpdateCall do
|
with DataUpdateCall do
|
||||||
begin
|
begin
|
||||||
MethodName := ASource.DataUpdateCall.MethodName;
|
MethodName := ASource.DataUpdateCall.MethodName;
|
||||||
@ -211,6 +385,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
|
// ****** Fin migración DA 5
|
||||||
|
|
||||||
with MasterParamsMappings do
|
with MasterParamsMappings do
|
||||||
for i := 0 to ASource.MasterParamsMappings.Count - 1 do
|
for i := 0 to ASource.MasterParamsMappings.Count - 1 do
|
||||||
@ -239,7 +415,6 @@ begin
|
|||||||
ATarget.RemoteFetchEnabled := False;
|
ATarget.RemoteFetchEnabled := False;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function DeltaValuesAreDifferent(const aDelta : IDADelta): boolean;
|
function DeltaValuesAreDifferent(const aDelta : IDADelta): boolean;
|
||||||
var
|
var
|
||||||
@ -251,16 +426,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
for x := 0 to (aDelta.LoggedFieldCount-1) do
|
for x := 0 to (aDelta.LoggedFieldCount-1) do
|
||||||
begin
|
begin
|
||||||
if aDelta.LoggedFieldTypes[x] <> datBlob then
|
OldNewAreDifferent := (aDelta.Changes[i].OldValues[x] <> aDelta.Changes[i].NewValues[x]);
|
||||||
begin
|
|
||||||
try
|
|
||||||
OldNewAreDifferent := (aDelta.Changes[i].OldValues[x] <> aDelta.Changes[i].NewValues[x]);
|
|
||||||
except
|
|
||||||
// Capturar cualquier tipo de excepción de conversión de tipos
|
|
||||||
on E: EVariantTypeCastError do
|
|
||||||
OldNewAreDifferent := True;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if OldNewAreDifferent then
|
if OldNewAreDifferent then
|
||||||
Break; // Abandon iteration at the first difference between old and new.
|
Break; // Abandon iteration at the first difference between old and new.
|
||||||
@ -273,7 +439,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure CopyDataTable(ASource : TDADataTable; ATarget : TDADataTable;
|
procedure CopyDataTableDA3(ASource : TDADataTable; ATarget : TDADataTable;
|
||||||
const OnlySelectedRows : Boolean = False);
|
const OnlySelectedRows : Boolean = False);
|
||||||
var
|
var
|
||||||
DABin: Binary;
|
DABin: Binary;
|
||||||
@ -314,6 +480,7 @@ begin
|
|||||||
|
|
||||||
DABin := Binary.Create;
|
DABin := Binary.Create;
|
||||||
DAAdapter := TDABINAdapter.Create(nil);
|
DAAdapter := TDABINAdapter.Create(nil);
|
||||||
|
|
||||||
try
|
try
|
||||||
ATarget.LogicalName := ASource.LogicalName; // We need to specify new dataset LogicalName
|
ATarget.LogicalName := ASource.LogicalName; // We need to specify new dataset LogicalName
|
||||||
ATarget.RemoteFetchEnabled := False; // "Desconectamos" la tabla destino del servidor
|
ATarget.RemoteFetchEnabled := False; // "Desconectamos" la tabla destino del servidor
|
||||||
@ -322,12 +489,11 @@ begin
|
|||||||
ASource.Open;
|
ASource.Open;
|
||||||
ASource.First;
|
ASource.First;
|
||||||
|
|
||||||
DAAdapter.Initialize(DABin, aiWrite);
|
|
||||||
DAAdapter.WriteDataset(DABin, ASource, [woRows]);
|
DAAdapter.WriteDataset(DABin, ASource, [woRows]);
|
||||||
DAAdapter.Initialize(DABin, aiReadFromBeginning);
|
|
||||||
DAAdapter.ReadDataset(DABin, ATarget);
|
DAAdapter.ReadDataset(DABin, ATarget);
|
||||||
DAAdapter.Finalize;
|
DAAdapter.Finalize;
|
||||||
|
|
||||||
|
|
||||||
ATarget.RemoteFetchEnabled := True; // "Conectamos" la tabla del servidor otra vez
|
ATarget.RemoteFetchEnabled := True; // "Conectamos" la tabla del servidor otra vez
|
||||||
|
|
||||||
// Dejar el filtro de la tabla origen como estaba
|
// Dejar el filtro de la tabla origen como estaba
|
||||||
@ -461,14 +627,14 @@ begin
|
|||||||
if Assigned(ADetail) then
|
if Assigned(ADetail) then
|
||||||
begin
|
begin
|
||||||
// ¡¡¡¡¡ MUY IMPORTANTE !!!!!!!!!!!!!!!!!!
|
// ¡¡¡¡¡ MUY IMPORTANTE !!!!!!!!!!!!!!!!!!
|
||||||
ADetail.DataTable.DisableEventHandlers;
|
//ADetail.DataTable.DisableEventHandlers;
|
||||||
try
|
try
|
||||||
ADetail.DataTable.MasterSource := AMasterDataSource;
|
ADetail.DataTable.MasterSource := AMasterDataSource;
|
||||||
finally
|
finally
|
||||||
{ Hay que activar los eventos porque dejan de funcionar
|
{ Hay que activar los eventos porque dejan de funcionar
|
||||||
las reglas de negocio al establecer la relación
|
las reglas de negocio al establecer la relación
|
||||||
maestro-detalle. (Fallo de Data Abstract 3) }
|
maestro-detalle. (Fallo de Data Abstract 3) }
|
||||||
ADetail.DataTable.EnableEventHandlers;
|
//ADetail.DataTable.EnableEventHandlers;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -501,5 +667,4 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
Reference in New Issue
Block a user