Custom Replication

<< Click to Display Table of Contents >>

Navigation:  Bizagi Studio > Process wizard > Data Modeling > Connecting to external data sources > Data Replication > Using advanced Replication configuration >

Custom Replication

Overview

Bizagi provides a Replication Wizard to assist in connecting to an external sources such as SQL Server and Oracle (for data-level integration).

 

For any data source other then SQL Server and Oracle, there is the possibility to override the methods and classes used by Bizagi in its Replication feature.

 

What you need to do

In order to use Bizagi's Replication for an external data source other than SQL Server or Oracle, the following steps are carried out:

 

1. Creating a custom Replication library.

Within this custom library, you will need to override Bizagi Replication's classes and methods (as described in the next section: Classes and methods to override).

 

2. Configuring the data provider in Bizagi to use this custom Replication library.

This configuration uses the Advanced Replication configuration in Bizagi.

 

 

Classes and methods to override

To customize Bizagi's Replication, it is necessary to develop an assembly that implements the following interfaces:

ICustomProviderDA

ICustomQueryDA

ICustomReplicationDA

IDatabaseProperties

 

 

Bizagi separates the operations for connection, disconnection and transactional management from the operations to query data from the external sources in the Provider and Entity interfaces.

Therefore, when creating a custom Replication library, Bizagi follows best practices for this management and implementation's design.

 

Provider Interface ICustomProviderDA

The class that invokes this interface must contain the following methods:

 

void Init (Dictionary<string, string> metadata): In charge of taking the data supplied in the system configuration, such as server name, database name, user, password, etc. It receives a Dictionary<string, string> map that contains the data configured as system metadata.

void OpenConnection(): This method is used to make the connection with the external system. In the case of a database, this is where you build the connection links and open a connection with the repository.

void CloseConnection(): In charge of closing the connection with the external system.

void BeginTransaction(): In charge of initiating a new transaction for the current operation in the system.

void Commit(): Commits the current transaction in the reference system.

void Rollback(): Carries out rollback of the current transaction in the reference system.

 

Provider Interface ICustomQueryDA

The class that invokes this interface must contain the following methods:

 

void AddParameter (string parameterName, BizagiDataType dataType, int size, byte precision, byte scale, object value, ParameterDirection parameterDirection): In charge of adding a parameter to the query to be executed.

void ClearParameters(): Removes the existing parameters in the query.

DataSet RunQuery(string query, string tableName): used to query the values of the external data source. The logic is generally equivalent to making a query on the fields of the data object.

 

Entity Interface ICustomReplicationDA

The class that invokes this interface must contain the following methods:

 

void Init(ICustomProviderDA provider): Initializes the connection with the system.

 

Parameter

Description

provider

Allows the conversion towards the object that invokes the ICustomProviderDA interface.

 

DataSet GetEntity(string entitySource, string[] columnList, string optionalSourceFilter): used to query the values of the external data source. The logic is generally equivalent to making a query on the fields of the data object applying optional filters.

 

 

Parameter

Description

entitySource

Name of the table to replicate in the data source.

arrsColList

Array that contains the name of the columns to query in the data source.

optionalSourceFilter

Contains the where clause to query in the data source.

RETURNED DataSet

A DataSet with the values for that entity.

 

 

Constants Interfaces: IDatabaseProperties

Keep in mind Bizagi will build the query and its syntax.

According to this idea, make sure you define all the proper constants to be used in queries in the integrated Database engine.

 

 

Example

In this example, we will configure custom Replication for a MySQL database engine.

 

We will present an example of the Replication classes that implement the  "ICustomProviderDA", "ICustomQueryDA" and "IReplicationEntDA" interfaces.

 

note_pin

Take into account that the following code provides an illustration for the "GetEntity()" method implementation (to serve as a guide), but other methods are not included and would need further development.

 

 

Creating a custom Replication library

In this specific example, in order to implement Replication classes that connect to a MySQL database, it is required to first download and install the MySQL Connector/NET component for that connection.

 

The following classes were developed with Microsoft Visual Studio. Within this .NET project, referencing the "MySql.Data.dll" assembly as installed by the MySQL Connector/Net component is required.

 

It is also necessary to reference the library BizAgi.EntityManager.Interfaces.CustomSource.dll of Bizagi.

 

This is found at the bin of the project's web application folder (by default at "C:\Bizagi\Projects\[PROJECT_NAME]\WebApplication\bin\").

 

 

CustomRefs

 

 

Class Interfaces ICustomProviderDA and 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 parameters 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

   }

 

}

 

 

Class Interface ICustomReplicationDA

using System;

using System.Data;

using System.Collections.Specialized;

using System.Text;

using BizAgi.EntityManager.Interfaces.CustomSource;

 

namespace BizagiMySQL

{

 

   public class CMySQLReplication : ICustomReplicationDA

   {

       /// <summary>

       /// Flag to show if object has been disposed

       /// </summary>

       protected bool m_bDisposed;

 

       /// <summary>

       /// Connection with the virtual System

       /// </summary>

       protected CMySQLProvider m_objSystem;

 

       /// <summary>

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

       /// </summary>

       protected HybridDictionary m_htMetadata;

 

       public CMySQLReplication()

       {

           m_bDisposed = false;

       }

 

       #region ICustomReplicationDA Members

 

       public void Init(ICustomProviderDA provider)

       {

           m_objSystem = (CMySQLProvider)provider;

       }

 

       public DataSet GetEntity(string entitySource, string[] columnList, string optionalSourceFilter)

       {

           try

           {

               StringBuilder sbSQL = new StringBuilder();

               sbSQL.Append(" SELECT ");

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

               sbSQL.Append(" FROM ");

               sbSQL.Append(entitySource);

               if (!string.IsNullOrWhiteSpace(optionalSourceFilter))

               {

                   sbSQL.Append(" WHERE ");

                   sbSQL.Append(optionalSourceFilter);

               }

 

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

             

               return ds;

           }

           catch (Exception e)

           {

               throw new ApplicationException(e.Message);

           }

 

       }

 

       #endregion

 

       #region IDisposable Members

 

       void IDisposable.Dispose()

       {

           if (!m_bDisposed)

           {

               // You should never close the connection within this method!!

               m_bDisposed = true;

           }

       }

 

       #endregion

   }

}

 

Parameters Class

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;

 

         }

 }

}

 

 

Class Interface 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 reserved 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 reserved 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

   }

}

 

 

 

 

 

Configuring the data provider in Bizagi

In this step, we may configure the System and data provider for Replication; by specifying which library will be used (the custom component we created previously).

 

note_pin

Take into account that this configuration is done through the Advanced Replication configuration method, which require that the entities to be replicated are already created in Bizagi's data model.

 

1. Click Systems in the Expert View of Bizagi.

Then either right-click the Systems element and select New System from the drop-down menu or click New System in the standard menu bar.

 

VR_Both02_NewSystem

 

 

2. Enter a Name and Description for the new system and click the Enable data providers checkbox.

Click Ok to save changes.

 

CustomVirtualization_Image002

 

 

3. Click the plus sign (+) beside the newly created system.

Right-click the New Provider element.

 

CustomVirtualization_Image003

 

 

4. In the New Provider window enter a Name, Display name and Description in the Provider Setup tab.

Check the Enable data replication option. Also check Enable data virtualization for this Provider (if it applies).

 

CustomVirtualization_Image004

 

5. Select the Connection details tab and then click New Assembly.

 

CustomVirtualization_Image005

 

6. Enter a Name, Display name, Namespace and Description.

Then click Select Assembly to select the .dll of the custom replication library previously built. Click Ok in the New Assembly window.

 

CustomVirtualization_Image006

 

7. Click the New Class button and in the New Class for Assembly window, enter the name of the class that implements the IProviderVirtualDA interface.

Click Ok.

 

CustomVirtualization_Image007

 

8. Now in the Provider Development Properties tab, include the connection properties by clicking the Metadata button to create a new Property-Value row.

Click Ok on the New Provider window.

 

CustomVirtualization_Image008

 

9. Expand the new provider element, select the Replicated Entities element and create a New Replication Class.

 

CustomReplication_Image001

 

10. Select the assembly from the drop-down list In the New Class for Assembly window (if the Entity class is in the same assembly as the Provider class) or include a new one by clicking on New Assembly.

 

CustomVirtualization_Image010

 

Click New Class and complete the necessary fields in the new window. Click Ok to complete the Entity Class Configuration.

 

CustomReplication_Image002

 

11. Right-click the new entity class element and select the Add Replication Schedule option.

 

CustomReplication_Image003

 

12. In the Replication setup enter a Name, Display Name and a Description for the replication schedule.

 

CustomReplication_Image004

 

 

Select the Schedule Properties tab and specify the frequency with which the information will be replicated from the data source.

 

CustomReplication_Image005

 

For the setup presented in this tab, define the periodicity and frequency of execution according to the detail in this table below:

 

Schedule option

Description

Enable Schedule for this Replication

Mark this option for Bizagi to execute the data replication from the external source.

Periodicity

Mark Daily, Weekly or Monthly to define how frequently will Bizagi execute the Replication schema.

Every

This option will change according to Periodicity's selection.

When Daily is marked: enter the number of days between repetitions of the execution.

When Weekly is marked: enter the number of weeks between repetitions of the execution.  Also, select on which weekdays this schema will be executed.

When Monthly is marked: enter the number of months between repetitions of the execution as well. Additionally, select the day of the month in which this schema will be executed.

Daily frequency

Define if the execution happens once a day (and at which time), or if it should be executed every certain time (minutes or hours).

Beginning

Set a starting date for this schema to begin its execution.

Schedule properties description

 

 

After the configuration is set for the start date of execution, click Ok.

 

13. Right-click the schedule and select Add Entity to Replication.

 

CustomReplication_Image006

 

 

14. In the Add Entity to Replication window, select the desired entity from the Parameter entities drop-down list. Then, type the external entity name in the External Source field. Next, from the list of attributes of the Bizagi entity, select one (or more) to be the business key (an attribute that has a unique value so that it can be used to differentiate one register form another).

 

 

CustomReplication_Image007

 

Click Ok to save this changes.

 

15. Select the replicated entity. Enter the corresponding external column (field) for each attribute of the replicated entity.

This is done by right-clicking on the attribute and selecting Properties.

 

CustomReplication_Image008

 

 

In the Edit Attribute window, type down the external column's name and click Ok.

 

CustomReplication_Image009

 

 

Do this for each of the listed attributes in the replicated entity.

 

note_pin

If your custom Replication library has references to other assemblies, it is necessary to copy them into the Scheduler folder for the Replication's execution. This folder is found by default at: "C:\Bizagi\Projects\[PROJECT_NAME]\Scheduler".

 

At this point we completed the Replication setup using a custom component, to connect to a MySQL database.

 

Verifying Replication (Checkpoint)

Once Replication is set, you may choose to verify that its execution synchronizes the values for those Parameter Entities with the external table's columns.

 

There are two ways to do this: using the options in the Systems modules, or through the displayed entities information (Entities module).

Options displayed in the Systems module are useful for a Production or Test Environment.

Options presented in the Entities module will serve as a checkpoint during Replication configuration (in the Development Environment).

 

To view how to verify that the Replication was set up or is running properly, refer to Verifying Replication.