public async Task <DimensionValue> AddDimensionValueAsync(
            DimensionValue dimensionValue,
            long dimensionId)
        {
            try
            {
                Check.IsNotNull(dimensionValue);
                Check.AreNotEqual(dimensionId, 0);

                await _masterDataValidators.DimensionValueValidator.ValidateAsync(dimensionValue, o =>
                {
                    o.IncludeRuleSets(ValidatorRulesets.AddNewDimensionValue);
                    o.ThrowOnFailures();
                }).ConfigureAwait(false);

                using (MasterDataContext ctx = new MasterDataContext(_dbContextOptions))
                {
                    using (IDbContextTransaction transaction = await ctx.Database.BeginTransactionAsync()
                                                               .ConfigureAwait(false))
                    {
                        try
                        {
                            // Check whether dimension exist
                            DomainModel.Dimension dimension = await ctx.Dimensions
                                                              .FindAsync(dimensionId)
                                                              .ConfigureAwait(true);

                            string msg = $"Dimension with Id {dimensionId} doesnt exists";
                            Check.IsNotNull(dimension, msg);

                            // check whether value already exist
                            DimensionValue doesDimensionValueExists = await ctx.DimensionValues
                                                                      .FirstOrDefaultAsync(w => w.Value == dimensionValue.Value)
                                                                      .ConfigureAwait(false);

                            if (doesDimensionValueExists != null)
                            {
                                // check whether dimension - dimension value pair exist
                                DimensionDimensionValue doesDimensionDimensionValueRelationExist = await ctx
                                                                                                   .DimensionDimensionValues
                                                                                                   .FirstOrDefaultAsync(p => p.DimensionId == dimension.Id &&
                                                                                                                        p.DimensionValueId == doesDimensionValueExists.Id)
                                                                                                   .ConfigureAwait(false);

                                // if doesnt exists create one
                                if (doesDimensionDimensionValueRelationExist == null)
                                {
                                    DimensionDimensionValue dimensionDimensionValue = new DimensionDimensionValue
                                    {
                                        DimensionId      = dimension.Id,
                                        DimensionValueId = doesDimensionValueExists.Id,
                                    };
                                    await ctx.DimensionDimensionValues.AddAsync(dimensionDimensionValue)
                                    .ConfigureAwait(false);

                                    await ctx.SaveChangesAsync().ConfigureAwait(false);

                                    await transaction.CommitAsync().ConfigureAwait(false);

                                    return(doesDimensionValueExists);
                                }

                                // include all related entities
                                // return doesDimensionValueExists;
                                DimensionValue alreadyExistingDimensionValue =
                                    await GetDimensionValueWithRelatedEntities(
                                        dimensionValue.Value, ctx)
                                    .ConfigureAwait(false);

                                return(alreadyExistingDimensionValue);
                            }

                            // create dimension value entry
                            DimensionValue newDimensionValue = new DimensionValue
                            {
                                Value = dimensionValue.Value,
                            };
                            await ctx.DimensionValues.AddAsync(newDimensionValue)
                            .ConfigureAwait(false);

                            await ctx.SaveChangesAsync().ConfigureAwait(false);

                            // create dimension - dimension value relation
                            DimensionDimensionValue newlyAddedDimensionValue = new DimensionDimensionValue
                            {
                                DimensionId      = dimension.Id,
                                DimensionValueId = newDimensionValue.Id,
                            };
                            await ctx.DimensionDimensionValues.AddAsync(newlyAddedDimensionValue)
                            .ConfigureAwait(false);

                            await ctx.SaveChangesAsync().ConfigureAwait(false);

                            await transaction.CommitAsync().ConfigureAwait(false);

                            DimensionValue createdDimensionValue =
                                await GetDimensionValueWithRelatedEntities(dimensionValue.Value, ctx)
                                .ConfigureAwait(false);

                            return(createdDimensionValue);
                        }
                        catch (Exception e)
                        {
                            await transaction.RollbackAsync().ConfigureAwait(false);

                            throw;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw new MasterDataBusinessLogicAddDimensionValueAsyncOperationException(e.Message, e);
            }
        }
        public async Task <DimensionValue> ModifyDimensionValueAsync(
            long dimensionId,
            DimensionValue oldDimensionValue,
            DimensionValue newDimensionValue)
        {
            using (MasterDataContext ctx = new MasterDataContext(_dbContextOptions))
            {
                using (IDbContextTransaction transaction = await ctx.Database.BeginTransactionAsync()
                                                           .ConfigureAwait(false))
                {
                    try
                    {
                        string dimensionIdErrorMsg = $"{nameof(dimensionId)} is zero.";
                        Check.AreNotEqual(dimensionId, 0, dimensionIdErrorMsg);

                        string oldDimensionValueErrorMsg = $"{nameof(oldDimensionValue)} is null.";
                        Check.IsNotNull(oldDimensionValue, oldDimensionValueErrorMsg);

                        string newDimensionValueErrorMsg = $"{nameof(newDimensionValue)} is null.";
                        Check.IsNotNull(newDimensionValue, newDimensionValueErrorMsg);

                        await _masterDataValidators.DimensionValueValidator.ValidateAsync(oldDimensionValue, o =>
                        {
                            o.IncludeRuleSets(ValidatorRulesets.ModifyDimensionValue);
                            o.ThrowOnFailures();
                        }).ConfigureAwait(false);

                        DomainModel.Dimension dim = await ctx.Dimensions.FindAsync(dimensionId).ConfigureAwait(false);

                        string noDimErrMsg = $"There is no dimension with id: {dimensionId}";
                        Check.IsNotNull(dim, noDimErrMsg);

                        DimensionValue dimVal = await ctx.DimensionValues.FindAsync(oldDimensionValue.Id)
                                                .ConfigureAwait(false);

                        string dimValErrMsg = $"There is no dimension value with id: {oldDimensionValue.Id}";
                        Check.IsNotNull(dimVal, dimValErrMsg);

                        // count how many dimension - dimension value relation exists
                        List <DimensionDimensionValue> countOfDimensionDimensionValueRelation = await ctx
                                                                                                .DimensionDimensionValues
                                                                                                .Where(p => p.DimensionValueId == oldDimensionValue.Id &&
                                                                                                       p.DimensionId != dimensionId)
                                                                                                .ToListAsync().ConfigureAwait(false);

                        if (countOfDimensionDimensionValueRelation.Any())
                        {
                            // If multiple dimensions references to the given dimension value
                            // then we are going to create a new dimension value and we are going to modify
                            // the dimension - dimension value reference to that
                            DimensionValue modifiedButNewDimensionValue = new DimensionValue
                            {
                                Value = newDimensionValue.Value,
                            };
                            await ctx.DimensionValues.AddAsync(modifiedButNewDimensionValue).ConfigureAwait(false);

                            await ctx.SaveChangesAsync().ConfigureAwait(false);

                            DimensionDimensionValue theOneGoingToBeModified = await ctx.DimensionDimensionValues
                                                                              .FirstOrDefaultAsync(p => p.DimensionId == dimensionId &&
                                                                                                   p.DimensionValueId == oldDimensionValue.Id)
                                                                              .ConfigureAwait(false);

                            if (theOneGoingToBeModified == null)
                            {
                                string msg = $"There is no DimensionDimensionValue entity with " +
                                             $"dimension id: {dimensionId}, and" +
                                             $"dimension value id: {oldDimensionValue.Id}!";
                                throw new MasterDataBusinessLogicNoSuchDimensionDimensionValueEntity(msg);
                            }

                            theOneGoingToBeModified.DimensionValueId = modifiedButNewDimensionValue.Id;
                            ctx.Entry(theOneGoingToBeModified).State = EntityState.Modified;
                            await ctx.SaveChangesAsync().ConfigureAwait(false);

                            await transaction.CommitAsync().ConfigureAwait(false);

                            DimensionValue modifiedResult = await ctx.DimensionValues.FirstOrDefaultAsync(
                                p => p.Id == modifiedButNewDimensionValue.Id).ConfigureAwait(false);

                            return(modifiedResult);
                        }

                        DimensionValue dimValToBeModified = await ctx.DimensionValues.FirstOrDefaultAsync(
                            p => p.Id == oldDimensionValue.Id).ConfigureAwait(false);

                        if (dimValToBeModified == null)
                        {
                            string erMsg = $"There is no dimension value with id: {oldDimensionValue.Id}";
                            throw new MasterDataBusinessLogicNoSuchDimensionValueEntity(erMsg);
                        }

                        dimValToBeModified.Value            = newDimensionValue.Value;
                        ctx.Entry(dimValToBeModified).State = EntityState.Modified;
                        await ctx.SaveChangesAsync().ConfigureAwait(false);

                        await transaction.CommitAsync().ConfigureAwait(false);

                        return(dimValToBeModified);
                    }
                    catch (Exception e)
                    {
                        await transaction.CommitAsync().ConfigureAwait(false);

                        throw new MasterDataBusinessLogicModifyDimensionValueAsyncOperationException(
                                  e.Message, e);
                    }
                }
            }
        }