The section in this chapter, "Using MicroStation Database Servers from Initapps" provides information on how to use MDL to interface MicroStation to databases.
There are various debug commands that will help diagnose problems when interacting with databases. Here is a breakdown of all of the debug commands and their effects:
MS_SERVER
This is the task name of your mdl loader application.
MS_LINKTYPE
This is the same environment variable that was needed in earlier versions of MicroStation. It specifies the type of links that are understood by the server. The first in the list is the type that will be written.
MS_SESSION_DEBUG
Setting this configuration variableto 1 starts debugging on database initialization. This can be beneficial when investigating situations when SERVER.MA is not loading.
MicroStation database servers can be started for use by an initapp. Typically MicroStation is configured for use with a database by designating the "server" MDL application as a design file application (dgnapp). The server gets the value of the MS_SERVER environment variable and starts the mdl loader. The MDL loader will determine the name of the external server by getting the MS_DBEXT environment variable and start the external server. When a MicroStation initapp is started, no design file has been attached, so the dgnapps, including the server application, have not yet been started.
Therefore, before using one of the database servers, mdlSystem_loadMdlProgram must be called to load the MDL server server.ma. When mdlSystem_loadMdlProgram is called it should be given the argument FRONTEND. This will notify the loader that it is being loaded from an initapp. A loader must know that it is being started as an initapp because MicroStation sends several startup messages to the server when the server is launched as a dgnapp. The FRONTEND argument will ensure that the loader simulates this "handshaking."
To complete the process of making the database server available from an initapp, log on to the database by issuing a connect statement with mdlDB_activeDatabase.
If the initapp will put MicroStation in graphics mode, further considerations must be made. If control will return to the initapp after MicroStation exits graphics, the server connection must be reestablished as above from the reload hook if the database is to be accessed from the initapp. This is necessary because MicroStation unloads all MDL applications including the loader when exiting graphics and returning to the initapp. When the reload function is finished with the server, it must unload the loader so the server is properly terminated.
The following code is presented as a sample skeleton initapp that uses a database server. The main routine first initializes the database server and does any necessary pre-processing of the database. The initapp then enters graphics, sets a reload function and attaches a DGN file. The reload function is called when MicroStation exits graphics. The database server is reloaded and any post-processing of the database is done here. Finally, the server is terminated and MicroStation is exited.
- You need to create an ODBC data source called GIS and point it to the delivered GIS.mdb delivered example for this to work. /*--------------------------------------------------------------------+ | | $Copyright: (c) 2006 Bentley Systems, Incorporated. | All rights reserved. $ | +--------------------------------------------------------------------*/ /*-----------------------------------------------------------------+ | dbinit.mc | | To execute from the command line: ustation.exe -WAdbinit.ma | +-----------------------------------------------------------------*/ /*-----------------------------------------------------------------+ | Include Files | +-----------------------------------------------------------------*/ #include <mdl.h> #include <cexpr.h> #include <system.h> #include <global.h> #include <dbdefs.h> #include <dberrs.h> #include <userfnc.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <msdb.fdf> #include <mssystem.fdf> #include <rdbmslib.fdf> /*-----------------------------------------------------------------+ | Private Global Variables | +------------------------------------------------------------------*/ /*-----------------------------------------------------------------+ | Major Public Code Section | +------------------------------------------------------------------*/ /*--------------------------------------------------------------------+ | | dbAttach | +--------------------------------------------------------------------*/ Private void dbAttach ( char *database, /* => Database connect string */ char *cfgFile /* => Database connection type i.e. ODBC, ORACLE, ... */ ) { DatabaseProfile profileP; int status; char buffer[255]; char cfgVarValue[MAXFILELENGTH]; char cfgFileSpec[MAXFILELENGTH]; /* Detatch database in a polite manner */ mdlDB_activeDatabase (" "); /* Remove existing database variable values */ mdlSystem_deleteCfgVar ("MS_DBASE"); mdlSystem_deleteCfgVar ("MS_SERVER"); mdlSystem_deleteCfgVar ("MS_LINKTYPE"); /* Unload server to guarantee a clean load of database cfg file */ if (mdlSystem_getTaskStatistics (NULL, "server") == SUCCESS) mdlSystem_unloadMdlProgram ("server"); /* Find the path to the database configuration directory */ mdlSystem_getCfgVar (cfgVarValue, "_USTN_DATABASE", MAXFILELENGTH); /* Create a Filespec for database configuration file to open */ sprintf (cfgFileSpec, "%s%s.cfg", mdlSystem_expandCfgVar(cfgVarValue), cfgFile); /* Load database configuration file */ status = mdlSystem_processCfgVarFile (cfgFileSpec, CFGVAR_LEVEL_USER); if (status == SUCCESS) { status = mdlSystem_loadMdlProgram ("server.ma", "server", "FRONTEND"); if (status == SUCCESS) { /* Determine the database connection just loaded */ status = mdlDB_databaseProfile (&profileP); /* If database is ORACLE connect this way */
/*--------------------------------------------------------------------+ | | $Copyright: (c) 2006 Bentley Systems, Incorporated. | All rights reserved. $ | +--------------------------------------------------------------------*/ /*-----------------------------------------------------------------+ | dbinit.mc | | To execute from the command line: ustation.exe -WAdbinit.ma | +-----------------------------------------------------------------*/ /*-----------------------------------------------------------------+ | Include Files | +-----------------------------------------------------------------*/ #include <mdl.h> #include <cexpr.h> #include <system.h> #include <global.h> #include <dbdefs.h> #include <dberrs.h> #include <userfnc.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <msdb.fdf> #include <mssystem.fdf> #include <rdbmslib.fdf> /*-----------------------------------------------------------------+ | Private Global Variables | +------------------------------------------------------------------*/ /*-----------------------------------------------------------------+ | Major Public Code Section | +------------------------------------------------------------------*/ /*--------------------------------------------------------------------+ | | dbAttach | +--------------------------------------------------------------------*/ Private void dbAttach ( char *database, /* => Database connect string */ char *cfgFile /* => Database connection type i.e. ODBC, ORACLE, ... */ ) { DatabaseProfile profileP; int status; char buffer[255]; char cfgVarValue[MAXFILELENGTH]; char cfgFileSpec[MAXFILELENGTH]; /* Detatch database in a polite manner */ mdlDB_activeDatabase (" "); /* Remove existing database variable values */ mdlSystem_deleteCfgVar ("MS_DBASE"); mdlSystem_deleteCfgVar ("MS_SERVER"); mdlSystem_deleteCfgVar ("MS_LINKTYPE"); /* Unload server to guarantee a clean load of database cfg file */ if (mdlSystem_getTaskStatistics (NULL, "server") == SUCCESS) mdlSystem_unloadMdlProgram ("server"); /* Find the path to the database configuration directory */ mdlSystem_getCfgVar (cfgVarValue, "_USTN_DATABASE", MAXFILELENGTH); /* Create a Filespec for database configuration file to open */ sprintf (cfgFileSpec, "%s%s.cfg", mdlSystem_expandCfgVar(cfgVarValue), cfgFile); /* Load database configuration file */ status = mdlSystem_processCfgVarFile (cfgFileSpec, CFGVAR_LEVEL_USER); if (status == SUCCESS) { status = mdlSystem_loadMdlProgram ("server.ma", "server", "FRONTEND"); if (status == SUCCESS) { /* Determine the database connection just loaded */ status = mdlDB_databaseProfile (&profileP); /* If database is ORACLE connect this way */
// 0 == Added by Keith Bertram - Bentley 2/3/2009
if (0 == strcmpi (profileP.brand.brandName, "ORACLE")) { sprintf (buffer, "connect %s", database); status = mdlDB_processSQL (buffer); } else { /* ... else connect this way */ status = mdlDB_activeDatabase (database); if (status != SUCCESS) printf ("Unable to connect!"); } } else { printf ("Unable to load server.ma!"); } } else { printf ("Unable to locate config file!"); } } /*-----------------------------------------------------------------+ | name reloadFunction | | This function is called by MicroStation after the | user closes the design file opened in main. | +-----------------------------------------------------------------*/ void reloadFunction ( int argc, char *argv[] ) { char buffer[256]; int status; /* The database server is unloaded by MicroStation when closing the design file. If more work needs to be done with the database, the server must be reactivated. */ dbAttach ("gis", "ODBC"); /* do any necessary "cleanup" work with the database */ status=mdlDB_sqlQuery(buffer, "select owner from parcel where mslink=1"); /* unload the loader here so the server is properly terminated */ mdlSystem_unloadMdlProgram("server"); /* exit the MDL initapp and MicroStation will exit */ mdlSystem_exit(0, 1); } /*-----------------------------------------------------------------+ | | name main | +-----------------------------------------------------------------*/ cmdName main() { char buffer[256]; int status; dbAttach ("gis", "ODBC"); /* do any necessary setup work with the database */ status=mdlDB_sqlQuery(buffer, "select owner from parcel where mslink=1"); printf("query result <%s>\n", buffer); mdlSystem_enterGraphics(); /* Set the function MDL should call when it needs to reload this MDL application. This function will be called, for example, when the user chooses to close the current design file. */ mdlSystem_setFunction(SYSTEM_RELOAD_PROGRAM, reloadFunction); mdlSystem_newDesignFile("database"); return status; } #---------------------------------------------------------------------- # # dbinit.mke # # $Copyright: (c) 2006 Bentley Systems, Incorporated. # All rights reserved. $ # #---------------------------------------------------------------------- #---------------------------------------------------------------------- # # Compile Applications with only an MC file. # #---------------------------------------------------------------------- appName = dbinit baseDir = $(_MakeFilePath) %include mdl.mki #---------------------------------------------------------------------- # Create output directories #---------------------------------------------------------------------- always: ~mkdir $(o) #---------------------------------------------------------------------- # Compile MC Source #---------------------------------------------------------------------- $(o)$(appName).mo : $(baseDir)$(appName).mc $(mdlapps)$(appName).ma : $(o)$(appName).mo $(mdlLibs)rdbmslib.dlo