AXForum  
Вернуться   AXForum > Блоги > Заметки по Dynamics Ax от Poleax
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

Рейтинг: 5.00. Голосов: 3.

Connecting to Databases through X++

Запись от Poleax размещена 14.10.2010 в 17:31

Connecting to Databases through X++

In this article, I am going to explain about different ways through which one can connect to different databases for data manipulation operations.

In AX, the methods that I know are following. Please feel free to add more methods that you feel are also available.
  • ODBC Connection
  • ADO Connection
  • OleDB Connection
  • Connection class

Let us go through each of these options one by one.

ODBC Connection:

ODBC stands for Open Data Base Connectivity. It is a connection that is created to define a connection between a computer and a database stored on another system. The ODBC connection contains information needed to allow a computer user to access the information stored in a database that is not local to that computer. In Dynamics AX, we have ODBCConnection class to carry out this type of database connection need. This class uses LoginProperty class for login information and uses Statement and ResultSet classes for carrying out DML operations. Below is an example of how to use this class.
X++:
    static void dbODBCConnection(Args _args)
    {
        LoginProperty   loginProp;
        ODBCConnection  conn;
        Resultset       resultSet, resultSetCount;
        Statement       statement1, statement2;
        ;

        loginProp = new LoginProperty();

        loginProp.setServer('SUMIT');
        loginProp.setDatabase('AX2009');

        conn = new ODBCConnection(loginProp);

        statement1  = conn.createStatement();
        resultSet   = statement1.executeQuery("SELECT * from CustTable where DATAAREAID = 'CEU'");

        while (resultSet.next())
        {
            info(resultSet.getString(1));
        }
     }
The above sample code is a job. Note that you may have to use respective permission classes like SQLStatementExecutePermission etc. while using in classes and any other place. Note that if you need to invoke a stored procedure then just type exec <SPName> in the executeQuery instead of the select statement.

ADO Connection:

ADO is an abbreviation for ActiveX Data Objects. ADO is a set of COM objects for accessing databases or data stores. In AX we have following objects making a collection for implementing ADO concept.
  • CCADOConnection - Helps in establishing a connection to the target database.
  • CCADOCommand - Helps in executing a command (a Text type or a Stored procedure)
  • CCADORecordSet - Stores the data
  • CCADOFields - A collection of all fields in CCADORecordSet
  • CCADOField - A single field from the collection of fields
  • CCADOParameter - A class that helps in passing parameters that a command needs or demands
The example below demonstrates the working of some of these classes:

X++:
   static void dbCCADOConnection(Args _args)
    {
        CCADOConnection connection = new CCADOConnection();
        CCADOCommand    ccADOCommand;
        CCADORecordSet  record;
        str connectStr = "Provider=SQLNCLI.1;Integrated Security=SSPI;"+
                         "Persist Security Info=False;Initial Catalog=AX2009;Data Source=SUMIT";

        COM     recordSet;  /*This is required to call moveNext method to parse the record set. In AX 4.0 this method was there in the CCADORecordSet class but in AX 2009 this has been deleted*/
        ;

        // Executing a SQL Statement
        try
        {
            connection.open(connectStr);
            ccADOCommand = new CCADOCommand();
            ccADOCommand.commandText("Select * from CustTable where DataAreaId = 'CEU'");
            ccADOCommand.activeConnection(connection);
            record = ccADOCommand.execute();
            recordSet = record.recordSet();
            while (!record.EOF())
            {
                info(any2str(record.fields().itemIdx(0).value()));
                recordSet.moveNext();
            }
        }
        catch
        {
            error("An Exception has occurred");
        }

        connection.close();
    }
The above sample code is a job. Note that you may have to use respective permission classes like SQLStatementExecutePermission etc. while using in classes and any other place.

OLEDB Connection:

OLEDB stands for Object Linking and Embedding, DataBase. It is a set of APIs designed by Microsoft and used for accessing different types of data stored in a uniform manner. Dynamics AX as such doesn't have any specific classes built for this purpose. But one can make use of .Net Framework's System.Data.OleDb namespace through AX's COM Interoperability feature and use it in AX.

Below is an example code that depicts this scenario:
X++:
    static void dbOLEDBConnection(Args _args)
    {
        System.Exception                    e;
        System.Data.OleDb.OleDbConnection   objConn;
        System.Data.OleDb.OleDbCommand      cmdSelect;
        System.Data.OleDb.OleDbDataReader   reader;
        InteropPermission                   perm;
        str connectStr = "Provider=SQLNCLI.1;Integrated Security=SSPI;"+
                         "Persist Security Info=False;Initial Catalog=AX2009;Data Source=SUMIT";
        str exceptionStr;
        ;

        try
        {
            perm = new InteropPermission(InteropKind::ClrInterop);
            if (perm == null)
            {
                throw error("Error with file permissions");
            }
            perm.assert();

            objConn = new System.Data.OleDb.OleDbConnection(connectStr);
            objConn.Open();

            cmdSelect   = objConn.CreateCommand();
            cmdSelect.set_CommandText("SELECT * FROM CustTable where DATAAREAID = 'CEU'");
            reader      = cmdSelect.ExecuteReader();

            while (reader.Read())
            {
                info(reader.GetString(0));
            }
        }
        catch(Exception::CLRError)
        {
            CodeAccessPermission::revertAssert();

            perm = new InteropPermission(InteropKind::ClrInterop);
            if (perm == null)
            {
                return;
            }
            perm.assert();

            e = ClrInterop::getLastException();

            CodeAccessPermission::revertAssert();

            while( e )
            {
                exceptionStr += e.get_Message();
                e = e.get_InnerException();
            }
            info(exceptionStr);
        }
        catch
        {
            error("An Exception has occurred");
        }

        if(objConn)
            objConn.Close();
    }

Connection Class:


Connection class is mainly used for accessing the database in which a user has logged into AX i.e. Current Database and carry out the operations. This class is exetensively used in ReleaseUpdateDB classes, the classes used in data upgrades. This class cannot be run on client and should always be run on server. One more unique thing that I noticed is that the statements that you want to execute should be asserted first for permissions and then passed on to other method where they are executed. Create a class with following methods and set its RunOn property to Server.
X++:
    class TestSQLExecuteClass
    {
    }

    //This method tests the permissions for statement and then calls the method that will execute the statement
    static void dbConnectionClass()
    {
        ResultSet   rs;
        SqlStatementExecutePermission perm;
        ;

        perm = new SQLStatementExecutePermission("select * from CustTable where DATAAREAID = 'CEU'");
        perm.assert();

        rs = TestSQLExecuteClass::statementExeQuery("select * from CustTable where DATAAREAID = 'CEU'");

        while (rs.next())
        {
            info(rs.getString(1));
        }
        CodeAccessPermission::revertAssert();
    }

    //Executes the passed statement
    private static ResultSet statementExeQuery(str _sql, Connection _con = null)
    {
        ResultSet   resultSet;
        Statement   statement;
        ;

        try
        {
            if(!_con)
            {
                _con = new Connection();
            }

            statement = _con.createStatement();

            // Do not call assert() here, do it in the caller
            // BP deviation documented
            resultSet = statement.executeQuery(_sql);
        }
        catch (Exception::Error)
        {
            throw error("@SYS99562");
        }

        return resultSet;
    }
Now you can call the method in a job as shown below:
X++:
    static void dbConnectionClass(Args _args)
    {
        ;

        TestSQLExecuteClass::dbConnectionClass();
    }
These examples shown here are pretty simple and easy to understand and start with. Hope it helps you in building 'connections' Tongue out.
Размещено в Без категории
Просмотров 82819 Комментарии 3
Всего комментариев 3

Комментарии

  1. Старый комментарий
    Аватар для a33ik
    Такой вопрос. Я совсем не знаю x++, поверхностно знаю с++. Почему в коде встречаются одинокие ; ?
    Запись от a33ik размещена 16.10.2010 в 20:05 a33ik is offline
  2. Старый комментарий
    Аватар для mazzy
    отличный. FAQ'овый вопрос.

    X++ разрешает использовать одинаковые имена для типов и для переменных. (Скорее всего, здесь нет какой-то задумки, а просто "так получилось")
    В результате, система не может определить где кончается блок определения переменных и начинается использование переменных.

    например,
    X++:
    {
    MySuperName4Class MySuperName4Class;
    
    MySuperName4Class.mySuperMethod(); // ошибка компиляции
    }
    во второй строчке идет использование переменной.
    но мозгов у компилятора не хватает. И он будет выдавать ошибку о том, что с типом такого делать нельзя.

    поэтому приходится ставить дополнительную точку с запятой как признак конца блока определения
    X++:
    {
    MySuperName4Class MySuperName4Class;
    ;
    MySuperName4Class.mySuperMethod();
    }
    опытные программисты X++ ставят дополнительную точку с запятой всегда (на всякий случай).
    Запись от mazzy размещена 21.10.2010 в 15:18 mazzy is offline
  3. Старый комментарий
    Аватар для Lemming
    Цитата:
    Сообщение от mazzy Просмотреть комментарий
    отличный. FAQ'овый вопрос.

    X++ разрешает использовать одинаковые имена для типов и для переменных. (Скорее всего, здесь нет какой-то задумки, а просто "так получилось")
    Java и C# тоже вроде разрешают. Скажем честно, те кто создавали лексический анализатор Х++ просто немного "не смогли"
    Запись от Lemming размещена 06.12.2012 в 08:13 Lemming is offline
 


Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 10:28.