Dbusearea( lNew ,cRDD , cFileName, cAlias , lShared , lReadonly )
lucasdebeltran wrote:Hola,
Cuando usas adsconnect60 no puedes usar tablas libres.
reinaldocrespo wrote:Yessica;
Hola. Hace mucho tiempo no uso tablas libres (free tables), no obstante, entiendo que no existe ninguna ciencia oculta para hacerlo. Es decir, tablas libres es la forma tradicional de usar dbfs. No estoy seguro si lo que Lucas dice es siempre cierto. Yo recuerdo cuando comencé a usar el dd que también usaba tablas libres a la vez. Especialmente para tablas dbfs temporeras.
¿Usas el "remote" server o el "local server"? ¿Tienes el directorio donde residen las tablas libres compartido y existe ruta desde la estación de trabajo a dicho directorio? Te recuerdo que a menos que las tablas residan localmente en el disco c:, para usar tablas libres necesitas un "share"- es decir, compartir el directorio donde residen las tablas libres y desde código necesitas proveer la ruta a la tabla además del nombre de la tabla.
- Code: Select all Expand view
Dbusearea( lNew ,cRDD , cFileName, cAlias , lShared , lReadonly )
donde cFileName incluye la ruta (c:\PathToData\customers.dbf). Por favor déjame conocer que tal te funciona .
Reinaldo.
reinaldocrespo wrote:¿Puedes citar el error? Tal vez tienes el RDD por default set a ADSADT o algún otro tipo de RDD no compatible con la tabla libre. Te recuerdo que siempre puedes añadir el RDD que se debe usar con la cláusula VIA. Por ejemplo VIA "DBFCDX" ¿Será ese el problema?
reinaldocrespo wrote:Yessica;
Cuando te conectas a un DD, el DD contiene metadata que describe las tablas. Entre otras cosas describe que indices tiene asociados, triggers, que tipo de tabla es, como por ejemplo; si la tabla es dbfcdx, dbfntx, adsadt, etc... Yo pienso que es posible que el problema que confrontas sea que la tabla es dbfcdx y la intentas abrir con adsadt. Intenta usar la cláusula VIA como parte del USE ... ¿Es la tabla DBFNTX, DBFCDX? Usa el RDD correspondiente en tu USE command. ¿Te funciona? Una última cosa, la tabla que llamas "free" es también parte de un DD, entonces esa tabla NO es "free".
Yo uso xHarbour con FW 12_10 y no puedo reproducir el problema. A ver si te puedo crear un -self-contained-reduced sample que puedas probar allá con tu harbour y fw.
Reinaldo.
//This console mode app shows how to create a few tables of different types.
//How to create an Advantage Data Dictionary and add the newly created
//tables the data dictionary file.
//I'm using various table types using ADS RDDs for DBF/NTX, DBF/VFP, ADT/ADI
//
//After that it atttempts to connect to the dd, create a new table and then
//open the new table as a free table.
//In short- it creates tables and dd, opens dd bound tables and free tables
//at the same time.
//
//The sample code uses pure rdds + some ACE calls.
//No GUI dependency as only a console mode app is being built, which should
//build just the same under Windows as well as under Linux.
//
#include "ads.ch"
#xcommand DEFAULT <uVar1> := <uVal1> ;
[, <uVarN> := <uValN> ] => ;
<uVar1> := iif( <uVar1> == nil, <uVal1>, <uVar1> ) ;;
[ <uVarN> := iif( <uVarN> == nil, <uValN>, <uVarN> ); ]
REQUEST DBFCDX
REQUEST ADS //Make sure rddads gets linked to our app.
REQUEST hb_gt_win //needed for console mode app.
//Static variable cPath will contain the path where tables and DD will be created.
//After connecting to an existing DD, there is no need to use the file path as the
//DD saves the relative path of each table as part of its metadata.
STATIC cPath
*-----------------------------------------------------------------------------------------------------
FUNCTION Main()
LOCAL afiles
SetMode(25,80) //25 lines by 80 columns console
rddRegister( "ADS", 1 )
rddSetDefault( "ADS" )
adsSetServerType( ADS_LOCAL_SERVER )
//NON-compatible locking mode. If other NON-ADS clients are going to
//to work on the same tables, then make sure to use compatible locking mode.
AdsLocking( .t. )
AdsRightsCheck( 0 )
//Path for existing .dbf tables maybe sent as a parameter
//on the command line. This is just one idea. It could be saved
//on a .ini file or hardcoded.
cPath := hb_ArgV( 1 )
//in case no path was sent on command line, assume current path.
DEFAULT cpath := ""
//sanitize cPath contents.
//IF !EMPTY( cPath ) .and. RIGHT( cPath, 1 ) != '' ;cPath += '' ;ENDIF
//if you need to create some new tables other than existing tables look
//at function CreateTables(). CreateTables shows how to create
//adt tables, vfp tables, and dbf-ntx tables.
//
//CreateTables() creates an array with table names and structure for each.
//It then creates the tables. After being created they will be added to a newly
//created data dictionary using function CreateDictionary().
//If your .dbf tables are alreay present, then you won't need to execute
//CreateTables, instead you could simply execute a Directory() harbour
//function to retreive existing table names. By storing the names of these tables
//into afiles variable, you can then execute CreateDictionary() in exactly the same
//manner.
afiles := CreateTables()
IF !EMPTY( afiles ) ;CreateDictionary( afiles ) ;ENDIF
//now that we have a dd created, we will attempt to connect to it and
//use the tables as dd bound tables.
IF !AdsConnect60( cPath + "test_dd.add", ADS_LOCAL_SERVER, "user1", "password1" )
Alert( "Cannot connect to test_dd" + Str( AdsGetLastError() ) )
QUIT
ENDIF
//Now we create a dbfcdx table to be used as a free table.
CreateAndUseFreeTable()
RETURN NIL
//--------------------------------------------------------------------------------------
//function CreateTables() will create three tables using stnd harbour func dbCreate
//Each table structure is saved on an array following the std returned by dbStruct()
//Each element on the array is an array describing the field. Thus, the array
//for a table with 3 fields would look like this:
//aStructure := { { cFieldName1, cFieldType1, nFldWidth, nDecimals },;
// { cFieldName2, cFieldType2, nFldWidth, nDecimals },;
// { cFieldName3, cFieldType3, nFldWidth, nDecimals } }
//
STATIC FUNCTION CreateTables()
LOCAL cAlias := "MyAlias"
LOCAL afiles := {}
LOCAL cFileName, e
//---------------------- customers.adt --------------------------------------------
LOCAL aStruc := { { "cust_id" , "C", 10, 0 },;
{ "Sequence" , "AutoInc", 07, 0 },; //ADT extended field type autoincrement
{ "customer_name" , "C", 25, 0 },;
{ "Start_date" , "TimeStamp", 01, 0 },; //ADT extended field type
{ "Notes" , "M", 10, 0 } }
AdsSetFileType( ADS_ADT )
TRY
dbCreate( ( cFileName := cPath + "customers.adt" ), aStruc,, .t., cAlias )
( cAlias )->( OrdCreate( cPath + "customers", "cust_id", "cust_id" ) )
( cAlias )->( OrdCreate( cPath + "customers", "Start_date", "Start_date" ) )
( cAlias )->( dbclosearea() )
AADD( afiles, { cFileName, "customers.adi" } )
//------------------------ sales.dbf -------------------------------------------------
aStruc := { { "cust_id" , "C", 10, 0 },;
{ "invoice" , "C", 15, 0 },;
{ "s_date" , "TimeStamp", 01, 0 },; //VFP extended field type
{ "item_id" , "C", 15, 0 },;
{ "Units" , "N", 03, 0 },;
{ "Price" , "Money", 09, 2 },; //VFP extended field type
{ "Notes" , "M", 10, 0 } }
AdsSetFileType( ADS_VFP )
dbCreate( ( cFileName := cPath + "sales.dbf" ), aStruc,, .t., cAlias )
( cAlias )->( OrdCreate( cPath + "sales", "invoice", "invoice" ) )
( cAlias )->( OrdCreate( cPath + "sales", "cust_id", "cust_id" ) )
( cAlias )->( dbclosearea() )
aadd( afiles, { cFileName, "sales.cdx" } )
//------------------------ items.dbf -------------------------------------------------
aStruc := { { "item_id" , "C", 15, 0 },;
{ "Desc" , "C", 25, 0 },;
{ "Price" , "N", 07, 2 } }
AdsSetFileType( ADS_NTX )
dbCreate( ( cFileName := cPath + "items.dbf" ), aStruc,, .t., cAlias )
( cAlias )->( OrdCreate( cPath + "itm_id",, "item_id" ) )
( cAlias )->( OrdCreate( cPath + "itm_desc",, "Desc" ) )
( cAlias )->( dbclosearea() )
aadd( afiles, { cFileName, "itm_id.ntx;itm_desc.ntx" } )
CATCH e
ShowError( cFileName, e )
afiles := {}
END
RETURN afiles
/*--------------------------------------------------------------------------------------------------------
CreateDictionary creates an Advantage Data Dictionary based on already existing tables
--------------------------------------------------------------------------------------------------------*/
STATIC FUNCTION CreateDictionary( afiles )
LOCAL cExt AS CHARACTER := ""
LOCAL cDD := cPath + "test_dd.add"
IF !ADSDDCREATE( cDD,, "Sample data dictinoary" )
ALERT( "AdsCreate() of " + cDD + " failed. Error:" + Str( AdsGetLastError() ) )
RETURN NIL
ENDIF
//Calling ACE function AdsDDSetDatabaseProperty()
AdsDDSetDatabaseProperty( ADS_DD_ENABLE_INTERNET, .t. )
AdsDDSetDatabaseProperty( ADS_DD_INTERNET_SECURITY_LEVEL, ADS_DD_LEVEL_2 )
AdsDDSetDatabaseProperty( ADS_DD_DEFAULT_TABLE_PATH, cPath )
AdsDDSetDatabaseProperty( ADS_DD_LOG_IN_REQUIRED, .t. )
//ACE Function ADsDDCreateUser() creates a dd user.
//When a new dd is created user ADSSYS is auto-created as the dd administrator
//it is a good idea to create other users to limit access and permissions.
//
AdsDDCreateUser( , "user1", "password1", "User named userd1 with password password1" )
AdsDDCreateUser( , "user2", "password2", "Description of user2" )
AdsDDCreateUser( , "user3", "password3", "Optional description of user3" )
//array aFiles contains the names of the tables to be added to the newly created
//data dictionary.
//element 1 on the array is the table name,
//element 2 on the array is the index file name.
//Since .dbf tables could be vfp, cdx, or ntx type tables,
//we are using the extension on the index file name to "guess" the .dbf
//file type. If this is already known beforehand, then the code below
//could be much simpler. I'm using AEVAL only because I love it albeit it is
//more cryptic. The same can be done on a FOR EACH (FOR/REPEAT/WHILE) loop
AEVAL( aFiles, ;
{ |e| hb_FNameSplit( iif( len( e ) > 1, e[ 2 ], e[ 1 ] ), , , @cExt ), ;
AdsSetFiletype( iif( lower( cExt ) $ ".adt,.adi", ADS_ADT, ;
iif( lower( cExt ) == ".ntx", ADS_NTX, ADS_VFP ) ) ),;
addfiletoDD( e, cPath ), ;
SetTableProp( e ), ;
QOut( "Adding table to DD", ;
e[ 1 ], ;
AdsSetFileType(), ;
cExt, ;
ADSGetLastError() ) } )
//assign the password "password" to the ADSSYS user of the DD. Just as default.
AdsDDSetDatabaseProperty( ADS_DD_ADMIN_PASSWORD, "password" )
Wait
return Nil
//-------------------------------------------------------------------------------------------------------
//This is the code that adds the table to the DD.
STATIC FUNCTION AddFiletoDD( aFile, cPath )
LOCAL cIndexs := ""
IF LEN( afile ) > 1 .AND. LEFT( afile[ 2 ], 1 ) <> "."
AEVAL( afile, { |e| cIndexs += e +";" }, 2 )
cIndexs := LEFT( cIndexs, LEN( cIndexs ) -1 )
ENDIF
RETURN( AdsDDAddTable( left( afile[ 1 ], at(".", afile[1] )-1 ), ;
cPath + aFile[ 1 ], ;
cIndexs ) )
//--------------------------------------------------------------------------------------------------------
//You may use this function to assign certain properties to all tables.
//The only table property I'm assigning is the auto_create property.
//Many others could also be applied. Look at ads.h include file for
//more constants.
STATIC FUNCTION SetTableProp( aFile )
LOCAL cFileName
hb_FNameSplit( afile[ 1 ],, @cFileName )
AdsDDSetTableProperty( cFileName, ADS_DD_TABLE_AUTO_CREATE, .t. )
// AdsDDSetTableProperty( cFileName, ADS_DD_TABLE_ENCRYPTION, .t. )
RETURN NIL
*-------------------------------------------------------------------------------------------------------------------------------
STATIC FUNCTION ShowError( cMsg, oErr )
LOCAL cErr
cErr := STR( AdsGetLastError() )
ALERT( "Error : " + ALLTRIM( cErr ) + " " + ;
cMsg + " " + oErr:Subsystem + " " + ;
STR( oErr:subCode ) + " " + oErr:operation + " " + oErr:description )
dbCloseAll()
RETURN NIL
//-----------------------------------------------------------------------------------------------------
STATIC FUNCTION CreateAndUseFreeTable()
LOCAL aStruct := { ;
{ "CHARACTER", "C", 25, 0 }, ;
{ "NUMERIC" , "N", 8, 0 }, ;
{ "DOUBLE" , "N", 8, 2 }, ;
{ "DATE" , "D", 8, 0 }, ;
{ "LOGICAL" , "L", 1, 0 }, ;
{ "MEMO1" , "M", 10, 0 }, ;
{ "MEMO2" , "M", 10, 0 } ;
}
DbCreate( "testdbf", aStruct, "DBFCDX", .T., "MYALIAS" )
Browse()
RETURN NIL
FUNCTION ADSOpeningDataBase()
// Para Tablas libre
REQUEST DBFCDX
USE "DB_PARAMS.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS DB_PARAMS
USE "SUMREP1.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS SUMREP1
USE "VERSION.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS VERSION
USE "DEVICES.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS DEVICES
// Para el dictionario de datos ADS
AdsConnect60( cPathDataDict, 2, "UserName", "Password", 1, @hConn) // ADS = 2 CLIENT/SERVER DATABASE
USE "USERS" NEW SHARED ALIAS USERS
USE "CUSTOMER" NEW SHARED ALIAS CUSTOMER
George wrote:Hola,
Asi lo uso:FUNCTION ADSOpeningDataBase()
// Para Tablas libre
REQUEST DBFCDX
USE "DB_PARAMS.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS DB_PARAMS
USE "SUMREP1.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS SUMREP1
USE "VERSION.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS VERSION
USE "DEVICES.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS DEVICES
// Para el dictionario de datos ADS
AdsConnect60( cPathDataDict, 2, "UserName", "Password", 1, @hConn) // ADS = 2 CLIENT/SERVER DATABASE
USE "USERS" NEW SHARED ALIAS USERS
USE "CUSTOMER" NEW SHARED ALIAS CUSTOMER
Saludos,
George
reinaldocrespo wrote:Abajo te incluyo código que acabo de probar y funciona perfectamente. Crea varias tablas de varios tipos diferentes (DBFNTX, DBFVFP, ADSADT) usando ADS RDD. Luego crea un dd y añade las 3 tablas al DD. Luego se conecta al DD y luego crea una 4ta tabla usando DBFCDX para entonces abrirla como un free table.
He probado usando xharbour de SVN + Borland c 5.82. El código es independiente de GUI, o sea, nada tiene que ver con fw y es código muy sencillo y corto. ¿Te funciona igual a ti?
- Code: Select all Expand view
//This console mode app shows how to create a few tables of different types.
//How to create an Advantage Data Dictionary and add the newly created
//tables the data dictionary file.
//I'm using various table types using ADS RDDs for DBF/NTX, DBF/VFP, ADT/ADI
//
//After that it atttempts to connect to the dd, create a new table and then
//open the new table as a free table.
//In short- it creates tables and dd, opens dd bound tables and free tables
//at the same time.
//
//The sample code uses pure rdds + some ACE calls.
//No GUI dependency as only a console mode app is being built, which should
//build just the same under Windows as well as under Linux.
//
#include "ads.ch"
#xcommand DEFAULT <uVar1> := <uVal1> ;
[, <uVarN> := <uValN> ] => ;
<uVar1> := iif( <uVar1> == nil, <uVal1>, <uVar1> ) ;;
[ <uVarN> := iif( <uVarN> == nil, <uValN>, <uVarN> ); ]
REQUEST DBFCDX
REQUEST ADS //Make sure rddads gets linked to our app.
REQUEST hb_gt_win //needed for console mode app.
//Static variable cPath will contain the path where tables and DD will be created.
//After connecting to an existing DD, there is no need to use the file path as the
//DD saves the relative path of each table as part of its metadata.
STATIC cPath
*-----------------------------------------------------------------------------------------------------
FUNCTION Main()
LOCAL afiles
SetMode(25,80) //25 lines by 80 columns console
rddRegister( "ADS", 1 )
rddSetDefault( "ADS" )
adsSetServerType( ADS_LOCAL_SERVER )
//NON-compatible locking mode. If other NON-ADS clients are going to
//to work on the same tables, then make sure to use compatible locking mode.
AdsLocking( .t. )
AdsRightsCheck( 0 )
//Path for existing .dbf tables maybe sent as a parameter
//on the command line. This is just one idea. It could be saved
//on a .ini file or hardcoded.
cPath := hb_ArgV( 1 )
//in case no path was sent on command line, assume current path.
DEFAULT cpath := ""
//sanitize cPath contents.
//IF !EMPTY( cPath ) .and. RIGHT( cPath, 1 ) != '' ;cPath += '' ;ENDIF
//if you need to create some new tables other than existing tables look
//at function CreateTables(). CreateTables shows how to create
//adt tables, vfp tables, and dbf-ntx tables.
//
//CreateTables() creates an array with table names and structure for each.
//It then creates the tables. After being created they will be added to a newly
//created data dictionary using function CreateDictionary().
//If your .dbf tables are alreay present, then you won't need to execute
//CreateTables, instead you could simply execute a Directory() harbour
//function to retreive existing table names. By storing the names of these tables
//into afiles variable, you can then execute CreateDictionary() in exactly the same
//manner.
afiles := CreateTables()
IF !EMPTY( afiles ) ;CreateDictionary( afiles ) ;ENDIF
//now that we have a dd created, we will attempt to connect to it and
//use the tables as dd bound tables.
IF !AdsConnect60( cPath + "test_dd.add", ADS_LOCAL_SERVER, "user1", "password1" )
Alert( "Cannot connect to test_dd" + Str( AdsGetLastError() ) )
QUIT
ENDIF
//Now we create a dbfcdx table to be used as a free table.
CreateAndUseFreeTable()
RETURN NIL
//--------------------------------------------------------------------------------------
//function CreateTables() will create three tables using stnd harbour func dbCreate
//Each table structure is saved on an array following the std returned by dbStruct()
//Each element on the array is an array describing the field. Thus, the array
//for a table with 3 fields would look like this:
//aStructure := { { cFieldName1, cFieldType1, nFldWidth, nDecimals },;
// { cFieldName2, cFieldType2, nFldWidth, nDecimals },;
// { cFieldName3, cFieldType3, nFldWidth, nDecimals } }
//
STATIC FUNCTION CreateTables()
LOCAL cAlias := "MyAlias"
LOCAL afiles := {}
LOCAL cFileName, e
//---------------------- customers.adt --------------------------------------------
LOCAL aStruc := { { "cust_id" , "C", 10, 0 },;
{ "Sequence" , "AutoInc", 07, 0 },; //ADT extended field type autoincrement
{ "customer_name" , "C", 25, 0 },;
{ "Start_date" , "TimeStamp", 01, 0 },; //ADT extended field type
{ "Notes" , "M", 10, 0 } }
AdsSetFileType( ADS_ADT )
TRY
dbCreate( ( cFileName := cPath + "customers.adt" ), aStruc,, .t., cAlias )
( cAlias )->( OrdCreate( cPath + "customers", "cust_id", "cust_id" ) )
( cAlias )->( OrdCreate( cPath + "customers", "Start_date", "Start_date" ) )
( cAlias )->( dbclosearea() )
AADD( afiles, { cFileName, "customers.adi" } )
//------------------------ sales.dbf -------------------------------------------------
aStruc := { { "cust_id" , "C", 10, 0 },;
{ "invoice" , "C", 15, 0 },;
{ "s_date" , "TimeStamp", 01, 0 },; //VFP extended field type
{ "item_id" , "C", 15, 0 },;
{ "Units" , "N", 03, 0 },;
{ "Price" , "Money", 09, 2 },; //VFP extended field type
{ "Notes" , "M", 10, 0 } }
AdsSetFileType( ADS_VFP )
dbCreate( ( cFileName := cPath + "sales.dbf" ), aStruc,, .t., cAlias )
( cAlias )->( OrdCreate( cPath + "sales", "invoice", "invoice" ) )
( cAlias )->( OrdCreate( cPath + "sales", "cust_id", "cust_id" ) )
( cAlias )->( dbclosearea() )
aadd( afiles, { cFileName, "sales.cdx" } )
//------------------------ items.dbf -------------------------------------------------
aStruc := { { "item_id" , "C", 15, 0 },;
{ "Desc" , "C", 25, 0 },;
{ "Price" , "N", 07, 2 } }
AdsSetFileType( ADS_NTX )
dbCreate( ( cFileName := cPath + "items.dbf" ), aStruc,, .t., cAlias )
( cAlias )->( OrdCreate( cPath + "itm_id",, "item_id" ) )
( cAlias )->( OrdCreate( cPath + "itm_desc",, "Desc" ) )
( cAlias )->( dbclosearea() )
aadd( afiles, { cFileName, "itm_id.ntx;itm_desc.ntx" } )
CATCH e
ShowError( cFileName, e )
afiles := {}
END
RETURN afiles
/*--------------------------------------------------------------------------------------------------------
CreateDictionary creates an Advantage Data Dictionary based on already existing tables
--------------------------------------------------------------------------------------------------------*/
STATIC FUNCTION CreateDictionary( afiles )
LOCAL cExt AS CHARACTER := ""
LOCAL cDD := cPath + "test_dd.add"
IF !ADSDDCREATE( cDD,, "Sample data dictinoary" )
ALERT( "AdsCreate() of " + cDD + " failed. Error:" + Str( AdsGetLastError() ) )
RETURN NIL
ENDIF
//Calling ACE function AdsDDSetDatabaseProperty()
AdsDDSetDatabaseProperty( ADS_DD_ENABLE_INTERNET, .t. )
AdsDDSetDatabaseProperty( ADS_DD_INTERNET_SECURITY_LEVEL, ADS_DD_LEVEL_2 )
AdsDDSetDatabaseProperty( ADS_DD_DEFAULT_TABLE_PATH, cPath )
AdsDDSetDatabaseProperty( ADS_DD_LOG_IN_REQUIRED, .t. )
//ACE Function ADsDDCreateUser() creates a dd user.
//When a new dd is created user ADSSYS is auto-created as the dd administrator
//it is a good idea to create other users to limit access and permissions.
//
AdsDDCreateUser( , "user1", "password1", "User named userd1 with password password1" )
AdsDDCreateUser( , "user2", "password2", "Description of user2" )
AdsDDCreateUser( , "user3", "password3", "Optional description of user3" )
//array aFiles contains the names of the tables to be added to the newly created
//data dictionary.
//element 1 on the array is the table name,
//element 2 on the array is the index file name.
//Since .dbf tables could be vfp, cdx, or ntx type tables,
//we are using the extension on the index file name to "guess" the .dbf
//file type. If this is already known beforehand, then the code below
//could be much simpler. I'm using AEVAL only because I love it albeit it is
//more cryptic. The same can be done on a FOR EACH (FOR/REPEAT/WHILE) loop
AEVAL( aFiles, ;
{ |e| hb_FNameSplit( iif( len( e ) > 1, e[ 2 ], e[ 1 ] ), , , @cExt ), ;
AdsSetFiletype( iif( lower( cExt ) $ ".adt,.adi", ADS_ADT, ;
iif( lower( cExt ) == ".ntx", ADS_NTX, ADS_VFP ) ) ),;
addfiletoDD( e, cPath ), ;
SetTableProp( e ), ;
QOut( "Adding table to DD", ;
e[ 1 ], ;
AdsSetFileType(), ;
cExt, ;
ADSGetLastError() ) } )
//assign the password "password" to the ADSSYS user of the DD. Just as default.
AdsDDSetDatabaseProperty( ADS_DD_ADMIN_PASSWORD, "password" )
Wait
return Nil
//-------------------------------------------------------------------------------------------------------
//This is the code that adds the table to the DD.
STATIC FUNCTION AddFiletoDD( aFile, cPath )
LOCAL cIndexs := ""
IF LEN( afile ) > 1 .AND. LEFT( afile[ 2 ], 1 ) <> "."
AEVAL( afile, { |e| cIndexs += e +";" }, 2 )
cIndexs := LEFT( cIndexs, LEN( cIndexs ) -1 )
ENDIF
RETURN( AdsDDAddTable( left( afile[ 1 ], at(".", afile[1] )-1 ), ;
cPath + aFile[ 1 ], ;
cIndexs ) )
//--------------------------------------------------------------------------------------------------------
//You may use this function to assign certain properties to all tables.
//The only table property I'm assigning is the auto_create property.
//Many others could also be applied. Look at ads.h include file for
//more constants.
STATIC FUNCTION SetTableProp( aFile )
LOCAL cFileName
hb_FNameSplit( afile[ 1 ],, @cFileName )
AdsDDSetTableProperty( cFileName, ADS_DD_TABLE_AUTO_CREATE, .t. )
// AdsDDSetTableProperty( cFileName, ADS_DD_TABLE_ENCRYPTION, .t. )
RETURN NIL
*-------------------------------------------------------------------------------------------------------------------------------
STATIC FUNCTION ShowError( cMsg, oErr )
LOCAL cErr
cErr := STR( AdsGetLastError() )
ALERT( "Error : " + ALLTRIM( cErr ) + " " + ;
cMsg + " " + oErr:Subsystem + " " + ;
STR( oErr:subCode ) + " " + oErr:operation + " " + oErr:description )
dbCloseAll()
RETURN NIL
//-----------------------------------------------------------------------------------------------------
STATIC FUNCTION CreateAndUseFreeTable()
LOCAL aStruct := { ;
{ "CHARACTER", "C", 25, 0 }, ;
{ "NUMERIC" , "N", 8, 0 }, ;
{ "DOUBLE" , "N", 8, 2 }, ;
{ "DATE" , "D", 8, 0 }, ;
{ "LOGICAL" , "L", 1, 0 }, ;
{ "MEMO1" , "M", 10, 0 }, ;
{ "MEMO2" , "M", 10, 0 } ;
}
DbCreate( "testdbf", aStruct, "DBFCDX", .T., "MYALIAS" )
Browse()
RETURN NIL
Observa que una vez construyes el .exe, para probarlo necesitas enviar el "path" a donde se deben crear las tablas, el dd, y la tabla libre. Por ejemplo: "c:\createdd.exe c:\data\"
Reinaldo.
//This console mode app shows how to create a few tables of different types.
//How to create an Advantage Data Dictionary and add the newly created
//tables the data dictionary file.
//I'm using various table types using ADS RDDs for DBF/NTX, DBF/VFP, ADT/ADI
//
//After that it atttempts to connect to the dd, create a new table and then
//open the new table as a free table.
//In short- it creates tables and dd, opens dd bound tables and free tables
//at the same time.
//
//The sample code uses pure rdds + some ACE calls.
//No GUI dependency as only a console mode app is being built, which should
//build just the same under Windows as well as under Linux.
//
#include "ads.ch"
#xcommand DEFAULT <uVar1> := <uVal1> ;
[, <uVarN> := <uValN> ] => ;
<uVar1> := iif( <uVar1> == nil, <uVal1>, <uVar1> ) ;;
[ <uVarN> := iif( <uVarN> == nil, <uValN>, <uVarN> ); ]
REQUEST DBFCDX
REQUEST ADS //Make sure rddads gets linked to our app.
REQUEST hb_gt_win //needed for console mode app.
//Static variable cPath will contain the path where tables and DD will be created.
//After connecting to an existing DD, there is no need to use the file path as the
//DD saves the relative path of each table as part of its metadata.
STATIC cPath
*-----------------------------------------------------------------------------------------------------
FUNCTION Main()
LOCAL afiles
SetMode(25,80) //25 lines by 80 columns console
rddRegister( "ADS", 1 )
rddSetDefault( "ADS" )
adsSetServerType( ADS_LOCAL_SERVER )
//NON-compatible locking mode. If other NON-ADS clients are going to
//to work on the same tables, then make sure to use compatible locking mode.
AdsLocking( .t. )
AdsRightsCheck( 0 )
//Path for existing .dbf tables maybe sent as a parameter
//on the command line. This is just one idea. It could be saved
//on a .ini file or hardcoded.
cPath := hb_ArgV( 1 )
//in case no path was sent on command line, assume current path.
DEFAULT cpath := ""
IF !AdsConnect60( cPath + "test_dd.add", ADS_LOCAL_SERVER, "user1", "password1" )
Alert( "Cannot connect to test_dd" + Str( AdsGetLastError() ) )
QUIT
ENDIF
//Now we create a dbfcdx table to be used as a free table.
//CreateAndUseFreeTable()
OpenExistingFreeTable()
RETURN NIL
//-----------------------------------------------------------------------------------------------------
STATIC FUNCTION OpenExistingFreeTable()
DbUseArea( .T., "DBFCDX", "testdbf", "TestAlias", .T., .F. )
Browse()
RETURN NIL
//-----------------------------------------------------------------------------------------------------
reinaldocrespo wrote:No veo que haga alguna diferencia y de hecho tu misma pudieras hacer la prueba con el mismo código que te he escrito.
Abajo te incluyo nuevo código que hace la prueba tal como la deseas. Observa que he removido código que crean tablas y el dd y he añadido una sola función de 2 lineas para abrir y ver una tabla libre ya existente después de estar conectados al ADS DD. La tabla existente y el DD son producto del código que anteriormente tienes en este mismo hilo:
- Code: Select all Expand view
//This console mode app shows how to create a few tables of different types.
//How to create an Advantage Data Dictionary and add the newly created
//tables the data dictionary file.
//I'm using various table types using ADS RDDs for DBF/NTX, DBF/VFP, ADT/ADI
//
//After that it atttempts to connect to the dd, create a new table and then
//open the new table as a free table.
//In short- it creates tables and dd, opens dd bound tables and free tables
//at the same time.
//
//The sample code uses pure rdds + some ACE calls.
//No GUI dependency as only a console mode app is being built, which should
//build just the same under Windows as well as under Linux.
//
#include "ads.ch"
#xcommand DEFAULT <uVar1> := <uVal1> ;
[, <uVarN> := <uValN> ] => ;
<uVar1> := iif( <uVar1> == nil, <uVal1>, <uVar1> ) ;;
[ <uVarN> := iif( <uVarN> == nil, <uValN>, <uVarN> ); ]
REQUEST DBFCDX
REQUEST ADS //Make sure rddads gets linked to our app.
REQUEST hb_gt_win //needed for console mode app.
//Static variable cPath will contain the path where tables and DD will be created.
//After connecting to an existing DD, there is no need to use the file path as the
//DD saves the relative path of each table as part of its metadata.
STATIC cPath
*-----------------------------------------------------------------------------------------------------
FUNCTION Main()
LOCAL afiles
SetMode(25,80) //25 lines by 80 columns console
rddRegister( "ADS", 1 )
rddSetDefault( "ADS" )
adsSetServerType( ADS_LOCAL_SERVER )
//NON-compatible locking mode. If other NON-ADS clients are going to
//to work on the same tables, then make sure to use compatible locking mode.
AdsLocking( .t. )
AdsRightsCheck( 0 )
//Path for existing .dbf tables maybe sent as a parameter
//on the command line. This is just one idea. It could be saved
//on a .ini file or hardcoded.
cPath := hb_ArgV( 1 )
//in case no path was sent on command line, assume current path.
DEFAULT cpath := ""
IF !AdsConnect60( cPath + "test_dd.add", ADS_LOCAL_SERVER, "user1", "password1" )
Alert( "Cannot connect to test_dd" + Str( AdsGetLastError() ) )
QUIT
ENDIF
//Now we create a dbfcdx table to be used as a free table.
//CreateAndUseFreeTable()
OpenExistingFreeTable()
RETURN NIL
//-----------------------------------------------------------------------------------------------------
STATIC FUNCTION OpenExistingFreeTable()
DbUseArea( .T., "DBFCDX", "testdbf", "TestAlias", .T., .F. )
Browse()
RETURN NIL
//-----------------------------------------------------------------------------------------------------
Igualmente funciona perfectamente.
Te animo a que escribas un ejemplo reducido, o sea, tan reducido como sea posible, que recree el problema que describes. Seguramente así te podamos ayudar mejor. No creo que exista problema alguno con abrir tablas libres mientras estás conectado a un dd, de otra manera mucha gente estaría reportando ese problema y si te fijas en el foro de Advantage no existe mención de problema tal.
Saludos,
Reinaldo.
Return to FiveWin para Harbour/xHarbour
Users browsing this forum: Adolfredo Martinez, Google [Bot] and 71 guests