/// <summary>
        /// Creates a new reservation and saves it to the database
        /// </summary>
        /// <param name="request">Create reservation DTO</param>
        /// <returns>The newly created reserrvation DTO</returns>
        public Dto.ReservationResult AddNewReservation(Dto.ReservationRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            return(Call(() =>
            {
                //creates a new reservation entity
                var reservation = ReservationFactory.CreateReservation(request.Name, request.ReservationDateTime, request.GuestsCount, request.UserId);

                var entityValidator = EntityValidatorLocator.CreateValidator();
                if (entityValidator.IsValid(reservation))
                {
                    using (var transaction = _reservationRepository.BeginTransaction())
                    {
                        _reservationRepository.Add(reservation);
                        transaction.Commit();
                    }
                }
                else
                {
                    return new Dto.ReservationResult
                    {
                        Status = ActionResultCode.Errored,
                        Message = Messages.validation_errors,
                        Errors = entityValidator.GetInvalidMessages(reservation)
                    };
                }

                //returns success
                return reservation.ProjectedAs <Dto.ReservationResult>();
            }));
        }
        /// <summary>
        /// Updates an existing reservation
        /// </summary>
        /// <param name="id">The reservation id</param>
        /// <param name="request">The changed reservation DTO</param>
        /// <returns>The updated reservation DTO</returns>
        public Dto.ReservationResult UpdateReservation(int id, Dto.ReservationRequest request)
        {
            if (id < 1)
            {
                throw new ArgumentOutOfRangeException("id");
            }

            return(Call(() =>
            {
                using (var transaction = _reservationRepository.BeginTransaction())
                {
                    //get the reservation
                    var reservation = _reservationRepository.Get(id);

                    //returns failure if a reservation is not found
                    if (reservation == null)
                    {
                        return new Dto.ReservationResult
                        {
                            Status = ActionResultCode.Failed,
                            Message = string.Format(Messages.reservation_not_found, id)
                        };
                    }

                    //updates fields from the DTO
                    reservation.Name = request.Name;
                    reservation.ReservationDateTime = request.ReservationDateTime;
                    reservation.GuestsCount = request.GuestsCount;
                    reservation.ModifiedBy = request.UserId;
                    reservation.ModifiedOn = DateTime.Now;

                    //validates the reservation
                    var entityValidator = EntityValidatorLocator.CreateValidator();
                    if (entityValidator.IsValid(reservation))
                    {
                        transaction.Commit();
                    }
                    else
                    {
                        return new Dto.ReservationResult
                        {
                            Status = ActionResultCode.Errored,
                            Message = Messages.validation_errors,
                            Errors = entityValidator.GetInvalidMessages(reservation)
                        };
                    }

                    //returns the updated reservation
                    return reservation.ProjectedAs <Dto.ReservationResult>();
                }
            }));
        }
        public static EntityResult <T> SaveEntity <TEntity, T>(this IRepository <TEntity> repository, T entity)
            where TEntity : class
            where T : class, TEntity
        {
            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }

            var entityValidator = EntityValidatorLocator.CreateValidator();
            var isValid         = entityValidator.IsValid(entity);

            if (!isValid)
            {
                return(new EntityResult <T>(entityValidator, entity, false));
            }

            var context = repository.UnitOfWork;

            repository.Add(entity);
            context.SaveChanges();

            return(new EntityResult <T>(entityValidator, entity, true));
        }
        public static EntityResult <T> SaveEntity <TEntity, T>(this IRepository <TEntity> repository, T entity)
            where TEntity : class
            where T : class, TEntity
        {
            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }

            var entityValidator = EntityValidatorLocator.CreateValidator();
            var isValid         = entityValidator.IsValid(entity);

            if (!isValid)
            {
                return(new EntityResult <T>(entityValidator, entity, false));
            }

            using (var transaction = repository.BeginTransaction())
            {
                repository.Add(entity);
                transaction.Commit();
            }
            return(new EntityResult <T>(entityValidator, entity, true));
        }