/// <summary>
        /// Execute a service from a client
        /// </summary>
        /// <param name="customerId"></param>
        /// <param name="userId"></param>
        /// <param name="profile"></param>
        /// <param name="area"></param>
        /// <param name="moduleId"></param>
        /// <param name="service"></param>
        /// <param name="record"></param>
        /// <param name="identity"></param>
        /// <returns>Data</returns>
        public JObject ExecuteService(int customerId, int userId, UserProfile.EUserProfile profile, string area, int moduleId, string service, JObject record, JObject identity)
        {
            JObject result = null;

            Info($"Executing the service: ['{service}', '{(record == null ? "null" : record.ToString(Formatting.None))}', '{(identity == null ? "null" : identity.ToString(Formatting.None))}'] ...");

            // Lock database during the execution of the service

            using (DatabaseLock lockDatabase = Database.Lock(customerId))
            {
                // Execute the request

                try
                {
                    result = Database.ExecuteService(customerId, userId, profile, area, moduleId, service, record, identity);

                    // Unlock the database

                    lockDatabase.Commit();
                }
                catch (System.Exception ex)
                {
                    Exception("An exception occurs on executing the service", ex);

                    // Rollback the requests done

                    throw;
                }
            }

            Info($"The service has correctly been executed : {(result == null ? "null" : result.ToString(Formatting.None))}");

            return(result);
        }
示例#2
0
        /// <summary>
        /// Override the Dispose to write a message on deleting the database context
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            if (IsVerbose())
            {
                Verbose($"Deleting {ConfigurationManager.DatabaseProvider} database instance ...");
            }

            if (_lock != null)
            {
                _lock.Dispose();
                _lock = null;
            }

            base.Dispose(disposing);
        }
        /// <summary>
        /// Execute a list of requests from a client
        /// </summary>
        /// <param name="transaction"></param>
        /// <returns>RequestId, Error, Record</returns>
        public List <Tuple <DSRecord, InformationRecord> > ExecuteTransaction(DSTransaction transaction)
        {
            Info($"Executing the transaction [{transaction.RequestId}] containing {transaction.Requests.Count} requests ...");

            List <Tuple <DSRecord, InformationRecord> >         recordsTreated  = new List <Tuple <DSRecord, InformationRecord> >();
            List <Tuple <string, DSRecord, InformationRecord> > recordsToUpdate = new List <Tuple <string, DSRecord, InformationRecord> >();

            // Retrieve the database schema

            DSDatabase schema = ConfigurationManager.Schemas[transaction.Area];

            if (schema == null)
            {
                Error("No schema available!");
                throw new ExceptionDefinitionRecord("ERR_SCHEMA");
            }

            // Lock database during the execution of the request

            using (DatabaseLock lockDatabase = Database.Lock(transaction.CustomerId))
            {
                try
                {
                    if (IsVerbose())
                    {
                        Verbose("Getting the first tick of the transaction ...");
                    }

                    // Get the tick

                    string          tickKey    = $"Database.Tick.{transaction.CustomerId}";
                    int             tick       = 0;
                    ParameterRecord tickRecord = Database._Parameter.FirstOrDefault(p => p.Key.Equals(tickKey));
                    if (tickRecord == null)
                    {
                        tickRecord = new ParameterRecord {
                            Key = tickKey, Value = transaction.Requests.Count.ToString()
                        };
                        tickRecord = Database._Parameter.Add(tickRecord);
                    }
                    else
                    {
                        tick             = int.Parse(tickRecord.Value);
                        tickRecord.Value = (tick + transaction.Requests.Count).ToString();
                    }
                    Database.SaveChanges();

                    if (IsDebug())
                    {
                        Debug($"First tick is {tick}");
                    }

                    // Execute the OnBefore trigger

                    if (IsVerbose())
                    {
                        Verbose("Executing the pre-request of the transaction ...");
                    }

                    transaction.SetNewTick(tick);

                    foreach (DSRequest request in transaction.Requests)
                    {
                        // Execute the request

                        if (IsVerboseAll())
                        {
                            Verbose($"Executing the pre-request[{request.Id}] with tick[{request.NewTick}]: {request} ...");
                        }

                        // Execute the trigger before requesting

                        schema.OnBeforeExecuteRequest(Database, request.NewTick,
                                                      transaction.CustomerId, transaction.UserId, transaction.Area, transaction.Profile,
                                                      request.Table, request.Action, request.RecordId, request.Record, request.Identity);
                    }

                    if (IsDebug())
                    {
                        Debug($"Pre-request executed for {transaction.Requests.Count} requests");
                    }

                    // Execute each request

                    if (IsVerbose())
                    {
                        Verbose("Executing the transaction ...");
                    }

                    // Execution by lot

                    List <RequestTableRecord> actions = new List <RequestTableRecord>();

                    int index = 0;
                    foreach (List <DSRequest> lot in transaction.LotRequests)
                    {
                        // Execute the lot of requests

                        if (IsVerbose())
                        {
                            Verbose($"Executing the lot[{index}] with {lot.Count} requests ...");
                        }

                        // Execute the lot of requests

                        recordsTreated.AddRange(schema.ExecuteRequest(Database, transaction, lot));

                        // Saving data

                        Database.SaveChanges();

                        index++;
                    }

                    if (IsVerbose())
                    {
                        Verbose("Building the list of actions ...");
                    }

                    index = 0;
                    foreach (DSRequest request in transaction.Requests)
                    {
                        Tuple <DSRecord, InformationRecord> recordTreated = recordsTreated[index];

                        // Keep in memory all records executed

                        recordsToUpdate.Add(Tuple.Create(request.Table, recordTreated.Item1, recordTreated.Item2));

                        // The request is correctly executed ... Store a new request

                        actions.Add(new RequestTableRecord
                        {
                            Tick       = request.NewTick,
                            CustomerId = transaction.CustomerId,
                            UserId     = transaction.UserId,
                            RequestId  = transaction.RequestId,
                            Table      = request.Table,
                            Action     = request.Action,
                            Id         = (recordTreated == null || recordTreated.Item1 == null ? -1 : recordTreated.Item1.Id)
                        });

                        Info($"The request[{request.Id}] has correctly been executed : {(recordTreated == null ? "null" : recordTreated.ToString())}");

                        index++;
                    }

                    if (IsDebug())
                    {
                        Debug($"Transaction executed with {transaction.Requests.Count} requests");
                    }

                    // Write actions into the RequestTable

                    if (IsVerbose())
                    {
                        Verbose($"Writing {actions.Count} actions into the RequestTable ...");
                    }

                    Database._RequestTable.AddRange(actions);
                    Database.SaveChanges();

                    if (IsDebug())
                    {
                        Debug($"{actions.Count} actions written into the RequestTable");
                    }

                    // Execute the OnAfter trigger

                    if (IsVerbose())
                    {
                        Verbose("Executing the post-request of the transaction ...");
                    }

                    foreach (DSRequest request in transaction.Requests)
                    {
                        // Execute the request

                        if (IsVerboseAll())
                        {
                            Verbose($"Executing the post-request[{request.Id}] with tick[{request.NewTick}]: {request} ...");
                        }

                        // Execute the trigger before requesting

                        DSRecord record = recordsTreated[request.Id].Item1;
                        if (record != null)
                        {
                            schema.OnAfterExecuteRequest(Database, request.NewTick,
                                                         transaction.CustomerId, transaction.UserId, transaction.Area, transaction.Profile,
                                                         request.Table, request.Action, record.Id, record);
                        }
                    }

                    if (IsDebug())
                    {
                        Debug($"Post-request executed for {transaction.Requests.Count} requests");
                    }

                    // Unlock the database and commit all changes

                    if (IsVerbose())
                    {
                        Verbose("Committing changes ...");
                    }

                    lockDatabase.Commit();

                    if (IsVerbose())
                    {
                        Verbose("Changes committed");
                    }

                    // Update the cache manager

                    if (IsVerbose())
                    {
                        Verbose("Updating cache ...");
                    }

                    DatabaseCacheManager.Instance.UpdateCache(recordsToUpdate, transaction.CustomerId, tick + transaction.Requests.Count);

                    if (IsVerbose())
                    {
                        Verbose("Cache updated");
                    }
                }
                catch (System.Exception ex)
                {
                    Exception("An exception occurs on executing the transaction", ex);

                    bool saveFailed = false;

                    do
                    {
                        saveFailed = false;
                        try
                        {
                            Database.SaveChanges();
                        }
                        catch (DbUpdateException ex2)
                        {
                            saveFailed = true;
                            ex2.Entries.Single().Reload();
                        }
                    }while (saveFailed);

                    // Rollback all request already executed

                    throw ex;
                }
            }

            Info("Transaction done");

            return(recordsTreated);
        }
示例#4
0
        /// <summary>
        /// Lock the database for a customer
        /// </summary>
        /// <param name="customerId"></param>
        public DatabaseLock Lock(int customerId)
        {
            string lockKey = $"Database.Lock.{customerId}";

            // Create Database.Lock if the line doesn't exist

            ParameterRecord parameterRecord = _Parameter.FirstOrDefault(p => p.Key.Equals(lockKey));

            if (parameterRecord == null)
            {
                parameterRecord = new ParameterRecord()
                {
                    Key = $"Database.Lock.{customerId}", Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                };
                parameterRecord = _Parameter.Add(parameterRecord);
                SaveChanges();
            }

            // Lock the database

            DbContextTransaction transaction = Database.BeginTransaction();

            switch (_provider.Type)
            {
            case Provider.Provider.EProvider.Oracle:
                if (Database.Connection.State != System.Data.ConnectionState.Open)
                {
                    Database.Connection.Open();
                }
                Database.ExecuteSqlCommand($"UPDATE \"_Parameter\" SET \"Value\" = '{DateTime.Now:yyyy-MM-dd HH:mm:ss}' where \"Key\" = 'Database.Lock.{customerId}'");
                break;

            case Provider.Provider.EProvider.SQLServer:
                if (Database.Connection.State != System.Data.ConnectionState.Open)
                {
                    Database.Connection.Open();
                }
                Database.ExecuteSqlCommand($"UPDATE [{ConfigurationManager.DatabaseSchema}].[_Parameter] SET [Value] = '{DateTime.Now:yyyy-MM-dd HH:mm:ss}' where [Key] = 'Database.Lock.{customerId}'");
                break;

            case Provider.Provider.EProvider.Firebird:
                if (Database.Connection.State != System.Data.ConnectionState.Open)
                {
                    Database.Connection.Open();
                }
                Database.ExecuteSqlCommand($"UPDATE \"_Parameter\" SET \"Value\" = '{DateTime.Now:yyyy-MM-dd HH:mm:ss}' where \"Key\" = 'Database.Lock.{customerId}'");
                break;

            case Provider.Provider.EProvider.MySQL:
                if (Database.Connection.State != System.Data.ConnectionState.Open)
                {
                    Database.Connection.Open();
                }
                Database.ExecuteSqlCommand($"UPDATE `{ConfigurationManager.DatabaseSchema}`.`_Parameter` SET `Value` = '{DateTime.Now:yyyy-MM-dd HH:mm:ss}' where `Key` = 'Database.Lock.{customerId}'");
                break;

            default:
                Warn("Unable to lock the database due to an implementation of locking database missing!");
                break;
            }

            _lock = new DatabaseLock(transaction);
            return(_lock);
        }