/// <summary>
        /// Executes Insert DataAction
        /// </summary>
        /// <param name="Action">DataAction to execute</param>
        private void DoInsertAction(DataAction Action)
        {
            // BEFORE INSERT
            if (this.BeforeInsert != null)
            {
                #region LOG ENTRY
#if !NO_LOG
                Log.WriteLine(this, "Calling BeforeInsert event(Action = [" + Action.ToString() + "]");
#endif
                #endregion
                this.BeforeInsert(this, new DataActionProcessingEventArgs(Action));
            }
            this.AssertHasAccess(AccessRights.Insert);
            // INSERT ITSELF
            if (!Action.Completed)
            {
                #region LOG ENTRY
#if !NO_LOG
                Log.WriteLine(this, "Executing insert action.");
#endif
                #endregion
                if (this.CustomSQLs.ContainsKey(CustomSQLType.Insert))
                {
                    string sql = this.ParseSQLTemplate(this.CustomSQLs[CustomSQLType.Insert], Action.Data, Action.PrimaryKeyField, Action.PrimaryKeyValue);
                    Action.PostoperationalPrimaryKeyValue = this.Adapter.ExecuteScalar(sql);
                }
                else
                    Action.PostoperationalPrimaryKeyValue = this.Adapter.ExecuteInsertQuery(Action.TableName, Action.Data, Action.PrimaryKeyField, Action.PrimaryKeyValue);
                #region LOG ENTRY
#if !NO_LOG
                Log.WriteLine(this, "Action completed. PostoperationalPrimaryKeyValue is " + Convert.ToString(Action.PostoperationalPrimaryKeyValue ?? "null") + ".");
#endif
                #endregion
            }
            #region LOG ENTRY
#if !NO_LOG
            else
                Log.WriteLine(this, "Skipping insert action, because it's marked as completed.");
#endif
            #endregion

            // AFTER INSERT
            if (this.Inserted != null)
            {
                #region LOG ENTRY
#if !NO_LOG
                Log.WriteLine(this, "Calling Inserted event. Action =[" + Action.ToString() + "]");
#endif
                #endregion
                this.Inserted(this, new DataActionProcessingEventArgs(Action));
            }
        }
        /// <summary>
        /// Executes Delete DataAction
        /// </summary>
        /// <param name="Action">DataAction to execute</param>
        private void DoDeleteAction(DataAction Action)
        {
            // BEFORE DELETE
            if (this.BeforeDelete != null)
            {
                #region LOG ENTRY
#if !NO_LOG
                Log.WriteLine(this, "Calling BeforeDelete event(Action = [" + Action.ToString() + "]");
#endif
                #endregion
                this.BeforeDelete(this, new DataActionProcessingEventArgs(Action));
            }
            this.AssertHasAccess(AccessRights.Delete);
            // DELETE ITSELF
            if (!Action.Completed)
            {
                #region LOG ENTRY
#if !NO_LOG
                Log.WriteLine(this, "Executing delete action.");
#endif
                #endregion
                if (this.CustomSQLs.ContainsKey(CustomSQLType.Delete))
                {
                    string sql = this.ParseSQLTemplate(this.CustomSQLs[CustomSQLType.Delete], Action.Data, Action.PrimaryKeyField, Action.PrimaryKeyValue);
                    Action.PostoperationalPrimaryKeyValue = this.Adapter.ExecuteScalar(sql);
                }
                else
                    this.Adapter.ExecuteDeleteQuery(Action.TableName, Action.PrimaryKeyField, Action.PrimaryKeyValue);
            }
            #region LOG ENTRY
#if !NO_LOG
            else
                Log.WriteLine(this, "Skipping delete action, because it's marked as completed.");
#endif
            #endregion
            // DELETED
            if (this.Deleted != null)
            {
                #region LOG ENTRY
#if !NO_LOG
                Log.WriteLine(this, "Calling Deleted event. Action =[" + Action.ToString() + "]");
#endif
                #endregion
                this.Deleted(this, new DataActionProcessingEventArgs(Action));
            }
        }
        /// <summary>
        /// Executes DataAction object (if it's not marked as completed)
        /// </summary>
        /// <param name="Action">DataAction object to execute</param>
        protected void ProcessDataAction(DataAction Action)
        {
            //BEFORE EVENT
            if (this.BeforeDataActionProcessing != null)
            {
                #region LOG ENTRY
#if !NO_LOG
                Log.WriteLine(this, "Calling BeforeDataActionProcessing event(Action = [" + Action.ToString() + "]");
#endif
                #endregion
                this.BeforeDataActionProcessing(this, new DataActionProcessingEventArgs(Action));
            }
            #region LOG ENTRY
#if !NO_LOG
            Log.WriteLine(this, "Processing data action (Action = [" + Action.ToString() + "]");
#endif
            #endregion
            //PROCESSING
            if (!Action.Completed)
                try
                {
                    //Open transaction if necessary
                    if (this.TransactionMode == TransactionMode.PerRecord)
                    {
                        #region LOG ENTRY
#if !NO_LOG
                        Log.WriteLine(this, "Entering " + this.TransactionMode.ToString() + " transaction mode");
#endif
                        #endregion
                        this.Adapter.BeginTransaction();
                    }
                    switch (Action.ActionType)
                    {
                        case ActionType.Inserted:
                            this.DoInsertAction(Action);
                            break;
                        case ActionType.Updated:
                            this.DoUpdateAction(Action);
                            break;
                        case ActionType.Deleted:
                            this.DoDeleteAction(Action);
                            break;
                        // CUSTOM ACTION
                        default:
                            break;
                    }
                    //close transaction if necessary
                    if (this.TransactionMode == TransactionMode.PerRecord)
                    {
                        #region LOG ENTRY
#if !NO_LOG
                        Log.WriteLine(this, "Commiting " + this.TransactionMode.ToString() + " transaction");
#endif
                        #endregion
                        this.Adapter.CommitTransaction();
                    }
                    //now data action is finished
                    Action.SetCompleted();
                }
                catch (Exception ex1)
                {
                    #region LOG ENTRY
#if !NO_LOG
                    Log.WriteLine(this, "Exception cought: " + ex1.Message);
#endif
                    #endregion
                    try
                    {
                        //rollback transaction if necessary
                        if (this.TransactionMode == TransactionMode.PerRecord)
                        {
                            #region LOG ENTRY
#if !NO_LOG
                            Log.WriteLine(this, "Rolling back " + this.TransactionMode.ToString() + " transaction");
#endif
                            #endregion
                            this.Adapter.RollbackTransaction();
                        }
                        #region LOG ENTRY
#if !NO_LOG
                        Log.WriteLine(this, "ERROR: " + ex1.Message);
#endif
                        #endregion
                        Action.SetFailed(ex1.Message);
                    }
                    catch (Exception ex2)
                    {
                        #region LOG ENTRY
#if !NO_LOG
                        Log.WriteLine(this, "Exception cought: " + ex2.Message);
#endif
                        #endregion
                        Action.SetFailed(ex1.Message + Environment.NewLine + "Transaction rollback failed with the following error: " + ex2.Message);
                    }
                }
            //AFTER EVENT
            if (this.DataActionProcessed != null)
            {
                #region LOG ENTRY
#if !NO_LOG
                Log.WriteLine(this, "Calling DataActionProcessed event. Action=[" + Action.ToString() + "]");
#endif
                #endregion
                this.DataActionProcessed(this, new DataActionProcessingEventArgs(Action));
            }
        }