2012-04-19 17 views
12

Tengo un TDatasetProvider personalizado que permite crear nuevos campos para cualquier dato que proporciona.Forma más rápida de mover datos de una estructura de conjunto de datos a otra (en TDatasetProvider)

Por lo tanto, digamos que tienes los campos folowing en el conjunto de datos original:

  • CustomerId
  • Nombre
  • Edad

y hay que seleccionarlo en DBGrid utilizando mostrando una Mapa de bits Bueno, puede hacerlo ya que mi DSP puede agregar un campo booleano llamado Selected a los datos del conjunto de datos.

La forma en que hago que ahora:

  1. crear 2 objetos TClientDataSet (origen y destino)
  2. En Origen, me carga los datos conseguidos de los parámetros del método InternalGetRecords (Me hizo caso omiso de ella)
  3. en Target, creo FieldDefs los definidos a partir del conjunto de datos de origen y añadir los FieldDefs creados en tiempo de diseño por el desarrollador
  4. ejecutar una CreateDataSet en el blanco
  5. y, fila por fila (una d campo por campo), copio los datos de la base de datos de Origin en el conjunto de datos de destino
  6. Al final, devuelva la variante de Datos como un valor de retorno de InternalGetRecords.

Realmente no sé si hay una forma más elegante (y más rápida) de hacerlo. ¿Hay otra forma (más rápida y/o elegante) de obtener ese resultado?

+0

¿no puede simplemente crear el campo booleano decalcal interno en el conjunto de datos original sin todo ese lío? – vavan

+0

Después de hacer este componente, la vida se hizo más fácil ya que puedo crear campos de datos que el CDS reconoce como campos de datos ... –

+0

pero está haciendo mucho trabajo innecesario. y ¿cuál es el sentido de crear esos campos de datos? – vavan

Respuesta

12

Parece que después de cargar los datos del conjunto de datos de origen, puede llamar IDSBase.AddField añadir más campos:

uses 
    DB, DBCommon, DBClient, DSIntf; 

type 
    THackClientDataSet = class(TClientDataSet); 

procedure EncodeFieldDesc(var FieldDesc: DSFLDDesc; 
    const Name: string; DataType: TFieldType; Size, Precision: Integer; 
    Calculated: Boolean; Attributes: TFieldAttributes); 
begin 
    // ... copied from TClientDataSet.EncodeFieldDesc 
end; 

//... 
var 
    FldDesc: DSFLDDesc; 
begin 
    FillChar(FldDesc, SizeOf(FldDesc), 0); 
    EncodeFieldDesc(FldDesc, 'SELECTED', ftBoolean, 0, 0, False, []); 
    with THackClientDataSet(DataSet) do 
    Check(DSBase.AddField(@FldDesc)); 
    // now you can create a second client dataset and assign it DataSet.Data directly: 
    // DataSet2.Data := DataSet.Data; 
    // DataSet2 now contains the new field (with empty values in all existing records) 
end; 

No he probado a fondo, pero el El ejemplo simple anterior funcionaba como se esperaba, pude navegar el segundo conjunto de datos del cliente y editar los valores de todos los campos como de costumbre.

+0

OMG ... ¡Esto es realmente interesante! Lo intentaré lo antes posible! –

+0

No funcionó para nada ... Lo intentaré de nuevo el lunes ... –

+0

Parece que fue un problema entre la silla y el teclado. Solución brillante. Aceptado y +1. –

-1

Puede usar la propiedad Datos de TClientDataset para copiar todo el conjunto de datos, metadatos y datos. Se supone que esta es la forma más rápida de copiar un TClientDataset a otro.

Ver http://docwiki.embarcadero.com/RADStudio/en/Assigning_Data_Directly

+0

-1 Parece que no leyó la pregunta ... Los CDS de Target tienen metadatos diferentes (con campos adicionales). Entonces, si realmente solo copio la variante de Data de Origin a Target, solo tendré eso: una copia de Origin sin los campos adicionales deseados. –

+0

Al leer su pregunta, su conjunto de datos de origen contiene los campos "nuevos" que creó a través de su TDatasetProvider personalizado y los datos de campo provienen de sus InternalGetRecords reemplazados. Esa es la base de mi respuesta. De lo contrario, ¿por qué necesita un TDatasetProvider personalizado? Puede crear los nuevos campos en Destino mientras copia la información de campo de Origin. – crefird

+0

Has leído mal. Target tiene los nuevos campos. Origin obtiene los datos obtenidos de los parámetros del proveedor del conjunto de datos (los datos "puros" tienen componentes de acceso a datos). –

1

La forma más rápida sería utilizar CloneCursor. Algo como esto:

  1. Crear 2 objetos TClientDataSet (origen y destino)
  2. En Origen, cargar los datos obtuvo de los parámetros del método InternalGetRecords
  3. En destino, cree las FieldDefs definida a partir del conjunto de datos de origen y añadir los FieldDefs creados en tiempo de diseño por el desarrollador
  4. Target.CloneCursor(Origin); //there are more params than this, but this is the basic idea
  5. de destino contendrá ahora una nueva visión de los mismos datos como el origen, pero limitado por cualquier campos, filtros, etc. existir en Target. (Si no ha definido ningún campo, copiará los campos de Origin. Si define campos, entonces se quedará con lo que le dio.)
  6. Copie los datos del destino, y eso debería ser exactamente lo que está buscando para.
+0

que no funcionará si OP realmente quiere tener campos fkData adicionales. si todo lo que necesita son algunos campos de búsqueda, calculados, internalcalc o agregados, no hay necesidad de meterse con toda esa copia/clonación y se puede lograr usando cds únicos (originales) – vavan

+0

Intenté la idea, pero no funcionó, todo lo que obtengo es la matriz de datos de origen. Tal vez malentendí algo ... –

0

Tengo un ejemplo que agrega campos a un CDS dinámicamente, utilizando métodos anónimos para los cálculos de campos individuales, para lograr más flexibilidad.Antes de abrir el CDS, agregue los campos calculados, luego ábralo ...

¿Esto es lo que está buscando? La pregunta no es muy clara ...

+2

Esto debería ser un comentario, no una respuesta. – kobik

+0

El legendario Marco Cantù en mi humilde pregunta? *** Genial. *** De vuelta al trabajo: Estoy creando campos de datos DESPUÉS de cds.open (en InternalGetRecords of TDataSetProvider) –

Cuestiones relacionadas