Global Mapper v25.0

How manipulate layers with functions of databases

Aplies
Aplies Global Mapper UserTrusted User
edited April 2013 in SDK
Hello,

I'm trying to get layers from spatial databases but I don't understand how this works.
Indeed, we never get a layer structure with the functions. We manipulate "GM_DB_TableList_t32" structure and I don't know how use this to get a layer with the other functions of SDK.

Best regards,

Tristan C.

Comments

  • bmg_bob
    bmg_bob Global Mapper Programmer
    edited April 2013
    Hello,

    You can get a layer for a database table using GM_LoadLayerListEx:
    GM_DLL_EXPORTED GM_Error_t32 __stdcall GM_LoadLayerListEx
        ( 
        const char*             aFilename,
        GM_LayerHandle_t32**    aLayerList,
        uint32*                 aNumLoadedLayers,
        GM_LoadFlags_t32        aLoadFlags,
        const char*             aExtraLoadOptions
        );
    

    Pass the file name of the database in the aFileName parameter. (If you are connecting to a spatial database on a server, you will need to create a connection string using the GM_DBMakeConnectionString function, then pass the connection string in the aFileName parameter.) Pass the name of the table you want to read in the aExtraLoadOptions parameter.

    Here is a snippet from the GMDLL_Tester sample program. In the snippet, we start with the aFileName value. If that variable contains the name of a database file (or connection string) we get the list of tables from the database and choose the first table. If you want to allow your user to choose a table name, you will need to a UI for that.
    GM_Error_t32 theErr = GM_Error_None;
    
    // Load as a database table
    std::string theTableName;
    if ( GM_DBIsDatabaseFile( aFilename ) )
    {
        // Get the list of tables to load
        GM_DB_TableList_t32 theTableList = NULL;
        theErr = GM_DBSelectTable( &theTableList, aFilename );
        if ( GM_Error_None == theErr )
        {
            // If any tables were selected, add them to the load string
            uint32 theCount = 0;
            theErr = GM_DBTableList_GetCount( &theCount, theTableList );
            if ( theCount > 0 )
            {
                // For the purposes of this example, only load the first table in the list.
                char theTempTableName[_MAX_PATH];
                theErr = GM_DBTableList_GetTableName( theTempTableName, 0, theTableList );
                theTableName = theTempTableName;
            }
    
            // Free the table list
            GM_DBTableList_Free( &theTableList );
            theTableList = NULL;
        }
    }
    
    // Load the layer
    GM_LayerHandle_t32* theLayerHandleList = NULL;
    uint32 theNumLayersLoaded = 0;
    theErr = GM_LoadLayerListEx
    (
        aFilename, &theLayerHandleList, &theNumLayersLoaded, aLoadFlags, theTableName.c_str()
    );
    

    Once you have the layer handle list, you can access the data in the layers the same as any other layer type.

    I hope this helps.

    Cheers,

    Bob
  • Aplies
    Aplies Global Mapper User Trusted User
    edited April 2013
    Thanks for your answer helpful.
    It's very simple actually.

    Best regards,

    Tristan C.
  • Aplies
    Aplies Global Mapper User Trusted User
    edited April 2013
    Hello,

    I have another problem. I can't connect to a spatial database Oracle 10.2 .
    I get a connection string with GM_DBMakeConnectionString, then I try GM_DBTestConnection with this string but it displays :
    "Database connection failed : in <unamed>"
    I verified the connection between my computer and the database with the client of Oracle system, and its good. Its just with the SDK.

    Code to create string connection:

    GlobalMapperDLL.GM_DBConnectionParms_t connectionParameters = new GlobalMapperDLL.GM_DBConnectionParms_t();
    connectionParameters.mConnectionName = "ConnectionBDD";
    connectionParameters.mDbType = GlobalMapperDLL.GM_db_type_t8.GM_DB_TYPE_ORACLE;
    connectionParameters.mServer = server;
    connectionParameters.mPort = port;
    connectionParameters.mDbName = database;
    connectionParameters.mUserName = user;
    connectionParameters.mPassword = password;

    // Allocate a large buffer
    IntPtr connectionStringPointer = Marshal.AllocCoTaskMem(1024);

    LastGMError = GlobalMapperDLL.GM_DBMakeConnectionString(connectionStringPointer, (uint)1024, ref connectionParameters);

    if (LastGMError == GlobalMapperDLL.GM_Error_t32.GM_Error_None)
    {
    // Copy the filename to our own string and free the dynamically allocated buffer
    string connectionString = Marshal.PtrToStringAnsi(connectionStringPointer);
    Marshal.FreeCoTaskMem(connectionStringPointer);
    return connectionString;
    }

    Best regards,

    Tristan C.
  • Aplies
    Aplies Global Mapper User Trusted User
    edited April 2013
    I tried too several implementation for GM_DBConnectionParms_t structure in C#, but it doesn't work :

    public struct GM_DBConnectionParms_t
    {
    public GM_db_type_t8 mDbType;
    public IntPtr mConnectionName;
    public IntPtr mServer;
    public IntPtr mPort;
    public IntPtr mDbName;
    public IntPtr mUserName;
    public IntPtr mPassword;
    } ;

    public struct GM_DBConnectionParms_t
    {
    public GM_db_type_t8 mDbType;
    public String mConnectionName;
    public String mServer;
    public String mPort;
    public String mDbName;
    public String mUserName;
    public String mPassword;
    } ;

    Best regards,

    Tristan C.
  • Aplies
    Aplies Global Mapper User Trusted User
    edited April 2013
    Actually, my connection string is good :

    "<gm_conn_str>:name=X,type=2,host=X.X.X.X,port=X,database=X,user=X,password=X"

    Its just the function GM_DBTestConnection which returns an error.

    Best regards,

    Tristan C.