コード例 #1
0
ファイル: RideStorage.cs プロジェクト: e5r/E5R.Architecture
        public IEnumerable <TDataModel> Search(IDataFilter <TDataModel> filter,
                                               IDataIncludes includes)
        {
            Checker.NotNullArgument(filter, nameof(filter));

            return(QuerySearch(_query, filter, includes).ToList());
        }
コード例 #2
0
ファイル: StorageBase.cs プロジェクト: e5r/E5R.Architecture
 protected IQueryable <TDataModel> TryApplyIncludes(
     IQueryable <TDataModel> query,
     IDataIncludes includes)
 {
     return(includes != null
         ? includes.Includes.Aggregate(query, (q, i) => q.Include(i))
         : query);
 }
コード例 #3
0
ファイル: StorageBase.cs プロジェクト: e5r/E5R.Architecture
        protected IQueryable <TDataModel> QueryFind(
            IEntityType entityType,
            IQueryable <TDataModel> origin,
            object[] identifiers,
            IDataIncludes includes)
        {
            Checker.NotNullArgument(origin, nameof(origin));
            Checker.NotNullArgument(entityType, nameof(entityType));
            Checker.NotNullArgument(identifiers, nameof(identifiers));

            var primaryKeys = entityType.FindPrimaryKey().Properties;

            if (identifiers.Length < 1)
            {
                // TODO: Implementar i18n/l10n
                throw new InvalidOperationException("At least one identifier must be informed.");
            }

            if (primaryKeys.Count() != identifiers.Count())
            {
                // TODO: Implementar i18n/l10n
                throw new InvalidOperationException($"Number of primary keys configured in {typeof(TDataModel)} different than expected.");
            }

            var filter = new DataFilter <TDataModel>();
            var param  = Expression.Parameter(typeof(TDataModel), "e");
            Expression <Func <TDataModel, bool> > filterExpression = null;

            foreach (var(pk, idx) in primaryKeys.Select((pk, idx) => (pk, idx)))
            {
                if (filterExpression != null)
                {
                    filterExpression = Expression.Lambda <Func <TDataModel, bool> >(
                        Expression.AndAlso(
                            filterExpression.Body,
                            Expression.Equal(
                                Expression.PropertyOrField(param, pk.Name),
                                Expression.Constant(identifiers[idx])
                                )),
                        param
                        );
                }
                else
                {
                    filterExpression = Expression.Lambda <Func <TDataModel, bool> >(
                        Expression.Equal(
                            Expression.PropertyOrField(param, pk.Name),
                            Expression.Constant(identifiers[idx])
                            ),
                        param
                        );
                }
            }

            filter.AddFilter(filterExpression);

            return(QuerySearch(origin, filter, includes));
        }
コード例 #4
0
ファイル: RideStorage.cs プロジェクト: e5r/E5R.Architecture
        public TDataModel Find(object[] identifiers, IDataIncludes includes = null)
        {
            Checker.NotNullArgument(identifiers, nameof(identifiers));

            var entityType = _dbContext.Model.FindEntityType(typeof(TDataModel));

            return(QueryFind(entityType, _query, identifiers, includes)
                   .FirstOrDefault());
        }
コード例 #5
0
ファイル: RideStorage.cs プロジェクト: e5r/E5R.Architecture
        public PaginatedResult <TDataModel> LimitedGet(IDataLimiter <TDataModel> limiter,
                                                       IDataIncludes includes)
        {
            Checker.NotNullArgument(limiter, nameof(limiter));

            var(offset, limit, total, result) = QueryPreLimitResult(_query, limiter, includes);

            return(new PaginatedResult <TDataModel>(
                       result.ToList(),
                       offset,
                       limit,
                       total
                       ));
        }
コード例 #6
0
ファイル: StorageBase.cs プロジェクト: e5r/E5R.Architecture
        protected IQueryable <TDataModel> QuerySearch(
            IQueryable <TDataModel> origin,
            IDataFilter <TDataModel> filter,
            IDataIncludes includes)
        {
            Checker.NotNullArgument(origin, nameof(origin));
            Checker.NotNullArgument(filter, nameof(filter));

            var filterExpressions = filter.GetExpressions();

            Checker.NotNullObject(filterExpressions, $"filter.{nameof(filter.GetExpressions)}()");

            var query = filterExpressions.Aggregate(origin, (q, w) => q.Where(w));

            return(TryApplyIncludes(query, includes));
        }
コード例 #7
0
ファイル: RideStorage.cs プロジェクト: e5r/E5R.Architecture
        public PaginatedResult <TDataModel> LimitedSearch(IDataFilter <TDataModel> filter,
                                                          IDataLimiter <TDataModel> limiter, IDataIncludes includes)
        {
            Checker.NotNullArgument(filter, nameof(filter));
            Checker.NotNullArgument(limiter, nameof(limiter));

            var query = QuerySearch(_query, filter, includes);

            // A projeção já foi aplicada em QuerySearch(),
            // por isso não precisa ser repassada aqui
            var(offset, limit, total, result) = QueryPreLimitResult(query, limiter, null);

            return(new PaginatedResult <TDataModel>(
                       result.ToList(),
                       offset,
                       limit,
                       total
                       ));
        }
コード例 #8
0
ファイル: RideStorage.cs プロジェクト: e5r/E5R.Architecture
 public IEnumerable <TDataModel> GetAll(IDataIncludes includes) =>
 TryApplyIncludes(_query, includes).ToList();
コード例 #9
0
ファイル: RideStorage.cs プロジェクト: e5r/E5R.Architecture
 public TDataModel GetFirst(IDataFilter <TDataModel> filter, IDataIncludes includes = null) =>
 QuerySearch(_query, filter, includes).FirstOrDefault();
コード例 #10
0
        /// <summary>
        /// Find an item stored by a data instance
        /// </summary>
        /// <param name="storage">Storage object</param>
        /// <param name="data">Data item</param>
        /// <param name="includes">Linked data to include</param>
        /// <returns>Instance of <see cref="TDataModel"/>, or null when not found</returns>
        public static TDataModel Find <TDataModel>(this IFindableStorage <TDataModel> storage, TDataModel data, IDataIncludes includes = null)
            where TDataModel : IIdentifiable
        {
            Checker.NotNullArgument(storage, nameof(storage));
            Checker.NotNullArgument(data, nameof(data));

            return(storage.Find(data.Identifiers, includes));
        }
コード例 #11
0
        /// <summary>
        /// Find an item stored by identifier
        /// </summary>
        /// <param name="storage">Storage object</param>
        /// <param name="identifier">Item identifier</param>
        /// <param name="includes">Linked data to include</param>
        /// <returns>Instance of <see cref="TDataModel"/>, or null when not found</returns>
        public static TDataModel Find <TDataModel>(this IFindableStorage <TDataModel> storage, object identifier, IDataIncludes includes = null)
            where TDataModel : IIdentifiable
        {
            Checker.NotNullArgument(storage, nameof(storage));
            Checker.NotNullArgument(identifier, nameof(identifier));

            return(storage.Find(new object[] { identifier }, includes));
        }
コード例 #12
0
ファイル: StorageBase.cs プロジェクト: e5r/E5R.Architecture
        /// <summary>
        /// Query for operations that must return an <see cref="PaginatedResult{TDataModel}" />
        /// </summary>
        /// <param name="limiter">Data limiter</param>
        /// <param name="origin">Original data query</param>
        /// <param name="includes">Data includes</param>
        /// <returns>Tuple of (offset, limit, total, result)</returns>
        protected (uint, uint, int, IQueryable <TDataModel>) QueryPreLimitResult(
            IQueryable <TDataModel> origin,
            IDataLimiter <TDataModel> limiter,
            IDataIncludes includes)
        {
            Checker.NotNullArgument(limiter, nameof(limiter));
            Checker.NotNullArgument(origin, nameof(origin));

            // Ensures offset range
            if (limiter.OffsetLimit.HasValue &&
                (limiter.OffsetLimit.Value == 0 || limiter.OffsetLimit.Value > int.MaxValue))
            {
                throw new ArgumentOutOfRangeException($"limiter.{limiter.OffsetLimit}");
            }

            var result = TryApplyIncludes(origin, includes);

            IOrderedQueryable <TDataModel> orderBy = null;

            foreach (var sorter in limiter.GetSorters())
            {
                if (orderBy == null)
                {
                    orderBy = sorter.Descending
                        ? result.OrderByDescending(sorter.Sorter)
                        : result.OrderBy(sorter.Sorter);
                }
                else
                {
                    orderBy = sorter.Descending
                        ? orderBy.ThenByDescending(sorter.Sorter)
                        : orderBy.ThenBy(sorter.Sorter);
                }
            }

            result = orderBy ?? result;

            uint offset;
            uint limit;

            var total = result.Count();

            if (limiter.OffsetBegin.HasValue)
            {
                offset = limiter.OffsetBegin.Value;
                result = result.Skip(Convert.ToInt32(offset));
            }
            else
            {
                offset = 0;
            }

            if (limiter.OffsetLimit.HasValue)
            {
                limit  = limiter.OffsetLimit.Value;
                result = result.Take(Convert.ToInt32(limit));
            }
            else
            {
                limit = Convert.ToUInt32(total);
            }

            return(offset, limit, total, result);
        }