From e6e810c371cee6867a68b48f15deae5e990dca11 Mon Sep 17 00:00:00 2001 From: roberto Date: Wed, 12 Dec 2007 20:09:20 +0000 Subject: [PATCH] =?UTF-8?q?Arreglado=20un=20error=20que=20se=20produc?= =?UTF-8?q?=C3=ADa=20al=20comprobar=20si=20un=20DataTable=20sin=20deltas?= =?UTF-8?q?=20preparados=20ha=20sido=20modificado.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: https://192.168.0.254/svn/Proyectos.LuisLeon_FactuGES/trunk@199 c93665c3-c93d-084d-9b98-7d5f4a9c3376 --- Source/Base/Utiles/uDataTableUtils.pas | 223 +++++++++++++++++++++---- 1 file changed, 194 insertions(+), 29 deletions(-) diff --git a/Source/Base/Utiles/uDataTableUtils.pas b/Source/Base/Utiles/uDataTableUtils.pas index 21b2c0e4..76e67f34 100644 --- a/Source/Base/Utiles/uDataTableUtils.pas +++ b/Source/Base/Utiles/uDataTableUtils.pas @@ -3,7 +3,7 @@ unit uDataTableUtils; interface uses - uDACDSDataTable, uDADataTable, uDAInterfaces; + uDACDSDataTable, uDADataTable, uDAInterfaces, uDADelta, uDAMemDataTable; const ID_NULO = -9000; @@ -19,9 +19,19 @@ function SetFieldNull(ATarget: TDADataTable; const FieldName: String): Boolean; procedure ConectarTabla (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; 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; Const WithKey: Boolean = False); @@ -29,9 +39,6 @@ procedure DuplicarRegistros(ASource : TDADataTable; ATarget : TDADataTable; AModo : TModoDuplicarRegistros; APermitirRepetidos: Boolean = True; Const WithDeltas: Boolean = True; Const WithKey: Boolean = False); -procedure CopyDataTable(ASource : TDADataTable; ATarget : TDADataTable; - const OnlySelectedRows : Boolean = False); - procedure DeleteAllTable(const ADataTable : TDADataTable); function DeltaValuesAreDifferent(const aDelta : IDADelta): boolean; @@ -48,7 +55,84 @@ implementation uses 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; begin @@ -101,10 +185,11 @@ var i : integer; begin bCambiado := False; + if Assigned(ADataTable) and (ADataTable.Active) then begin - bCambiado := (ADataTable.State = dsEdit) or - DeltaValuesAreDifferent(ADataTable.Delta); + bCambiado :=(ADataTable.State = dsEdit) or + (ADataTable.HasDelta and DeltaValuesAreDifferent(ADataTable.Delta)); if (not bCambiado) then begin @@ -113,7 +198,8 @@ begin begin bCambiado := bCambiado 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 Break; end; @@ -128,6 +214,81 @@ begin ADataTable.ClearRows; 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; var ATarget : TDACDSDataTable; RemoteUpdate: Boolean); var @@ -135,10 +296,17 @@ var begin with ATarget do begin - RemoteService := ASource.GetRemoteService; - Adapter := ASource.GetAdapter; + // ****** Inicio migración DA 5 + {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; Name := ASource.Name + '_' + IntToStr(Random(MAXINT)); LogicalName := ASource.LogicalName; @@ -148,6 +316,8 @@ begin if Assigned(ASource.LocalSchema) then LocalSchema := ASource.LocalSchema else begin + // ****** Inicio migración DA 5 + { with SchemaCall do begin MethodName := ASource.SchemaCall.MethodName; @@ -162,9 +332,13 @@ begin end; end; end; + } + // ****** Fin migración DA 5 ATarget.Fields.AssignFieldCollection(ASource.Fields); // o también ATarget.LoadSchema; end; + // ****** Inicio migración DA 5 + { with DataUpdateCall do begin MethodName := ASource.DataUpdateCall.MethodName; @@ -211,6 +385,8 @@ begin end; end; end; + } + // ****** Fin migración DA 5 with MasterParamsMappings do for i := 0 to ASource.MasterParamsMappings.Count - 1 do @@ -239,7 +415,6 @@ begin ATarget.RemoteFetchEnabled := False; end; end; - function DeltaValuesAreDifferent(const aDelta : IDADelta): boolean; var @@ -251,16 +426,7 @@ begin begin for x := 0 to (aDelta.LoggedFieldCount-1) do begin - if aDelta.LoggedFieldTypes[x] <> datBlob then - 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; + OldNewAreDifferent := (aDelta.Changes[i].OldValues[x] <> aDelta.Changes[i].NewValues[x]); if OldNewAreDifferent then Break; // Abandon iteration at the first difference between old and new. @@ -273,7 +439,7 @@ begin end; -procedure CopyDataTable(ASource : TDADataTable; ATarget : TDADataTable; +procedure CopyDataTableDA3(ASource : TDADataTable; ATarget : TDADataTable; const OnlySelectedRows : Boolean = False); var DABin: Binary; @@ -314,6 +480,7 @@ begin DABin := Binary.Create; DAAdapter := TDABINAdapter.Create(nil); + try ATarget.LogicalName := ASource.LogicalName; // We need to specify new dataset LogicalName ATarget.RemoteFetchEnabled := False; // "Desconectamos" la tabla destino del servidor @@ -322,12 +489,11 @@ begin ASource.Open; ASource.First; - DAAdapter.Initialize(DABin, aiWrite); DAAdapter.WriteDataset(DABin, ASource, [woRows]); - DAAdapter.Initialize(DABin, aiReadFromBeginning); DAAdapter.ReadDataset(DABin, ATarget); DAAdapter.Finalize; + ATarget.RemoteFetchEnabled := True; // "Conectamos" la tabla del servidor otra vez // Dejar el filtro de la tabla origen como estaba @@ -461,14 +627,14 @@ begin if Assigned(ADetail) then begin // ¡¡¡¡¡ MUY IMPORTANTE !!!!!!!!!!!!!!!!!! - ADetail.DataTable.DisableEventHandlers; + //ADetail.DataTable.DisableEventHandlers; try ADetail.DataTable.MasterSource := AMasterDataSource; finally { Hay que activar los eventos porque dejan de funcionar las reglas de negocio al establecer la relación maestro-detalle. (Fallo de Data Abstract 3) } - ADetail.DataTable.EnableEventHandlers; + //ADetail.DataTable.EnableEventHandlers; end; end; end; @@ -501,5 +667,4 @@ begin end; end; - end.