In 3.4 Managers Overview we introduced the Managers who are connect the Business Logic with the Data Access Layer.

As we have already referenced almost all the existing managers inherits from BusinessCaseBaseManager  that implements the interface IBusinessCaseBaseManager .

IBusinessCaseBaseManager
namespace One.Core.Business.Interfaces
{
    /// <summary>
    /// Business Case base manager
    /// </summary>
    /// [3900-3999]
    [OneDealerMethodInjector(AttributeInheritance = MulticastInheritance.Multicast)]
    [MonitorTelemetry(AttributeInheritance = MulticastInheritance.Multicast, AttributeTargetMemberAttributes = MulticastAttributes.UserGenerated)]
    public interface IBusinessCaseBaseManager
    {
        UnAuthenticatedAccessBaseManager UnAuthenticatedAccessManager { get; }

        /// <summary>
        /// SERVICE LAYER ONLY
        /// </summary>
        T GetEntityByKey<T>(object keyValue) where T : IBusinessData;

        [BusinessCase("3900", BusinessCaseActionTypes.R)]
        IList<T> GetFullEntityList<T>(bool directAccess = false) where T : IBusinessData;

        [BusinessCase("3901", BusinessCaseActionTypes.R)]
        IList<T> GetEntityListByCombineFilter<T>(CombineFilter queryFilters, bool directAccess = false, int takeItems = 0, int skip = 0, string orderByPropertyName = null, bool orderByDescending = false, string orderThenByPropertyName = null, bool orderThenByDescending = false) where T : IBusinessData;
        
        [BusinessCase("3902", BusinessCaseActionTypes.R)]
        IList<T> GetEntityListByExpression<T>(Expression<Func<T, bool>> expressionFilter, bool directAccess = false, int takeItems = 0, int skip = 0, string orderByPropertyName = null, bool orderByDescending = false, string orderThenByPropertyName = null, bool orderThenByDescending = false) where T : IBusinessData;

        [BusinessCase("3903", BusinessCaseActionTypes.R)]
        IList<T> GetEntityListByFilter<T>(IFilter filter, bool directAccess = false, int takeItems = 0, int skip = 0, string orderByPropertyName = null, bool orderByDescending = false, string orderThenByPropertyName = null, bool orderThenByDescending = false) where T : IBusinessData;

        [BusinessCase("3904", BusinessCaseActionTypes.R)]
        T GetEntityByExpression<T>(Expression<Func<T, bool>> expressionFilter, bool directAccess = false) where T : IBusinessData;

        int? GetEntityCountByExpression<T>(Expression<Func<T, bool>> expressionFilter, bool directAccess = true) where T : IBusinessData;

        int? GetEntityCountByFilter<T>(IFilter filter, bool directAccess = true) where T : IBusinessData;

        int? GetEntityCountByCombineFilter<T>(CombineFilter combinefilter, bool directAccess = true) where T : IBusinessData;

        IList<T> BusinessCaseDelete<T>(IBusinessCaseRepository<T> bcRepository, T entity, bool directAccess = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityByFilter<T>(IBusinessCaseRepository<T> bcRepository, IFilter filter, bool directAccess = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityByFilter<T>(IBusinessCaseRepository<T> bcRepository, Expression<Func<T, bool>> filter, bool directAccess = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityByFilter<T>(IBusinessCaseRepository<T> bcRepository, IFilter preFilter, Expression<Func<T, bool>> filter, bool directAccess = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityByFilter<T>(IBusinessCaseRepository<T> bcRepository, IFilter preFilter, IFilter filter, bool directAccess = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityByFilter<T>(IBusinessCaseRepository<T> bcRepository, Expression<Func<T, bool>> preFilter, IFilter filter, bool directAccess = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityByFilter<T>(IBusinessCaseRepository<T> bcRepository, Expression<Func<T, bool>> preFilter, Expression<Func<T, bool>> filter, bool directAccess = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityListByFilter<T>(IBusinessCaseRepository<T> bcRepository, Expression<Func<T, bool>> filter, bool useDirectDbAccess = true, int take = 0, int skip = 0, string orderByProperty = null, bool orderByDescending = false, string orderThenByProperty = null, bool orderThenByDescending = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityListByFilter<T>(IBusinessCaseRepository<T> bcRepository, Expression<Func<T, bool>> filter, Expression<Func<T, bool>> preFilter, bool useDirectDbAccess = true, int take = 0, int skip = 0, string orderByProperty = null, bool orderByDescending = false, string orderThenByProperty = null, bool orderThenByDescending = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityListByFilter<T>(IBusinessCaseRepository<T> bcRepository, IFilter filter, bool useDirectDbAccess = true, int take = 0, int skip = 0, string orderByProperty = null, bool orderByDescending = false, string orderThenByProperty = null, bool orderThenByDescending = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityListByFilter<T>(IBusinessCaseRepository<T> bcRepository, IFilter filter, IFilter preFilter, bool useDirectDbAccess = true, int take = 0, int skip = 0, string orderByProperty = null, bool orderByDescending = false, string orderThenByProperty = null, bool orderThenByDescending = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityListByFilter<T>(IBusinessCaseRepository<T> bcRepository, Expression<Func<T, bool>> filter, IFilter preFilter, bool useDirectDbAccess = true, int take = 0, int skip = 0, string orderByProperty = null, bool orderByDescending = false, string orderThenByProperty = null, bool orderThenByDescending = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityListByFilter<T>(IBusinessCaseRepository<T> bcRepository, IFilter filter, Expression<Func<T, bool>> preFilter, bool useDirectDbAccess = true, int take = 0, int skip = 0, string orderByProperty = null, bool orderByDescending = false, string orderThenByProperty = null, bool orderThenByDescending = false) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityByKey<T>(IBusinessCaseRepository<T> bcRepository, object primaryKeyValue) where T : IBusinessData;

        T BusinessCaseGetEntityFirstByFilter<T>(IBusinessCaseRepository<T> bcRepository, Expression<Func<T, bool>> filter, bool directAccess = false) where T : IBusinessData;

        IList<T> BusinessCaseInsert<T>(IBusinessCaseRepository<T> bcRepository, T entity, bool directAccess = false) where T : IBusinessData;

        IList<T> BusinessCaseInsertWithIdentity<T>(IBusinessCaseRepository<T> bcRepository, T entity) where T : IBusinessData;

        IList<T> BusinessCaseInsert<T>(IBusinessCaseRepository<T> bcRepository, IList<T> entityList, bool directAccess = true) where T : IBusinessData;

        IList<T> BusinessCaseListDelete<T>(IBusinessCaseRepository<T> bcRepository, IList<T> entityList, bool directAccess = true) where T : IBusinessData;

        IList<T> BusinessCaseListUpdate<T>(IBusinessCaseRepository<T> bcRepository, IList<T> entityList, bool directAccess = true) where T : IBusinessData;

        IList<T> BusinessCaseUpdate<T>(IBusinessCaseRepository<T> bcRepository, T entity, bool directAccess = false) where T : IBusinessData;

        IList<BusinessError> GetCurrentManagerErrors();

        IList<BusinessError> GetLastManagerErrors();

        bool HasErrors();

        void ClearErrors();

        string GetLastManagerErrorDescription();

        IList<BusinessError> GetErrorsByMethodName(string methodName);

        IList<T> BusinessCaseGetEntityFullList<T>(IBusinessCaseRepository<T> bcRepository, bool directAccess = true) where T : IBusinessData;

        IList<T> BusinessCaseGetEntityListByFilter<T>(IFilter filter, Expression<Func<T, bool>> preFilter, bool useDirectDbAccess = true, int take = 0, int skip = 0, string orderByProperty = null, bool orderByDescending = false, string orderThenByProperty = null, bool orderThenByDescending = false) where T : IBusinessData;

        #region "Stored Procedures"

        IList<T> BusinessCaseGetStoredProcedureResult<T>(T storedProcedureEntity) where T : IBusinessData;

        IList<T> BusinessCaseExecuteStoredProcedure<T>(T storedProcedureEntity) where T : IBusinessData;
        #endregion

        BusinessCaseBaseManagerResult<T> GetResult<T>(Func<T> func);

        IList<T> ExecuteSProcedure<T>(T entry) where T : IBusinessData;

        IList<T> GetValueOrNull<T>(IBusinessResult<T> bcResult, IList<T> @default = null) where T : IBusinessData;

        void SetErrors(IList<BusinessError> errors);

        void SetError(BusinessError error);

        IKernel Kernel { get; set; }

        string GenerateCode<T>(bool useDirectDbAccess = true) where T : IBusinessData;

        IList<IBusinessData> GetItemsByCombineFilter<T>(IFilter filters, int page, int pageSize, bool useDirectDbAccess = true) where T : IBusinessData;
        
        IList<IBusinessData> GetItemsByExpression<T>(Expression<Func<T, bool>> filters, int page, int pageSize, bool useDirectDbAccess = true) where T : IBusinessData;
        
        IList<T> Save<T>(T entry, IBusinessCaseRepository<T> bcRepository) where T : IBusinessData;

        [BusinessCase("3905", BusinessCaseActionTypes.U)]
        IList<T> UpdateEntity<T>(T entity, bool directAccess = false) where T : IBusinessData;

		[BusinessCase("3909", BusinessCaseActionTypes.U)]
		IList<T> UpdateListOfEntity<T>(List<T> entityList, bool directAccess = false) where T : IBusinessData;

		[BusinessCase("3906", BusinessCaseActionTypes.C)]
        IList<T> InsertEntity<T>(T entity, bool directAccess = false) where T : IBusinessData;
        [BusinessCase("3906", BusinessCaseActionTypes.C)]
        IList<T> InsertEntityWithIdentity<T>(T entity) where T : IBusinessData;

        [BusinessCase("3907", BusinessCaseActionTypes.C)]
        IList<T> DeleteEntity<T>(T entity, bool directAccess = false) where T : IBusinessData;

        IList<T> GetStoreProcePResult<T>(T entry) where T : IBusinessData;

		[BusinessCase("3908", BusinessCaseActionTypes.C)]
		IList<T> InsertListOfEntity<T>(List<T> entityList, bool directAccess = false) where T : IBusinessData;

    }
}

useDirectDbAccess

You will notice that some methods expecting as an input parameter the useDirectDbAccess , which is a flag for informing the repository how to communicate with the database ( direct access / sql query or Service Layer / HTTP request). We avoid of using the Service Layer (SL) because it is actually a HTTP request and prefer the direct access, but some objects we must use the SL. These objects usually are entities with sub collections or B1 Entities, such as Business Partner, Vehicle, Lead, etc.

The developer must know what value must the useDirectDbAccess have, but whatever value choose the query will perform successfully. Mostly it has to do with performance and stability.

Errors

As you can see from the interface the BusinessCaseBaseManager implements a set of data access methods. Some of them are dealing with error handling by constructing error structure ( BusinessError ). The following methods are related to error handling

  • GetCurrentManagerErrors
  • GetLastManagerErrors
  • HasErrors
  • ClearErrors
  • GetLastManagerErrorDescription
  • GetErrorsByMethodName
  • SetErrors
  • SetError

In this way you can use different managers and you can know if any error has occured inside a manager.

Each method is inside in a try/catch/finally block and in the catch block creates a BusinessError . In insert/update methods we have a finally block that informs, though SignalR, whoever it might listen for changes.For example if a Lead is created, users that are viewing the dashboard page can immediately see the change.

In the some methods we have the BCErrorTracing  to record log.

RepositoriesListInstance

The BusinessCaseBaseManager,in order to optimize performance , has a collection of repositories ( RepositoriesListInstance ) for each Entity that the manager have been called in order to improve the load from reflection.

Each time a method is called from the BusinessCaseBaseManager for a specific entity, it is called the CreateBCManager<T>  where T is a class of type IBusinessData .


CreateBCManager
public IBusinessCaseRepository<T> CreateBCManager<T>() where T : IBusinessData
        {
            var type = typeof(T).FullName;

            if (!RepositoriesListInstance.ContainsKey(type))
            {
                try
                {
                    lock (padlock)
                    {
                        if (!RepositoriesListInstance.ContainsKey(type))
                        {
                            var repositoryInstance = Kernel.Get<IBusinessCaseRepository<T>>();
                            RepositoriesListInstance.Add(type, repositoryInstance);
                            return (IBusinessCaseRepository<T>)RepositoriesListInstance[type];
                        }
                    }

                }
                catch (Exception ex)
                {
                    SetErrors(new List<BusinessError>()
                    {
                        new BusinessError()
                        {
                            BusinessErrorDescription = "BusinessCaseBaseManager: Could not create a business case generic repository instance out of the requested IBusinessData entity type. InnerException: " +ex.InnerException,
                            BusinessErrorCode = BusinessErrors.InternalError
                        }
                    });
                    return null;
                }
            }
            return (IBusinessCaseRepository<T>)RepositoriesListInstance[type];
        }

IBusinessCaseRepository 

The IBusinessCaseRepository  is binded to GenericBusinessCaseRepository<TBusinessData>  where TBusinessData  is type of IBusinessData .

The GenericBusinessCaseRepository has methods regarding the data dimensions permissions such as

  • UserHasAccessToRecordByDimensionValue
  • B1UserCanSeeRecord

and implements also the data access layer.

The GenericBusinessCaseRepository supports three (3) kinds of data access:

  • SAP HANA direct access with POCO through LinqToDB ORM (SqlRepository)
  • SAP HANA Service Layer access - HTTP Calls (SLRepository)
  • SAP HANA direct access for entities with sub collections (SL Decoupled data access version)

A typical example can be found below:

Example
public IBusinessResult<TBusinessData> CreateEntity(TBusinessData entity, bool useDirectDbAccess = false)
        {
            entity = _entityDimensionFilteringRepository.ApplyDimensionsBeforeEntityCreation(entity, _dimensionHelper.GetEntityDimensionGlobalRules(), _dimensionHelper.GetDimensionFieldName);
            _entityActionRepository?.OnBeforeInsert(entity);

            try
            {
                if (useDirectDbAccess)
                    entity = GetSQLRepository<TBusinessData>().Insert(entity);
                else if (!_systemOptionsProvider.HasSAPB1)
                    entity = GetSQLEntityRepository<TBusinessData>().Insert(entity);
                else
                    entity = GetSLRepository<TBusinessData>().Insert(entity);

                var success = CreateSuccess(entity);
                _entityActionRepository?.OnAfterInsert(entity, success);
                return success;
            }
            catch (DataServiceRequestException ex)
            {
                var manager = _kernel.Get<ILogger>();
                manager.LogException($"exception on CreateEntity({typeof(TBusinessData).Name}): {ex.InnerException}", ex);
                return CreateServiceLayerFailWithMessage(ex);
            }
            catch (Exception ex)
            {
                var manager = _kernel.Get<ILogger>();
                manager.LogException($"exception on CreateEntity({typeof(TBusinessData).Name}): {ex.InnerException}", ex);
                var fail = CreateFailWithMessage(ex.ToString());
                _entityActionRepository?.OnAfterInsert(entity, fail);
                return fail;
            }
        }

Related

4.7.1 Database Models

  • No labels
Write a comment…