Rafael, tengo problemas con el refresh, Error: The refresh key defined for 
table is not found.

El codigo es:

procedure CACompras
lparameters cAlia, cName
        * cInsCmd, cUpdCmd, cDelCmd pueden ser vacios
                
        oCA = createobject("CABase")
        oCA.Alias = cAlia
        oCA.CursorSchema = "PROVEEDOR C(30),FECHA D, IDPROV I, IDCOM I"
        oCA.InsertCmdRefreshFieldList = "IDCOM"
        oCA.name = cName
        oCA.SelectCmd = "select  PROVEEDOR, FECHA, IDPROV, IDCOM from 
compras c inner join proveedores p on c.idprov=p.idpro"
        oCA.Tables = "Compras"
        oCA.UpdatableFieldList = "FECHA, IDPROV"
        oCA.UpdateCmdRefreshFieldList = "FECHA, IDPROV"
        oCA.UpdateCmdRefreshKeyFieldList = "IDCOM"
        oCA.UpdateNameList = "FECHA Compras.FECHA IDPROV Compras.IDPROV"
        oCA.KeyFieldList = "IDCOM"
        oCA.CursorFill()
        return oCA
endproc 


define class CABase as CursorAdapter 

        procedure init
                
                local loConnDataSource, oRS
                loConnDataSource = createobject('ADODB.Connection')
                loConnDataSource.ConnectionString = 
[Provider=SQLNCLI10.1;Integrated Security=SSPI;Persist Security 
Info=False;] + ;
                [User ID="";Initial Catalog=Insumos;Data 
Source=PPC\SQLE;Initial File ] + ;
                [Name="";Server SPN="";]
        
                
                loConnDataSource.Open()
                
                oRS = createobject('ADODB.RecordSet')
                oRS.CursorLocation   = 3  && adUseClient
                oRS.LockType         = 3  && adLockOptimistic
                oRS.ActiveConnection = loConnDataSource
                
                this.DataSource = oRS
                this.DataSourceType = "ADO"
                this.AllowSimultaneousFetch = .t.
                this.BreakOnError = .t.
                this.BufferModeOverride = 3 && Optimistic row buffering
                this.conflictCheckType  = 3 && Check for both modified 
record and key uniqueness
                this.FetchMemo = .f.
                this.FetchSize = -1
                this.MapBinary = .t.
                this.MapVarchar = .t.
                this.SendUpdates = .t.
                this.UseCursorSchema = .t.
                *oCA.UseDeDataSource = .t.
        endproc 
enddefine




-----Original Message-----
From: Rafael Copquin <[email protected]>
To: "GUFA List Member"  <[email protected]>
Date: Thu, 26 Jul 2012 10:08:00 -0300
Subject: [GUFA] CursorAdapter

> Hola, te respondo las preguntas:
> 
> 1) los links estaban en español originalmente y fueron luego
> traducidos 
> al inglés y al portugués. Pero desde hace varios años, el dueño de
> la 
> revista solamente dejó disponibles las versiones en inglés
> 
> 2) podés hacer cursor adapters de varias tablas en la sentencia select
> sql. Pero lo mejor es actualizar una sola tabla, aunque la consulta sea
> de varias tablas. Los campos de la tabla que vas a actualizar los 
> definís en las propiedades updatefieldlist, updatenamelist y 
> keyfieldlist (en todas ellas tenés que incluir la clave primaria de la
> tabla, porque si no, no te va a funcionar) También tenés que poner la
> propiedad sendupdates en true.
> 
> 3) En cuanto a TierAdapter, preguntales a los autores Rubén Rovira y 
> Martín Salías
> 
> Saludos
> 
> Rafael Copquin
> 
> 
> 
> El 25/07/2012 07:50 p.m., pablo.oviedo escribió:
> > Gracias, empece con cursoradapter y me trabe. Se pueden usar un
> > cursoadapter que incluya columnas de distintas tablas? me tira error
> > cuando quiero refrescar algunos campos del cursor luego de una
> inserción.
> >
> > También estoy viendo TierAdapter. Los link que me pasaron, es
> posible que
> > esta información este en español?
> >
> > Existe alguna documentación sobre TierAdapter que describa todas las
> > clases, metodos y propiedades del frameworks a parte del diagrama de
> UML
> > que esta en el sitio de Martin?
> >
> > saludos
> >
> >
> > -----Original Message-----
> > From: Rafael Copquin <[email protected]>
> > To: "GUFA List Member"  <[email protected]>
> > Date: Tue, 24 Jul 2012 16:32:07 -0300
> > Subject: [GUFA] CursorAdapter
> >
> >> Te paso un ejemplo bien completo de cómo lo hago yo:
> >>
> >> ** creacion de las tablas en sqlserver
> >> ** en la vida real tienen más campos, pero estos son los mínimos
> que
> >> deberían tener
> >>
> >> CREATE TABLE [dbo].[DETALLE](
> >>       [FECHA] [date] NOT NULL,
> >>       [TIPODOC] [char](3) NOT NULL,
> >>       [DOCNUM] [char](8) NOT NULL,
> >>       [CODIGO] [char](30) NOT NULL,
> >>       [CANTIDAD] [int] NOT NULL,
> >>       [PRECIO] [numeric](10, 4) NOT NULL,
> >>       [DT] [datetime] NOT NULL,
> >>       [IDETALLE] [int] IDENTITY(1,1) NOT NULL,
> >>       [IDCABECERA] [int] NOT NULL,
> >>    CONSTRAINT [PK_DETALLE] PRIMARY KEY CLUSTERED
> >> (
> >>       [IDDETALLE] ASC
> >> )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF,
> IGNORE_DUP_KEY
> >> =
> >> OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
> >>    CONSTRAINT [CN_IDDETALLE] UNIQUE NONCLUSTERED
> >> (
> >>       [IDDETALLE] ASC
> >> )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF,
> IGNORE_DUP_KEY
> >> =
> >> OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
> >> ) ON [PRIMARY]
> >>
> >> CREATE TABLE [dbo].[CABECERA](
> >>       [FECHA] [date] NOT NULL,
> >>       [CUENTA] [char](4) NOT NULL,
> >>       [TIPODOC] [char](3) NOT NULL,
> >>       [DOCNUM] [char](8) NOT NULL,
> >>       [IVA] [numeric](10, 2) NOT NULL,
> >>       [TOTAL] [numeric](10, 2) NOT NULL,
> >>       [IDCABECERA] [int] IDENTITY(1,1) NOT NULL,
> >>       [DT] [datetime] NOT NULL,
> >>    CONSTRAINT [PK_IDCABECERA] PRIMARY KEY CLUSTERED
> >> (
> >>       [IDCABECERA] ASC
> >> )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF,
> IGNORE_DUP_KEY
> >> =
> >> OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
> >> ) ON [PRIMARY]
> >>
> >>
> >> ** lo siguiente se hace en Visual FoxPro
> >>
> >> ** generación de un cursor adapter para la tabla CABECERA
> >>
> >> Local cCmd,cSch,cUFL,cUNL,lOK
> >>
> >> Text to cCmd noshow pretext 15
> >> SELECT
> >>       FECHA ,
> >>       CUENTA ,
> >>       TIPODOC ,
> >>       DOCNUM ,
> >>       IVA ,
> >>       TOTAL ,
> >>       IDCABECERA ,
> >>       DT
> >>    FROM CABECERA WHERE 1=0
> >> EndText
> >>
> >> Text to cSch noshow pretext 15
> >>       FECHA D,
> >>       CUENTA C(4),
> >>       TIPODOC C(3),
> >>       DOCNUM C(8),
> >>       IVA N(10,2),
> >>       TOTAL N(10,2),
> >>       IDCABECERA I,
> >>       DT T
> >> EndText
> >>
> >>
> >> Text to cUFL noshow pretext 15
> >>       FECHA ,
> >>       CUENTA ,
> >>       TIPODOC ,
> >>       DOCNUM ,
> >>       IVA ,
> >>       TOTAL ,
> >>       IDCABECERA ,
> >>       DT
> >> EndText
> >>
> >> Text to cUNL noshow pretext 15
> >>       FECHA        CABECERA.FECHA,
> >>       CUENTA       CABECERA.CUENTA,
> >>       TIPODOC      CABECERA.TIPODOC,
> >>       DOCNUM       CABECERA.DOCNUM,
> >>       IVA          CABECERA.IVA,
> >>       TOTAL        CABECERA.TOTAL,
> >>       IDCABECERA   CABECERA.IDCABECERA,
> >>       DT           CABECERA.DT
> >> EndText
> >>
> >> cUFL        = Chrtran( cUFL, Chr(13) + Chr(10), " " )
> >> cUNL       = Chrtran( cUNL, Chr(13) + Chr(10), " " )
> >> cSch        = Chrtran( cSch, Chr(13) + Chr(10), " " )
> >> cCmd      = Chrtran( cCmd, Chr(13) + Chr(10), " " )
> >>
> >> Use in Select("")
> >>
> >> lOK = .t.
> >>
> >> If !PemStatus(thisform,'oCA',5)
> >>      thisform.AddProperty('oCA')
> >> EndIf
> >>
> >> Try
> >>
> >>       Thisform.oCA = Createobject("CursorAdapter")
> >>
> >>       lOK = .t.
> >>
> >> Catch to oErrores
> >>
> >>       MessageBox("No se pudo generar el objeto CursorAdapter"+;
> >>       Chr(13)+oErrores.message,16,"Atención",2000)
> >>
> >>       lOK = .f.
> >>
> >> Finally
> >> EndTry
> >>
> >>
> >> If lOK = .t.
> >>      try
> >>          With thisform.oCA
> >>               .DataSourceType     = "ODBC"
> >>               .DataSource         = thisform.nHandle
> >>               .alias                 = "curCabecera"
> >>               .tables             = "cabecera"
> >>               .BufferModeOverride = 5
> >>               .keyfieldlist        = "idcabecera"
> >>               .sendupdates         = .T.
> >>               .usetransactions    = .f.   && si están en falso, no
> usa
> >> transacciones y funciona entonces ponerlas en manual en SQL Server
> >>               .selectcmd             = cCmd
> >>               .updatablefieldlist = cUFL
> >>               .updatenamelist     = cUNL
> >>               .cursorschema       = cSch
> >>               .cursorfill()
> >>          EndWith
> >>
> >>          Select curCabecera
> >>
> >>      Catch to oErrores
> >>
> >>           MessageBox("No se pudo generar el Cursor
> >> "+Chr(13)+oErrores.message;
> >>           ,16,"Atención",2000)
> >>
> >>           lOK = .f.
> >>
> >>      endtry
> >> endif
> >>
> >> Return lOK
> >>
> >> **(hacer otro cursor adapter para la tabla DETALLE y obtener el
> cursor
> >> curDetalle)
> >>
> >> ** la sentencia where 1=0 genera un cursor vacío. Esto es para que
> >> llenes el cursor adapter con los datos necesarios antes de
> >> ** grabar. Estos datos salen de textboxes, grillas, cálculos, etc.
> >>
> >> ** rutina de grabación
> >>
> >> Local lOK,nPK,cCmd,nResults,lBatchMode
> >>
> >> SQLExec(thisform.nHandle,'BEGIN TRANSACTION')
> >> SQLSetProp(thisform.nHandle, "TRANSACTIONS", 2 )   && pone las
> >> transacciones en manuales
> >>
> >> Select curCabecera
> >> Scatter name oCab blank fields except idcabecera
> >> With oCab
> >>       .fecha    = Date()
> >>       .cuenta   = '1234'
> >>       .tipodoc  = 'FRA'
> >>       .docnum   = '12345678'
> >>       .iva      = 210.00
> >>       .total    = 1210.00
> >>       .dt       = Datetime()
> >> EndWith
> >>
> >> ** grabación de la cabecera y obtención de la clave primaria
> generada
> >> ** el campo idcabecera es autoincremental
> >>
> >> Insert into curCabecera from name oCab
> >>
> >> lOK = TableUpdate(.t.,.t.,'curCabecera')
> >>
> >> If lOK = .t.
> >>
> >>       nPK      = 0
> >>       nResults = 0
> >>       cCmd     = [select @@IDENTITY as pk ]
> >>
> >>       lBatchMode = SQLGetProp(thisform.nHandle,"BatchMode" )
> >>
> >>       SQLSetProp(thisform.nHandle,"BatchMode" ,.f.)
> >>
> >>       SQLExec(thisform.nHandle,cCmd,'curPK')
> >>
> >>       Do while nResults <> 2
> >>          nResults = SQLMoreResults(thisform.nHandle)
> >>       enddo
> >>
> >>       SQLSetProp(thisform.nHandle,"BatchMode" ,lBatchMode)
> >>
> >>       nPK = curPK.pk
> >>       Use in Select('curPK')
> >>
> >>       Select curFactura      && cursor auxiliar usado en el form
> para
> >> insertar las lineas de detalle de la factura
> >>                                           && tiene la misma
> estructura
> >> que la tabla detalle del sql server
> >>
> >>       Scan all
> >>            Scatter name oDet fields except iddetalle
> >>            With oDet
> >>                 .fecha      = Date()
> >>                 .tipodoc    = 'FRA'
> >>                 .docnum     = '12345678'
> >>                 .idcabecera = nPK       && aqui pasa a ser la clave
> >> foránea
> >>                 .dt         = Datetime()
> >>            *** los campos codigo, cantidad y precio ya están en el
> >> objeto, obtenidos con SCATTER NAME
> >>            endwith
> >>            Insert into curDetalle from name oDet
> >>       EndScan
> >>       lOK = TableUpdate(.t.,.t.,'curDetalle')
> >>
> >> endif
> >>
> >> If lOK = .t.
> >>
> >>      SQLCommit(thisform.nHandle)
> >>
> >> Else
> >>
> >>      SQLRollback(thisform.nHandle)
> >>
> >> endif
> >>
> >> SQLSetProp(thisform.nHandle,'Transactions',1 )     && transacciones
> >> automáticas
> >>
> >> A los cursor adapters les ponés la propiedad usetransactions en
> falso,
> >> para que no maneje las transacciones directamente. Acordate que en
> SQL
> >> Server, las transacciones son automáticas a menos que las pongas en
> >> manual. Esto hace que cada vez que insertás,borrás o modificás un
> >> registro, se abra y cierre una transacción automáticamente. No te
> >> sirve
> >> para el caso de una factura, porque si te da error alguna de las
> >> tablas,
> >> no podés cancelar una transacción completa. En cambio, si las
> >> transacciones las ponés en manual, solamente se completa la
> >> transacción
> >> cuando le mandás un SQLCommit (o SQLRollback si falla)
> >> Tenés que poner las transacciones del SQLServer en manual antes de
> >> comenzar a grabar y luego de cerrar la transacción las ponés
> >> nuevamente
> >> en automáticas,para que el SQL Server siga funcionando normalmente
> >>
> >> Fijate en estos artículos
> >>
> >> http://www.universalthread.com/ViewPageArticle.aspx?ID=667
> >>
> >> http://www.universalthread.com/ViewPageArticle.aspx?ID=817
> >>
> >> Rafael Copquin
> >>
> >
> 


Responder a