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.