Personalizar la Virtualización

<< Clic para mostrar Tabla de Contenidos >>

Personalizar la Virtualización

 

Personalizar la Virtualización

  •     Resumen
  •     ¿Qué se debe hacer?
  •         Sobrescribir de Clases y Métodos
  •     Ejemplo
  •         Crear una librería de replicación
  •         Configurar el proveedor en Bizagi
  •     Verificar Virtualización (Punto de chequeo)
  • Resumen

    Bizagi presenta el Asistente el cual le ayudará en la configuración de la conexión de una base datos externa SQL Server u Oracle (para integración a nivel de datos).

     

    Para otra fuente de datos diferente a SQL Server y Oracle, se puede sobrescribir los métodos y clases utilizado por Bizagi en la virtualización.

     

    ¿Qué se debe hacer?

    Para poder utilizar la Virtualización de Bizagi con una fuente de datos externa diferente a SQL Server u Oracle se debe seguir los siguientes pasos:

     

    1. Crear una librería de Virtualización

    A través de una librería personalizada, usted podrá sobrescribir las clases y métodos de la virtualización de Bizagi (como se describe en la siguiente sección: Sobrescribir de métodos y clases).

     

    2. Configurar el proveedor de datos de Bizagi para utilizarlo en la librería personalizada de Virtualización.

    Esta configuración utiliza la configuración avanzada de Bizagi para virtualizaciones.

     

    Sobrescribir de Clases y Métodos

    Para personalizar la virtualización de Bizagi, es necesario desarrollar un componente que implemente las interfaces:

    IProviderVirtualDA2

    IEntityVirtualDA

    IParameter

    IDatabaseConstants

     

    Bizagi separa la operación de conectar, desconectar y administración transaccional de la operación de la búsqueda de datos desde el proveedor de datos externos y de las interfaces de la entidad. Es decir, cuando se crea una librería de virtualización personalizada, Bizagi sigue las mejores prácticas para la gestión y diseño de la implementación.

     

    Interfaz del proveedor: IProviderVirtualDA2

    La clase que invoca la interfaz debe contener los siguientes métodos:

     

    void Init (Dictionary<string, string> metadata): A cargo de tomar la información suministrada, como el nombre del servidor, el nombre de la base de datos, usuario, contraseña, etc. La clase recibe el objeto Dictionary<string, string>, el cual contiene los datos configurados como metadata del sistema.

    void OpenConnection(): Este método es utilizado para realizar la conexión con el sistema externo. En el caso de una base de datos, el método construye los enlaces de la conexión y abre la conexión con el repositorio.

    void CloseConnection(): A cargo de cerrar la conexión con el sistema de datos externos.

    void BeginTransaction(): A cargo de iniciar una nueva transacción para la operación actual del sistema.

    void Commit(): Realizar commit de la transacción actual en el sistema de referencia.

    void Rollback(): Realizar un rollback (regresar al estado inicial) de la transacción actual del sistema de referencia.

    DataSet RunQuery(string sQuery, string sTableName): Este método se utiliza desde las formas para ejecutar la consultar en la fuente.

    void ClearParameters(): A cargo de limpiar el arreglo que contenga parámetros de una anterior invocación.

    void AddParameter(Vision.DA.IParameter oParameter): A cargo de cargar un parámetro para la invocación.

    Vision.DA.IParameter CreateParameterObject (string sParameterName, Vision.Defs.EDataType eDataType, int iSize, object oValue): A cargo de crear el objeto que contiene los parámetros.

     

    Interfaz del proveedor: ICustomQueryDA

    La clase que invoca la interfaz debe contener los siguientes métodos:

     

    void AddParameter (string parameterName, BizagiDataType dataType, int size, byte precision, byte scale, object value, ParameterDirection parameterDirection): A cargo de adicionar parámetros al query que será ejecutado.

    void ClearParameters(): Elimina los parámetros presentes en el query.

    DataSet RunQuery(string query, string tableName): se usa para consultar los valores de la funte de datos externa. La lógica es equivalente ahacer unquery sobre los campos del objeto.

     

    Interfaz de la entidad: ICustomVirtualizationDA

    La clase que implementa esta interfaz debe contener la lógica necesaria para manipular la información virtualizada, como insertar un registro nuevo, consultar dentro de un grupo de registros, modificar y eliminar un registro.

    Los métodos que esta clase debe tener se listan a continuación:

     

    void Init(ICustomProviderDA provider): Inicia la conexión con el sistema.

     

    Parámetros

    Descripción

    provider

    Permite convertir el objeto que invoca la interfaz

    ICustomProviderDA.

     

    DataSet GetEntity(string entitySource, KeyColumn[] keyColumns, string[] columnList): Utilizado como consulta de los valores de la fuente de datos externa. Esto es equivalente a realizar una consulta en los campos del objeto sin tener que aplicar filtros.

     

    Parámetros

    Descripción

    entitySource

    Nombre de la tabla a replicar en la fuente de datos

    keyColumns

    Arreglo que contiene el nombre de las columnas de la consulta en la fuente de datos.

    columnList

    Arreglo que contiene el nombre de las columnas a consultar

    RETURNED DataSet

    Un DataSet con los valores de la entidad.

     

    DataSet GetEntityInstance(string entitySource, KeyColumn[] keyColumns, string[] columnList): Toma datos de una instancia de la entidad (valores) de la tabla correspondiente a un ID especificado.

     

    Parámetros

    Descripción

    entitySource

    Tabla donde la entidad es implementada.

    keyColumns

    Arreglo que contiene los nombres de la columna a ser utilizada para filtrar los registros.

    columnList

    Arreglo que contiene el nombre de las columnas a ser consultadas.

    RETURNED DataSet

    Un conjunto de datos con valores para la entidad.

     

    DataSet GetEntityInstancesTable(string entitySource, string[] keyColumns, string[] outputColumnList, string filterText, bool fillSchema, int topReturnRows)

     

    Parámetros

    Descripción

    entitySource

    Tabla donde se localiza la entidad.

    keyColumns

    Arreglo de columnas utilizadas como llaves.

    outputColumnList

    Columnas a ser incluida en la lista.

    filterText

    Filtros para ser aplicados en búsqueda de entidades con la clausula o condición WHERE (donde)

    fillSchema

    Verdadero si la información del esquema debe ser retornada de la base, falso de lo contrario.

    topReturnRows

    Número de registros a ser regresados.

    RETURNED DataSet

    Un conjunto de datos con valores para la entidad

     

    Object GetAttributeValue(string entitySource, KeyColumn[] keyColumns, string attributeSource)

     

    Parámetros

    Descripción

    entitySource

    Tabla donde se implementa la entidad.

    keyColumns

    Arreglo de columnas utilizadas como llaves.

    attributeSource

    Columna de variables a regresar.

    RETURNED Object

    Los valores de los atributos.

     

    bool ExistsEntityInstance(string entitySource, KeyColumn[] keyColumns)

     

    Parámetros

    Descripción

    entitySource

    Tabla donde se implementa la entidad.

    keyColumns

    Arreglo de columnas utilizadas como llaves.

    RETURNED bool

    Verdadero si la instancia fue encontrada, falso de lo contrario.  

     

    int ExistsEntityInstance(string entitySource, EntityColumn columnToFind, KeyColumn[] keyColumns)

     

    Parámetros

    Descripción

    entitySource

    Tabla donde se implementa la entidad.

    columnToFind

    Columna utilizada para encontrar la instancia.

    keyColumns

    Arreglo de columnas utilizadas como llave.

    RETURNED int

    Debe retornar, “1” si la instancia fue encontrada “0” si no.

     

    EntityOutputColumn[] AddEntity(string entitySource, EntityColumn[] addColumns, KeyColumn[] keyColumns, EntityAutoColumn[] autoColumns): Adiciona una nueva instancia (valores).

     

    Parámetros

    Descripción

    entitySource

    Tabla donde se implementa la entidad

    addColumns

    Lista de columnas para incluir valores.

    keyColumns

    Arreglo de columnas utilizadas como llave.

    autoColumns

    Arreglo de columnas auto-numeric

    RETURNED EntityOutputColumn[]

    Debe regresar a HashTable que contiene el nombre de la columna emparejada con el valor incluido.

     

    EntityOutputColumn[] UpdateEntity(string entSource, EntityColumn[] updateColumns, KeyColumn[] keyColumns, EntityAutoColumn[] autoColumns): Actualiza la información de una instancia de la entidad (valores) en la base de datos y registra la actualización.

     

    Parámetros

    Descripción

    entSource

    Tabla donde se implementa la entidad

    updateColumns

    Hastable que contiene las columnas a ser actualizadas, con los valores de sus parejas.

    keyColumns

    Arreglo de columnas utilizadas como llave.

    autoColumns

    Arreglo de columnas auto-numeric

    RETURNED EntityOutputColumn[]

    Debe regresar a HashTable que contiene el nombre de la columna y el valor que fue incluido.

     

    bool DeleteEntity(string entSource, KeyColumn[] keyColumns): Elimina un registro de la base de datos.

     

    Parámetros

    Descripción

    entSource

    Tabla donde se implementa la entidad

    keyColumns

    Arreglo de columnas utilizadas como llave.

    RETURNED bool

    Debe regresar verdadero si el registro fue borrado, y Falso de lo contrario.  

     

    Interfaces de constantes: IDatabaseProperties

    Tenga en cuenta que Bizagi construirá la consulta y su sintaxis.

    De acuerdo a esta idea, asegúrese de definir todas las constantes apropiadas para las consultas en el motor de la Base de datos específico en estas interfaces.

     

    Ejemplo

    En el ejemplo, vamos a configurar una virtualización personalizada para un motor de base de datos MySQL.

     

    Vamos a presentar un ejemplo de las clases de virtualización que implementan las interfaces "ICustomProviderDA", "ICustomQueryDA" y "IEntityVirtualDA".

     

    note_pin

    Tenga en cuenta que el siguiente código ilustra la implementación del método "GetEntity()" (para servir como una guía), sin embargo otros métodos no son incluidos y podría necesitar otro un mayor desarrollo.

     

    Crear una librería de replicación

    En este ejemplo específico, para poder implementar las clases de replicación que conecten la base de datos MySQL, primero se debe descargar e instalar el componente MySQL Connector/NET para realizar la conexión.

     

    Para el ejemplo, las siguientes clases fueron desarrolladas utilizando Microsoft Visual Studio. A través de este proyecto .NET se hace referencia a la librería MySql.Data.dll, la cual debió ser instalado por el componente MySQL Connector/Net ya que es necesario.

     

    También es necesario hacer referencia a la librería BizAgi.EntityManager.Interfaces.CustomSource.dll de Bizagi.

     

    Estas se encuentran en la carpeta “bin” dentro de la carpeta de la aplicación del proyecto (por defecto en  "C:\Bizagi\Enterprise\Projects\[PROJECT_NAME]\WebApplication\bin\").  

     

    CustomRefs

     

    Class Interface ICustomProviderDA y ICustomQueryDA

    using System;

    using System.Data;

    using BizAgi.EntityManager.Interfaces.CustomSource;

    using MySql.Data.MySqlClient;

    using System.Collections.Generic;

    using System.Collections;

    using System.Text;

     

    namespace BizagiMySQL

    {

     

       public class CMySQLProvider : ICustomProviderDA, ICustomQueryDA

       {

     

           private Dictionary<string, string> _metadata;

           private MySqlConnection _mySqlconn;

           private bool _disposed;

           //--- The array        used to        store the parameters to        a stored procedure

           private readonly List<CMySqlParameter> _params;

     

           public CMySQLProvider()

           {

               _disposed = false;

               _mySqlconn = null;

               _params = new List<CMySqlParameter>();

           }

           

           #region IProviderVirtualDA2 Members

     

           public void AddParameter(string parameterName, BizagiDataType dataType, int size, byte precision, byte scale, object value, ParameterDirection parameterDirection)

           {

               _params.Add(new CMySqlParameter(parameterName, dataType, size, precision, scale, value, parameterDirection));

           }

     

           public void ClearParameters()

           {

               _params.Clear();

           }

     

           public DataSet RunQuery(string query, string tableName)

           {

               MySqlCommand command = new MySqlCommand();

               MySqlDataAdapter adapter = new MySqlDataAdapter();

               DataSet ds = new DataSet();

               command.Connection = this.GetConnection();

               command.CommandText = ReplaceQueryParameters(query, _params);

               command.CommandType = CommandType.Text;

     

               GetParameters(command);

               adapter.SelectCommand = command;

               adapter.Fill(ds, tableName);

               

               return ds;

           }

     

           public IDatabaseProperties Properties

           {

               get { return CMySqlDatabaseConstants.Instance; }

           }

     

           private void GetParameters(MySqlCommand oCmd)

           {

               //--- Get an enumerator        for        the        parameter array        list

               IEnumerator oEnumerator = _params.GetEnumerator();

     

               //--- Loop through the Parameters in the ArrayList

               while (oEnumerator.MoveNext())

               {

     

                   //--- Add the SQLParameter object to the SQLCommand        object

                   oCmd.Parameters.Add(ConvertParameterToMySqlParameter((CMySqlParameter)oEnumerator.Current));

               }

           }

     

           private MySqlParameter ConvertParameterToMySqlParameter(CMySqlParameter oP)

           {

               MySqlDbType dbType = oP.DataType;

     

               //--- Instantiate a        SqlParameter object

               MySqlParameter mySqlParameter = new MySqlParameter(oP.ParameterName, dbType, oP.Size);

     

               mySqlParameter.Value = oP.Value;

               mySqlParameter.Direction = (ParameterDirection)oP.Direction;

               mySqlParameter.Precision = oP.Precision;

               mySqlParameter.Scale = oP.Scale;

               mySqlParameter.SourceColumn = oP.SourceColumn;

               mySqlParameter.SourceVersion = oP.UseCurrentSourceColumnValue ? DataRowVersion.Current : DataRowVersion.Original;

     

               return mySqlParameter;

           }

     

           /// <summary>

           /// Replace parameter in the form '?', by parametes in the form ':ParamName'

           /// </summary>

           /// <param name="sQuery"></param>

           /// <returns></returns>

           private static string ReplaceQueryParameters(string sQuery, List<CMySqlParameter> alParams)

           {

               if (alParams != null && alParams.Count > 0)

               {

                   char cInter = '?', cQuote = '\'', cAt = '@', cColon = ':';

                   string sParamToken = ":";

                   bool bInQuote = false; // indicates if current character is in ''

                   StringBuilder sbResp = new StringBuilder();

                   int _i = 0, _n = sQuery.Length, nNumParam = 0, nLastStrIndex = 0;

                   while (_i < _n)

                   {

                       if (bInQuote)

                       {

                           if (sQuery[_i] == cQuote)

                           {

                               if ((_i + 1) < _n && sQuery[_i + 1] == cQuote)

                               {

                                   // "...''..." case, already in quote

                                   _i += 2;

                               }

                               else

                               {

                                   // "...'" case

                                   bInQuote = false;

                                   _i++;

                               }

                           }

                           else

                           {

                               _i++;

                           }

                       }

                       else

                       {

                           if (sQuery[_i] == cInter)

                           {

                               // "...?..." case

                               if (nNumParam >= alParams.Count)

                               {

                                   // parameter doesn't exists

                                   throw new Exception(string.Format("Parameter {0} doesn't exists in command: '{1}'", nNumParam, sQuery));

                               }

                               else

                               {

                                   // get valid param name

                                   string sValidParamName = GetValidParamName(((CMySqlParameter)alParams[nNumParam]).ParameterName, alParams, nNumParam - 1);

                                   (alParams[nNumParam]).ParameterName = sValidParamName;

     

                                   // replace parameter by name

                                   sbResp.Append(sQuery.Substring(nLastStrIndex, _i - nLastStrIndex));

                                   sbResp.Append(sParamToken + sValidParamName);

     

                                   nLastStrIndex = _i + 1;

                                   nNumParam++;

                               }

                           }

                           else if (sQuery[_i] == cAt)

                           {

                               // replace parameter by name

                               sbResp.Append(sQuery.Substring(nLastStrIndex, _i - nLastStrIndex));

                               sbResp.Append(cInter);

     

                               nLastStrIndex = _i + 1;

                               nNumParam++;

                           }

                           else if (sQuery[_i] == cQuote)

                           {

                               // "'..." case

                               bInQuote = true;

                           }

                           _i++;

                       }

                   }

                   sbResp.Append(sQuery.Substring(nLastStrIndex, _n - nLastStrIndex));

                   return sbResp.ToString();

               }

               return sQuery;

           }

     

           /// <summary>

           /// Gets a valid parameter name, unique for first iMaxParamIndex parameters

           /// </summary>

           /// <param name="sParamName"></param>

           /// <param name="alParams"></param>

           /// <param name="iMaxParamIndex"></param>

           /// <returns></returns>

           private static string GetValidParamName(string sParamName, List<CMySqlParameter> alParams, int iMaxParamIndex)

           {

               int iMaxDbIdLength = CMySqlDatabaseConstants.Instance.MaxDbIdLength;

               string sResp = (iMaxDbIdLength < sParamName.Length) ? sParamName.Substring(0, iMaxDbIdLength) : sParamName;

               int iSuffix = 1;

               while (IndexOfParam(sResp, alParams, iMaxParamIndex) != -1)

               {

                   // find an unique name

                   string sSuffix = iSuffix.ToString();

                   sResp = (iMaxDbIdLength - sSuffix.Length < sParamName.Length) ? sParamName.Substring(0, iMaxDbIdLength - sSuffix.Length) : sParamName;

                   sResp += sSuffix;

                   iSuffix++;

               }

               return sResp;

           }

     

           private static int IndexOfParam(string sParamName, List<CMySqlParameter> alParams, int iMaxParamIndex)

           {

               int i = 0, n = iMaxParamIndex;

               while (i < n)

               {

                   if ((alParams[i]).ParameterName == sParamName)

                   {

                       n = i;

                   }

                   else

                   {

                       i++;

                   }

               }

               return (n == iMaxParamIndex) ? -1 : n;

           }

     

           #endregion

     

           #region IProviderVirtualDA Members

     

           public void Init(Dictionary<string, string> metadata)

           {

               this._metadata = metadata;

           }

     

           public void BeginTransaction()

           {

           }

     

           public void Commit()

           {

           }

     

           public void Rollback()

           {

           }

     

           public void OpenConnection()

           {

               if (_mySqlconn == null)

               {

                   //Verify all parameters are filled

                   if (!_metadata.ContainsKey("Server") || !_metadata.ContainsKey("Database") ||

                   !_metadata.ContainsKey("Username") || !_metadata.ContainsKey("Password"))

                   {

                       throw new CustomVirtualizationException("Incomplete metadata: connection parameters missing");

                   }

                   else

                   {

                       //Build the connection string with the parameters received from Bizagi Server

                       string sServer = _metadata["Server"];

                       string sDatabase = _metadata["Database"];

                       string sUsername = _metadata["Username"];

                       string sPassword = _metadata["Password"];

                       string sConn = "Server=" + sServer + ";Database=" + sDatabase + ";Uid=" + sUsername + ";Pwd=" + sPassword + ";";

     

                       _mySqlconn = new MySqlConnection(sConn);

                       _mySqlconn.Open();

                   }

               }

           }

     

           public void CloseConnection()

           {

               if (_mySqlconn != null)

                   _mySqlconn.Close();

               _mySqlconn = null;

           }

     

           #endregion

     

           #region IDisposable Members

     

           void  IDisposable.Dispose()

           {

               if (!_disposed)

               {

                   _disposed = true;

               }

           }

     

           #endregion

     

           #region internal methods

     

           internal MySqlConnection GetConnection()

           {

               return this._mySqlconn;

           }

     

           internal DataSet ExecuteMySQLQuery(string sSQL)

           {

               DataSet ds = new DataSet();

     

               MySqlCommand command = new MySqlCommand(sSQL, this.GetConnection());

               MySqlDataAdapter adapter = new MySqlDataAdapter(command);

               adapter.Fill(ds);

     

               return ds;

           }

     

           internal DataSet ExecuteMySQLQuery(MySqlCommand command)

           {

               DataSet ds = new DataSet();

     

               MySqlDataAdapter adapter = new MySqlDataAdapter(command);

               adapter.Fill(ds);

     

               return ds;

           }

     

           internal void ExecuteNonQueryMySQL(string sSQL)

           {

               MySqlCommand command = new MySqlCommand(sSQL, this.GetConnection());

               command.ExecuteNonQuery();

           }

     

           /// <summary>

           /// Initializes command with current connection and transaction

           /// </summary>

           internal MySqlCommand GetCommand()

           {

     

               MySqlCommand m_oledbCmd = new MySqlCommand();

               m_oledbCmd.Connection = GetConnection();

               m_oledbCmd.CommandType = CommandType.Text;

               m_oledbCmd.Parameters.Clear();

     

               return m_oledbCmd;

           }

     

           #endregion

       }

     

    }

     

     

     

    Clase de la interfaz ICustomVirtualizationDA

    using System;

    using System.Collections.Generic;

    using System.Data;

    using System.Collections;

    using System.Collections.Specialized;

    using System.Text;

    using BizAgi.EntityManager.Interfaces.CustomSource;

    using MySql.Data.MySqlClient;

     

    namespace BizagiMySQL

    {

     

       public class CMySQLEntity : ICustomVirtualizationDA

       {

           /// <summary>

           /// Flag to show if object has been disposed                

           /// </summary>

           protected bool m_bDisposed;

     

           /// <summary>

           /// Metadata used to initialize object, as collection of name-value pairs

           /// </summary>

           protected HybridDictionary m_htMetadata;

     

     

           /// <summary>

           /// Connection with the virtual System

           /// </summary>

           protected CMySQLProvider m_objSystem;

     

     

           public CMySQLEntity()

           {

               m_bDisposed = false;

           }

     

           #region ICustomVirtualizationDA Members

     

           public void Init(ICustomProviderDA objProvider)

           {

               m_objSystem = (CMySQLProvider)objProvider;

           }

     

           public EntityOutputColumn[] AddEntity(string entitySource, EntityColumn[] addColumns, KeyColumn[] keyColumns, EntityAutoColumn[] autoColumns)

           {

               List<EntityOutputColumn> htResult = new List<EntityOutputColumn>();

     

               try

               {

                   StringBuilder sbIntoList = new StringBuilder(addColumns.Length * 10);

                   StringBuilder sbValuesList = new StringBuilder(addColumns.Length * 10);

     

                   // Columns to add

                   MySqlCommand command = this.m_objSystem.GetCommand();

     

                   int pos = 0;

                   foreach (EntityColumn oEntry in addColumns)

                   {

                       if (pos++ > 0)

                       {

                           sbIntoList.Append(",");

                           sbValuesList.Append(",");

                       }

     

                       // Builds INTO clause and VALUES clauses separately

                       sbIntoList.Append(oEntry.Name);

     

                       // Adds values as parameters

                       sbValuesList.Append("@param"+pos);

                       command.Parameters.AddWithValue("@param"+pos, oEntry.Value);

                   }

     

                   if (sbIntoList.Length == 0 || sbValuesList.Length == 0)

                   {

                       throw new CustomVirtualizationException("Nothing to insert.");

                   }

     

                   StringBuilder sbSQL = new StringBuilder();

     

                   // Inserts values in entity table

                   sbSQL.Append("INSERT INTO ");

                   sbSQL.Append(entitySource);

                   sbSQL.Append(" ( ");

                   sbSQL.Append(sbIntoList);

                   sbSQL.Append(" ) VALUES ( ");

                   sbSQL.Append(sbValuesList);

                   sbSQL.Append(" ) ");

     

                   command.CommandText = sbSQL.ToString();

                   command.ExecuteNonQuery();

     

                   //Check if some of the Column is autoFilled... (it should be part of the key, but this is not really neccesary)

                   //It can only be ONE autoFilledColumn

                   if (autoColumns.Length > 0)

                   {

                       command = m_objSystem.GetCommand();

                       command.CommandText = "SELECT last_insert_id()";

                       object ret = command.ExecuteScalar();

     

                       htResult.Add(new EntityOutputColumn { Name = autoColumns[0].Name, DataType = autoColumns[0].DataType, Value = ret });

                   }

     

                   return htResult.ToArray();

               }

               catch (Exception e)

               {

                   throw new ApplicationException(e.Message);

               }

           }

     

           public EntityOutputColumn[] UpdateEntity(string entSource, EntityColumn[] updateColumns, KeyColumn[] keyColumns, EntityAutoColumn[] autoColumns)

           {

               MySqlCommand command = null;

               List<EntityOutputColumn> htResult = new List<EntityOutputColumn>();

     

               try

               {

                   StringBuilder sbColsList = new StringBuilder(updateColumns.Length * 10);

     

                   command = m_objSystem.GetCommand();

     

                   // Loop thru attributes to update, to build SET clause

                   int pos = 0;

                   foreach (EntityColumn oEntry in updateColumns)

                   {

                       if (pos++ > 0)

                       {

                           sbColsList.Append(",");

                       }

     

                       sbColsList.Append(oEntry.Name);

     

                       // Adds values as parameters

                       sbColsList.Append("=@param" + pos);

                       command.Parameters.AddWithValue("@param" + pos, oEntry.Value);

                   }

     

                   // Builds SQL update query

                   if (updateColumns.Length > 0 && sbColsList.Length > 0)

                   {

                       StringBuilder sbSQL = new StringBuilder();

     

                       sbSQL.Append(" UPDATE ");

                       sbSQL.Append(entSource);

                       sbSQL.Append(" SET ");

                       sbSQL.Append(sbColsList);

     

                       sbSQL.Append(" WHERE ");

                       sbSQL.Append(BuildWhereClause(command, keyColumns));

     

                       // Performs update!

                       command.CommandText = sbSQL.ToString();

                       command.ExecuteNonQuery();

                       command.Parameters.Clear();

                   }

     

                   return htResult.ToArray();

               }

               finally

               {

                   // Dispose the SqlCommand

                   if (command != null)

                   {

                       command.Dispose();

                   }

               }

           }

     

           public bool DeleteEntity(string entSource, KeyColumn[] keyColumns)

           {

               MySqlCommand command = null;

     

               try

               {

                   command = m_objSystem.GetCommand();

     

                   StringBuilder sbSQL = new StringBuilder();

     

                   // Delete from entity table

                   sbSQL.Append("DELETE FROM ");

                   sbSQL.Append(entSource);

     

                   sbSQL.Append(" WHERE ");

                   sbSQL.Append(BuildWhereClause(command, keyColumns));

     

                   // Performs delete!

                   command.CommandText = sbSQL.ToString();

                   return command.ExecuteNonQuery() > 0;

               }

               finally

               {

                   // Dispose the SqlCommand

                   if (command != null)

                   {

                       command.Dispose();

                   }

               }

           }

     

           public DataSet GetEntityInstance(string entitySource, KeyColumn[] keyColumns, string[] columnList)

           {

               try

               {

                   MySqlCommand command = m_objSystem.GetCommand();

     

                   StringBuilder sbSQL = new StringBuilder();

     

                   sbSQL.Append(" SELECT ");

                   sbSQL.Append(string.Join(",", columnList));

                   sbSQL.Append(" FROM ");

                   sbSQL.Append(entitySource);

                   sbSQL.Append(" WHERE ");

                   sbSQL.Append(BuildWhereClause(command, keyColumns));

     

                   command.CommandText = sbSQL.ToString();

                   DataSet ds = m_objSystem.ExecuteMySQLQuery(command);

     

                   return ds;

               }

               catch (Exception e)

               {

                   throw new ApplicationException(e.Message);

               }

           }

     

     

           public object GetAttributeValue(string entitySource, KeyColumn[] keyColumns, string attributeSource)

           {

               try

               {

                   MySqlCommand command = m_objSystem.GetCommand();

     

                   StringBuilder sbSQL = new StringBuilder();

     

                   // Column to be retrieved

                   sbSQL.Append("SELECT ");

                   sbSQL.Append(attributeSource);

     

                   // FROM clause

                   sbSQL.Append(" FROM ");

                   sbSQL.Append(entitySource);

     

                   // Uses surrogate key value to find instance

                   sbSQL.Append(" WHERE ");

                   sbSQL.Append(BuildWhereClause(command, keyColumns));

     

                   command.CommandText = sbSQL.ToString();

                   DataSet ds = m_objSystem.ExecuteMySQLQuery(command);

                   DataTable dtAttribValues = ds.Tables[0];

     

                   return dtAttribValues;

               }

               catch (Exception e)

               {

                   throw new ApplicationException(e.Message);

               }

           }

     

           public DataSet GetEntityInstancesTable(string sEntSource, string[] arrsKeyColumns, string[] arrsColList, string sFilterText, bool bFillSchema, int iTopReturnRows)

           {

               try

               {

                   StringBuilder sbSQL = new StringBuilder();

                   sbSQL.Append(" SELECT ");

                   sbSQL.Append(string.Join(",", arrsColList));

                   // FROM clause

                   sbSQL.Append(" FROM ");

                   sbSQL.Append(sEntSource);

                   // WHERE clause

                   if (sFilterText.Length > 0)

                   {

                       // Filter text must be formatted in OleDb syntax

                       sbSQL.Append(" WHERE ");

                       sbSQL.Append(sFilterText);

                   }

                   sbSQL.Append(" ORDER BY ");

                   sbSQL.Append(string.Join(",", arrsKeyColumns));

     

                   DataSet ds = m_objSystem.ExecuteMySQLQuery(sbSQL.ToString());

                   ds.Tables[0].TableName = "ENTITYINSTANCES";

                   // Data table with values

                   //DataTable dtAttribValues = ds.Tables[0];

                   

                   /*XmlDataDocument xmlDoc = new XmlDataDocument(ds);

                   string sAux = xmlDoc.InnerXml;

                   sAux = sAux.Replace("Table", "ENTITYINSTANCES");

                   return sAux;*/

                   return ds;

               }

               catch (Exception e)

               {

                   throw new ApplicationException(e.Message);

               }

           }

     

           public bool ExistsEntityInstance(string entitySource, KeyColumn[] keyColumns)

           {

               try

               {

                   MySqlCommand command = m_objSystem.GetCommand();

     

                   StringBuilder sbSQL = new StringBuilder();

     

                   sbSQL.Append(" SELECT ");

                   sbSQL.Append(" count(1) ");

                   sbSQL.Append(" FROM ");

                   sbSQL.Append(entitySource);

                   sbSQL.Append(" WHERE ");

                   sbSQL.Append(BuildWhereClause(command, keyColumns));

     

                   command.CommandText = sbSQL.ToString();

                   object ret = command.ExecuteScalar();

     

                   int result;

                   if (int.TryParse(ret.ToString(), out result))

                       return result > 0;

                   else

                       return false;

               }

               catch (Exception e)

               {

                   throw new ApplicationException(e.Message);

               }

           }

     

           public int ExistsEntityInstance(string entitySource, EntityColumn columnToFind, KeyColumn[] keyColumns)

           {

               try

               {

                   MySqlCommand command = m_objSystem.GetCommand();

     

                   StringBuilder sbSQL = new StringBuilder();

     

                   sbSQL.Append(" SELECT ");

                   sbSQL.Append(BuildKeySelectClause(keyColumns));

                   sbSQL.Append(" FROM ");

                   sbSQL.Append(entitySource);

                   sbSQL.Append(" WHERE ");

                   sbSQL.Append(columnToFind);

                   sbSQL.Append(" = ");

                   sbSQL.Append("@keyParam");

     

                   command.Parameters.AddWithValue("@keyParam", columnToFind.Value);

     

                   command.CommandText = sbSQL.ToString();

                   object ret = command.ExecuteScalar();

     

                   int result;

                   if (int.TryParse(ret.ToString(), out result))

                       return result;

                   else

                       return 0;

     

               }

               catch (Exception e)

               {

                   throw new ApplicationException(e.Message);

               }

           }

     

           #endregion

     

           #region IDisposable Members

     

           public void Dispose()

           {

               if (!m_bDisposed)

               {

                   m_bDisposed = true;

               }

           }

     

           #endregion

     

           public string BuildWhereClause(MySqlCommand command, KeyColumn[] keyColumns)

           {

               StringBuilder sbSQL = new StringBuilder();

     

               for (int iKeyIndex = 0; iKeyIndex < keyColumns.Length; iKeyIndex++)

               {

                   if (iKeyIndex > 0)

                       sbSQL.Append(" AND ");

     

                   // Associate columns with values....

                   sbSQL.Append(keyColumns[iKeyIndex].Name);

                   sbSQL.Append(" = ");

                   sbSQL.Append("@keyParam"+iKeyIndex);

     

                   command.Parameters.AddWithValue("@keyParam"+iKeyIndex, keyColumns[iKeyIndex].Value);

               }

     

               return sbSQL.ToString();

           }

     

           public string BuildKeySelectClause(KeyColumn[] keyColumns)

           {

               StringBuilder builder = new StringBuilder();

     

               for (int i = 0; i < keyColumns.Length; i++)

               {

                   if (i > 0) builder.Append(", ");

     

                   var keyColumn = keyColumns[i];

                   builder.Append(keyColumn.Name);

               }

     

               return builder.ToString();

           }

       }

    }

     

     

    Clase de Parámetros

    using BizAgi.EntityManager.Interfaces;

    using BizAgi.EntityManager.Interfaces.CustomSource;

    using MySql.Data.MySqlClient;

     

    namespace BizagiMySQL {

     

     using System.Data;

     

     public class CMySqlParameter

     {

             private BizagiDataType                dataType;                                                //--- Provider-independent data type                        

           private MySqlDbType         dbDataType;                                                //--- Provider-specific datatype of the parameter

         private string                                paramName;                                                //--- The Internal name of the parameter

         private string                                originalParamName;                                //--- The Original o External name of the parameter

     

             //-------------------------------------------------------------------------------------------------------

             //--- Class Constructors

             //--- Overloaded:        Yes

             //-------------------------------------------------------------------------------------------------------

             public CMySqlParameter(string sParameterName, BizagiDataType BizagiDataType, int iSize, object oValue) {

                     ParameterName = sParameterName;

                     dataType = BizagiDataType;

                     dbDataType = getSqlDataType(BizagiDataType);

                     Size = iSize;

                     Value = oValue;

                     Direction = ParameterDirection.Input;

             }

     

             public CMySqlParameter (string sParameterName, BizagiDataType BizagiDataType, int iSize, object oValue, ParameterDirection eDirection) {

                     ParameterName = sParameterName;

                     dataType = BizagiDataType;

                     dbDataType = getSqlDataType(BizagiDataType);

                     Size = iSize;

                     Value = oValue;

                     Direction = eDirection;

             }

     

             public CMySqlParameter (string sParameterName, BizagiDataType BizagiDataType, int iSize, byte iPrecision, byte iScale, object oValue, ParameterDirection eDirection)

             {

                     ParameterName = sParameterName;

                     dataType = BizagiDataType;

                     dbDataType = getSqlDataType(BizagiDataType);

                     Size = iSize;

                     Precision = iPrecision;

                     Scale = iScale;

                     Value = oValue;

                     Direction = eDirection;

             }

     

             public CMySqlParameter (string sParameterName, BizagiDataType BizagiDataType, int iSize, byte iPrecision, byte iScale, object oValue, ParameterDirection eDirection, string sSourceColumn, bool bUseCurrentSourceColumnValue)

             {

                     ParameterName = sParameterName;

                     dataType = BizagiDataType;

                     dbDataType = getSqlDataType(BizagiDataType);

                     Size = iSize;

                     Precision = iPrecision;

                     Scale = iScale;

                     Value = oValue;

                     Direction = eDirection;

                     SourceColumn = sSourceColumn;

                     UseCurrentSourceColumnValue = bUseCurrentSourceColumnValue;

             }

     

           public ParameterDirection Direction { get; private set; }

     

           public object Value { get; private set; }

     

           public string SourceColumn { get; private set; }

     

           public string ParameterName

             {

               get { return paramName; }

                 set

                     {

                             string sResult = value;

                             originalParamName = value;

     

                             paramName = sResult.Replace ("@","?");

                     }

             }

     

             //--

             // Only for this IParameter implementation

             // ReadOnly -- Return the original name of the parameter

             //--

             public string OriginalName

             {

               get { return originalParamName; }

             }

     

             public BizagiDataType Type

             {

               get { return dataType; }

               set

               {

                   dataType = value;

                   dbDataType = getSqlDataType(dataType);

               }

             }

     

         public int Size { get; set; }

     

         public byte Precision { get; set; }

     

         public byte Scale { get; set; }

     

         public bool UseCurrentSourceColumnValue { get; set; }

     

         public MySqlDbType DataType

             {

               get { return dbDataType; }

             }

     

             private static MySqlDbType getSqlDataType(BizagiDataType BizagiDataType) {

               MySqlDbType oDbType = MySqlDbType.Int32;

     

                     switch (BizagiDataType) {

     

                             case BizagiDataType.BigInt:

                       oDbType = MySqlDbType.Int64;

                                     break;

     

                             case BizagiDataType.Int:

                       oDbType = MySqlDbType.Int32;

                                     break;

     

                             case BizagiDataType.SmallInt:

                       oDbType = MySqlDbType.Int16;

                                     break;

     

                             case BizagiDataType.TinyInt:

                       oDbType = MySqlDbType.Byte;

                                     break;

     

                             case BizagiDataType.Boolean:

                       oDbType = MySqlDbType.Bit;

                                     break;

     

                             case BizagiDataType.Decimal:

                       oDbType = MySqlDbType.Decimal;

                                     break;

     

                             case BizagiDataType.Numeric:

                       oDbType = MySqlDbType.Float;

                                     break;

     

                             case BizagiDataType.Money:

                       oDbType = MySqlDbType.Decimal;

                                     break;

     

                             case BizagiDataType.Float:

                       oDbType = MySqlDbType.Float;

                                     break;

     

                             case BizagiDataType.Real:

                       oDbType = MySqlDbType.Float;

                                     break;

     

                             case BizagiDataType.DateTime:

                       oDbType = MySqlDbType.DateTime;

                                     break;

     

                             case BizagiDataType.SmallDateTime:

                       oDbType = MySqlDbType.DateTime;

                                     break;

     

                             case BizagiDataType.Char:

                       oDbType = MySqlDbType.VarChar;

                                     break;

     

                             case BizagiDataType.VarChar:

                       oDbType = MySqlDbType.VarChar;

                                     break;

                     

                             case BizagiDataType.Text:

                       oDbType = MySqlDbType.Text;

                                     break;

                     

                             case BizagiDataType.Binary:

                       oDbType = MySqlDbType.Binary;

                                     break;

     

                             case BizagiDataType.VarBinary:

                       oDbType = MySqlDbType.VarBinary;

                                     break;

     

                             case BizagiDataType.Image:

                       oDbType = MySqlDbType.VarBinary;

                                     break;

     

                             case BizagiDataType.Guid:

                       oDbType = MySqlDbType.Guid;

                                     break;

     

                   case BizagiDataType.NChar:

                       oDbType = MySqlDbType.VarChar;

                       break;

     

                   case BizagiDataType.NVarChar:

                       oDbType = MySqlDbType.VarChar;

                       break;

     

                   case BizagiDataType.NText:

                       oDbType = MySqlDbType.Text;

                       break;

     

                             default:

                                     break;

                     }

     

                     return oDbType;

     

             }

     }

    }

     

     

    Clase de la Interfaz IDatabaseProperties

    using BizAgi.EntityManager.Interfaces.CustomSource;

     

    namespace BizagiMySQL

    {

       /// <summary>

       /// Specific database constants

       /// </summary>

       public class CMySqlDatabaseConstants : IDatabaseProperties

       {

           #region Singleton

     

           private static readonly CMySqlDatabaseConstants MySqlInstance = new CMySqlDatabaseConstants();

     

           public static CMySqlDatabaseConstants Instance

           {

               get { return MySqlInstance; }

           }

     

           protected CMySqlDatabaseConstants() {}

     

           #endregion

     

           #region Fields / Properties

     

           /// <summary>

           /// Open character for enclose a name that is reserverd word or has special characters

           /// </summary>

           private readonly string m_sQuotedNameOpenChar = "'";

           public string QuotedNameOpenChar { get { return m_sQuotedNameOpenChar; } }

     

           /// <summary>

           /// Close character for enclose a name that is reserverd word or has special characters

           /// </summary>

           private readonly string m_sQuotedNameCloseChar = "'";

           public string QuotedNameCloseChar { get { return m_sQuotedNameCloseChar; } }

     

           /// <summary>

           /// Indicates if by default comparisons between strings are case sensitive

           /// </summary>

           private readonly bool m_bCaseSensitive = false;

           public bool CaseSensitive { get { return m_bCaseSensitive; } }

     

           internal int MaxDbIdLength

           {

               get { return 128; }

           }

     

           #endregion

       }

    }

     

    Una vez haya terminado la implementación de las clases, debe construir el componente como una librería (para este ejemplo una librería dll).

     

    Configurar el proveedor en Bizagi

    En este paso, vamos a configurar el Sistema y el proveedor de datos de la virtualización especificando que librería debe ser usada (el componente personalizado creado anteriormente).

     

    note_pin

    Tenga en cuenta que la configuración es hecha a través del método de configuración estándar de virtualización, el cual requiere que las entidades a ser virtualizadas hayan sido creadas en el modelo de datos de Bizagi.

     

    1. Clic en Sistemas, en la vista de Experto de Bizagi.

    Puede dar clic derecho sobre el elemento sistema y seleccionar Nuevo Sistema del menú desplegable o dar clic en Nuevo sistema de la barra del menú.

     

    VR_Both02_NewSystem

     

    2. Ingrese el Nombre, Nombre Visual y Descripción para el nuevo sistema y seleccione el checkbox de Permitir Entidades Virtuales para replicación para este sistema.

    Clic en Ok para guardar cambios.

     

    CustomVirtualization_Image002

     

    3. Clic en el signo (+) al lado del sistema recién creado.

    Clic derecho en el elemento Nuevo Proveedor.

     

    CustomVirtualization_Image003

     

    4. En la ventana del Nuevo Proveedor ingrese Nombre, Nombre Visual y Descripción en la pestaña de Cconfiguración Básica.

    Marque la opción Permitir Entidades Virtuales para este proveedor. También marque la opción Permitir Replicación para este proveedor (si aplica).

     

    CustomVirtualization_Image004

     

    5. Seleccione la pestaña de Detalles de Conexión y dé clic en Nueva librería.

     

    CustomVirtualization_Image005

     

    6. Ingrese Nombre, Nombre Visual y Descripción.

    Luego haga clic en Seleccionar Librería para seleccionar el .dll de la librería de virtualización personalizada creada previamente.

    Dé clic en Ok en la ventana de Nueva Librería.

     

    CustomVirtualization_Image006

     

    7. Dé clic en el botón Nueva Clase y dentro de la ventana Nueva Clase para Librería, ingrese el nombre de la clase que implementa la interfaz IProviderVirtualDA.

    Dé clic en Ok .

     

    CustomVirtualization_Image007

     

    8. Ahora, en la pestaña Conexión Desarrollo, incluya las propiedades de la conexión haciendo clic en el botón Metadata para crear una nueva fila Propiedad-Valor.

    Dé clic en Ok.

     

    CustomVirtualization_Image008

     

    9.Expanda el elemento nuevo proveedor, seleccione el elemento Entidades Virtuales y cree una Nueva Clase de Virtualización.

     

    CustomVirtualization_Image009

     

    10. Seleccione la librería de la lista desplegable en la ventana Nueva Clase para Librería (si la clase de la Entidad esta en la misma librería que la Clase del Proveedor) o incluya una nueva dando clic en Nueva Librería..

     

    CustomVirtualization_Image010

     

    Dé clic en Nueva Clase y complete los campos necesarios en la nueva ventana.

    Haga clic en Ok para completar la Configuración de la Clase de la Entidad.

     

    CustomReplication_Image002

     

    11.Dé clic derecho sobre el nuevo elemento de la clase de la entidad y seleccione la opción Adicionar Entidad a Virtualización.

     

    CustomVirtualization_Image012

     

    12. En la ventana Adicionar Entidad, seleccione una entidad maestra de la lista desplegable. Luego, en el campo de fuente externa, ingrese el nombre de la tabla o vista de la fuente.

    Después seleccione uno (o más de un) atributo de la lista de atributos de la entidad de Bizagi, para que sean la llave de negocio (un atributo que tendrá un único valor, el cual puede ser utilizado para diferenciar un registro de otro).

     

    Dé clic en OK para guardar los cambios.  

     

    CustomVirtualization_Image013

     

    13. Seleccione la entidad virtualizada y para cada atributo seleccione el atributo externo correspondiente. Esto se realiza dando clic derecho sobre el atributo y seleccionando la opción Propiedades.

     

    CustomVirtualization_Image014

     

    En la ventana Editar Atributo, escriba el nombre del atributo externo y haga clic en OK.

     

    CustomVirtualization_Image015

     

    note_pin

    Si su librería de Virtualización personalizada tiene referencias a otras librerías, es necesario copiarlas a una carpeta de Bizagi Studio, (por defecto en "C:\Program Files\Bizagi\Bizagi Standard\Studio"), y en la carpeta bin de la carpeta aplicación web (por defecto en "C:\Bizagi\Standard\Projects\[PROJECT_NAME]\WebApplication\bin").

    Esto último se hace para que la virtualización funciona en tiempo de ejecución.

     

    Ya hemos terminado la configuración de la Virtualización utilizando un componente personalizado para una base de datos MySQL.

     

    Verificar Virtualización (Punto de chequeo)

    Una vez la Virtualización ha sido configurada, usted puede verificar si se ha sincronizado de forma apropiada las entidades maestras con las tablas externas. 

     

    Tenga en cuenta que con la Virtualización, los procesos en Bizagi acceden a información almacenada en diferentes fuentes de datos en tiempo de ejecución. 

     

    Esta funcionalidad es transparente para los usuarios del Portal de Trabajo; por lo que usted necesita verificar que la virtualización funcione de forma adecuada. Esto se realiza verificando en la forma de la actividad donde se utiliza la información de las entidades virtualizadas. 

    Adicionalmente, verifique de forma explicita los valores que se están sincronizando con la fuente. Usted puede ver los valores en la entidad especifica a través del modulo entidades (disponible para el ambiente de desarrollo) como se indica en Verificar la Virtualización.

    En este articulo