示例#1
0
        private async Task DeleteAsyncCore(
            [NotNull] TDbContext db,
            [NotNull] TSession session,
            [NotNull, ItemNotNull] IReadOnlyCollection <TDbModel> dbModels,
            [NotNull, ItemNotNull] IEnumerable <TModel> models,
            [NotNull] BenchmarkSection benchmarks)
        {
            if (db == null)
            {
                throw new ArgumentNullException(nameof(db));
            }
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (dbModels == null)
            {
                throw new ArgumentNullException(nameof(dbModels));
            }
            if (models == null)
            {
                throw new ArgumentNullException(nameof(models));
            }

            if (dbModels.Count == 0)
            {
                return;
            }

            using (var benchmarkSection = benchmarks.CreateSection(nameof(DeleteAsyncCore)))
            {
                using (benchmarkSection.CreateBenchmark("Permission check"))
                {
                    var deniedErrors = models
                                       .Where(model => !PermissionResolverHelper.CanAccessRecord(session.PermissionResolver, AccessType.Delete, model))
                                       .Select(model => TranslateApiError(new ApiForbiddenNoRightsError(string.Format(Resources.ServiceCrudNode_Delete,
                                                                                                                      typeof(TModel).Name))))
                                       .ToArray();

                    if (deniedErrors.Any())
                    {
                        throw new ApiErrorException(deniedErrors);
                    }
                }

                using (benchmarkSection.CreateBenchmark("DeleteDbModel"))
                {
                    foreach (var dbModel in dbModels)
                    {
                        // ReSharper disable once SuspiciousTypeConversion.Global
                        if (dbModel is IOptimisticLockable lockableDbModel)
                        {
                            db.Entry(dbModel).OriginalValues[nameof(IOptimisticLockable.SysStartTime)] = lockableDbModel.SysStartTime;
                        }

                        await DeleteDbModel(db, session, dbModel);
                    }
                }
            }
        }
示例#2
0
        /// <inheritdoc />
        public async Task <TModel> InternalCreateAsync(
            TDbContext db,
            TSession session,
            TState state,
            TModel model,
            BenchmarkSection benchmarks)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            using (var benchmarkSection = benchmarks.CreateSection($"{nameof(InternalCreateAsync)}<{typeof(TModel).Name}>"))
            {
                using (benchmarkSection.CreateBenchmark("Permission check"))
                {
                    if (!PermissionResolverHelper.CanAccessRecord(session.PermissionResolver, AccessType.Create, model))
                    {
                        throw new ApiErrorException(TranslateApiError(new ApiForbiddenNoRightsError(
                                                                          string.Format(Resources.ServiceCrudNode_Create, typeof(TModel).Name))));
                    }
                }

                TDbModel dbModel;
                using (benchmarkSection.CreateBenchmark("CreateDbModel"))
                {
                    dbModel = await CreateDbModel(db, session, model);
                }

                using (benchmarkSection.CreateBenchmark("SaveChangesAsync"))
                {
                    try
                    {
                        await db.SaveChangesAsync(state);
                    }
                    catch (DbUpdateException e)
                    {
                        throw TranslateDbUpdateExceptionCore(e);
                    }
#if !NET_CORE
                    catch (DbEntityValidationException e)
                    {
                        throw TranslateDbEntityValidationException(e);
                    }
#endif
                }

                using (benchmarkSection.CreateBenchmark("InternalGetByIdAsync"))
                {
                    model = (await InternalGetByIdAsync(db, session, dbModel.Id, false, false, benchmarkSection))
                            ?? throw new Exception($"Could not find element by id after creation (Entity = {typeof(TModel).Name}, Id = {dbModel.Id}).");
                }

                return(model);
            }
        }
示例#3
0
        /// <inheritdoc />
        public async Task <QueryResult <TModel> > InternalGetAsync(
            TDbContext db,
            TSession session,
            QueryInfo queryInfo         = null,
            BenchmarkSection benchmarks = null)
        {
            var dbSet       = GetDbSet(db).AsNoTracking();
            var dbDataQuery = FilterDbModelCollection(dbSet);

            BuiltQuery <TDbMetaData> builtResultsQuery;

            if (QueryOnMetaData)
            {
                builtResultsQuery = SelectDbMetaData(db, session, dbDataQuery
                                                     .BuildSecuredQuery(session.PermissionResolver))
                                    .BuildUnsecuredDbQuery <TDbMetaData, TModel>(queryInfo);
            }
            else
            {
                var builtQuery = dbDataQuery.BuildDbQuery <TDbModel, TModel>(queryInfo, session.PermissionResolver);
                builtResultsQuery = new BuiltQuery <TDbMetaData>(
                    SelectDbMetaData(db, session, builtQuery.Query),
                    SelectDbMetaData(db, session, builtQuery.PagedQuery),
                    builtQuery.PageSize);
            }

            var queryResult = await builtResultsQuery.ExecuteAsync(session.Benchmarks, x => x.ToArrayAsync(), x => x.LongCountAsync());

            TModel[] models;
            using (session.Benchmarks.CreateBenchmark("Map models"))
            {
                models = queryResult.Data
                         .Select(x =>
                {
                    var model = DbModelToModel(x);
                    model.AttachService(Service, session);
                    return(model);
                })
                         .ToArray();
            }

            return(new QueryResult <TModel>(models, queryResult.RecordCount, queryResult.PageCount));
        }
示例#4
0
 /// <summary>
 /// Execute the query.
 /// Will fail if called on in-memory-queries.
 /// </summary>
 /// <typeparam name="TModel">The record type.</typeparam>
 /// <param name="query">The query to execute. Must not be null.</param>
 /// <param name="benchmarks">A benchmark section. Can be null.</param>
 /// <returns>A query result.</returns>
 public static Task<QueryResult<TModel>> ExecuteAsync<TModel>(this BuiltQuery<TModel> query, BenchmarkSection benchmarks)
     where TModel : class
     => query.ExecuteAsync(benchmarks, x => x.ToArrayAsync(), x => x.LongCountAsync());
示例#5
0
        /// <inheritdoc />
        public async Task InternalBatchDeleteAsync(
            TDbContext db,
            TSession session,
            TState state,
            TId[] ids,
            BenchmarkSection benchmarks)
        {
            if (db == null)
            {
                throw new ArgumentNullException(nameof(db));
            }
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }
            if (ids == null)
            {
                throw new ArgumentNullException(nameof(ids));
            }
            if (ids.Length == 0)
            {
                return;
            }

            using (var benchmarkSection = benchmarks.CreateSection($"{nameof(InternalDeleteAsync)}<{typeof(TModel).Name}>"))
            {
                var currentDbModels = new TDbModel[ids.Length];
                var currentModels   = new TModel[ids.Length];
                using (benchmarkSection.CreateBenchmark("Query Current Models"))
                {
                    var dbModelQuery = FilterDbModelCollection(GetDbSet(db))
                                       .Where(d => ids.Contains(d.Id));
                    var dbMetaDataQuery = SelectDbMetaData(db, session, dbModelQuery);

                    var currentModelDataById = await dbModelQuery
                                               .Join(dbMetaDataQuery,
                                                     dbModel => dbModel.Id,
                                                     dbModelMetaData => dbModelMetaData.Id,
                                                     (dbModel, dbModelMetaData) => new
                    {
                        DbModel         = dbModel,
                        DbModelMetaData = dbModelMetaData
                    })
                                               .ToDictionaryAsync(x => x.DbModel.Id);

                    if (ids.Length != currentModelDataById.Count)
                    {
                        throw new ApiErrorException(ids
                                                    .Where(id => !currentModelDataById.ContainsKey(id))
                                                    .Select(id => TranslateApiError(ApiNotFoundError.Create(typeof(TModel).Name, id)))
                                                    .ToArray());
                    }

                    var index = 0;
                    foreach (var currentModelData in currentModelDataById.Values)
                    {
                        currentDbModels[index] = currentModelData.DbModel;
                        var model = DbModelToModel(currentModelData.DbModelMetaData);
                        model.AttachService(Service, session);
                        currentModels[index] = model;
                        ++index;
                    }
                }

                await DeleteAsyncCore(
                    db,
                    session,
                    currentDbModels,
                    currentModels,
                    benchmarkSection);

                using (benchmarkSection.CreateBenchmark("SaveChangesAsync"))
                {
                    try
                    {
                        await db.SaveChangesAsync(state);
                    }
                    catch (DbUpdateConcurrencyException)
                    {
                        throw new ApiErrorException(new ApiOptimisticLockingError <TModel>(
                                                        string.Format(Resources.ServiceCrudNode_OptimisticLocking, typeof(TModel).Name)));
                    }
                    catch (DbUpdateException e)
                    {
                        throw TranslateDbUpdateExceptionCore(e);
                    }
#if !NET_CORE
                    catch (DbEntityValidationException e)
                    {
                        throw TranslateDbEntityValidationException(e);
                    }
#endif
                }
            }
        }
示例#6
0
        /// <inheritdoc />
        public async Task InternalDeleteAsync(
            TDbContext db,
            TSession session,
            TState state,
            TId id,
            BenchmarkSection benchmarks)
        {
            using (var benchmarkSection = benchmarks.CreateSection($"{nameof(InternalDeleteAsync)}<{typeof(TModel).Name}>"))
            {
                TDbModel currentDbModel;
                TModel   currentModel;
                using (benchmarkSection.CreateBenchmark("Query Current Models"))
                {
                    var whereExpressionParam = Expression.Parameter(typeof(TDbModel), "x");
                    var whereExpressionBody  = Expression.Equal(Expression.Property(whereExpressionParam, nameof(IId <TId> .Id)), Expression.Constant(id, typeof(TId)));

                    var dbModelQuery = FilterDbModelCollection(GetDbSet(db))
                                       .Where(Expression.Lambda <Func <TDbModel, bool> >(whereExpressionBody, whereExpressionParam));
                    var dbMetaDataQuery = SelectDbMetaData(db, session, dbModelQuery);

                    var currentModelData = (await dbModelQuery
                                            .Join(dbMetaDataQuery,
                                                  dbModel => dbModel.Id,
                                                  dbModelMetaData => dbModelMetaData.Id,
                                                  (dbModel, dbModelMetaData) => new
                    {
                        DbModel = dbModel,
                        DbModelMetaData = dbModelMetaData
                    })
                                            .SingleOrDefaultAsync())
                                           ?? throw new ApiErrorException(TranslateApiError(ApiNotFoundError.Create(typeof(TModel).Name, id)));

                    currentDbModel = currentModelData.DbModel;
                    currentModel   = DbModelToModel(currentModelData.DbModelMetaData);
                    currentModel.AttachService(Service, session);
                }

                await DeleteAsyncCore(
                    db,
                    session,
                    new[] { currentDbModel },
                    new[] { currentModel },
                    benchmarkSection);

                using (benchmarkSection.CreateBenchmark("SaveChangesAsync"))
                {
                    try
                    {
                        await db.SaveChangesAsync(state);
                    }
                    catch (DbUpdateConcurrencyException)
                    {
                        throw new ApiErrorException(
                                  new ApiOptimisticLockingError <TModel>(string.Format(Resources.ServiceCrudNode_OptimisticLocking,
                                                                                       typeof(TModel).Name)));
                    }
                    catch (DbUpdateException e)
                    {
                        throw TranslateDbUpdateExceptionCore(e);
                    }
#if !NET_CORE
                    catch (DbEntityValidationException e)
                    {
                        throw TranslateDbEntityValidationException(e);
                    }
#endif
                }
            }
        }
示例#7
0
        /// <inheritdoc />
        public async Task <TModel[]> InternalBatchUpdateAsync(
            TDbContext db,
            TSession session,
            TState state,
            TModel[] models,
            Func <string, bool>[] updatedProperties,
            BenchmarkSection benchmarks)
        {
            if (models == null || models.Any(model => model == null))
            {
                throw new ArgumentNullException(nameof(models));
            }
            if (updatedProperties == null)
            {
                throw new ArgumentNullException(nameof(updatedProperties));
            }
            if (models.GroupBy(model => model.Id).Any(group => group.Count() != 1))
            {
                throw new InvalidOperationException("Cannot update the same element twice in one batch.");
            }

            if (models.Length == 0)
            {
                return(new TModel[0]);
            }

            using (var benchmarkSection = benchmarks.CreateSection($"{nameof(InternalBatchUpdateAsync)}<{typeof(TModel).Name}>"))
            {
                var mapping = models
                              .Select((model, idx) => new
                {
                    Idx = idx,
                    model.Id
                })
                              .ToDictionary(x => x.Id, x => x.Idx);

                var ids = mapping.Keys.ToArray();

                var currentDbModels = new TDbModel[ids.Length];
                var currentModels   = new TModel[ids.Length];
                using (benchmarkSection.CreateBenchmark("Query Current Models"))
                {
                    var dbModelQuery = FilterDbModelCollection(GetDbSet(db))
                                       .Where(d => ids.Contains(d.Id));
                    var dbMetaDataQuery = SelectDbMetaData(db, session, dbModelQuery);

                    var currentModelDataById = await dbModelQuery
                                               .Join(dbMetaDataQuery,
                                                     dbModel => dbModel.Id,
                                                     dbModelMetaData => dbModelMetaData.Id,
                                                     (dbModel, dbModelMetaData) => new
                    {
                        DbModel         = dbModel,
                        DbModelMetaData = dbModelMetaData
                    })
                                               .ToDictionaryAsync(x => x.DbModel.Id);

                    if (ids.Length != currentModelDataById.Count)
                    {
                        throw new ApiErrorException(ids
                                                    .Where(id => !currentModelDataById.ContainsKey(id))
                                                    .Select(id => TranslateApiError(ApiNotFoundError.Create(typeof(TModel).Name, id)))
                                                    .ToArray());
                    }

                    foreach (var currentModelData in currentModelDataById.Values)
                    {
                        if (!mapping.TryGetValue(currentModelData.DbModel.Id, out var index))
                        {
                            continue;
                        }

                        currentDbModels[index] = currentModelData.DbModel;
                        var model = DbModelToModel(currentModelData.DbModelMetaData);
                        model.AttachService(Service, session);
                        currentModels[index] = model;
                    }
                }

                using (benchmarkSection.CreateBenchmark("Permission check"))
                {
                    if (currentModels.Any(currentModel => !PermissionResolverHelper.CanAccessRecord(session.PermissionResolver, AccessType.Update, currentModel)))
                    {
                        throw new ApiErrorException(TranslateApiError(new ApiForbiddenNoRightsError(
                                                                          string.Format(Resources.ServiceCrudNode_Update, typeof(TModel).Name))));
                    }
                }

                using (benchmarkSection.CreateBenchmark("UpdateDbModel"))
                {
                    for (var i = 0; i < currentModels.Length; i++)
                    {
                        var model = models[i];
                        var updatedPropertiesSingle = updatedProperties[i];
                        var currentDbModel          = currentDbModels[i];

                        var updatedDbModel = await UpdateDbModel(db, session, currentDbModel, model, updatedPropertiesSingle);

                        // ReSharper disable once SuspiciousTypeConversion.Global
                        if (updatedDbModel is IOptimisticLockable lockableDbModel)
                        {
                            db.Entry(updatedDbModel).OriginalValues[nameof(IOptimisticLockable.SysStartTime)] = lockableDbModel.SysStartTime;
                        }
                    }
                }

                using (benchmarkSection.CreateBenchmark("SaveChangesAsync"))
                {
                    try
                    {
                        await db.SaveChangesAsync(state);
                    }
                    catch (DbUpdateConcurrencyException)
                    {
                        throw new ApiErrorException(
                                  new ApiOptimisticLockingError <TModel>(string.Format(Resources.ServiceCrudNode_OptimisticLocking,
                                                                                       typeof(TModel).Name)));
                    }
                    catch (DbUpdateException e)
                    {
                        throw TranslateDbUpdateExceptionCore(e);
                    }
#if !NET_CORE
                    catch (DbEntityValidationException e)
                    {
                        throw TranslateDbEntityValidationException(e);
                    }
#endif
                }

                using (benchmarkSection.CreateBenchmark("InternalGetByIdsAsync"))
                {
                    models = await InternalGetByIdsAsync(db, session, ids, false, false, benchmarkSection);

                    if (models.Any(m => m == null))
                    {
                        throw new Exception($"Could not find element by id after batch update (Entity = {typeof(TModel).Name}).");
                    }
                }

                return(models);
            }
        }
示例#8
0
        /// <inheritdoc />
        public async Task <TModel> InternalUpdateAsync(
            TDbContext db,
            TSession session,
            TState state,
            TModel model,
            Func <string, bool> updatedProperties,
            BenchmarkSection benchmarks)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            using (var benchmarkSection = benchmarks.CreateSection($"{nameof(InternalUpdateAsync)}<{typeof(TModel).Name}>"))
            {
                var id = model.Id;

                TDbModel currentDbModel;
                TModel   currentModel;
                using (benchmarkSection.CreateBenchmark("Query Current Models"))
                {
                    var whereExpressionParam = Expression.Parameter(typeof(TDbModel), "x");
                    var whereExpressionBody  = Expression.Equal(Expression.Property(whereExpressionParam, nameof(IId <TId> .Id)), Expression.Constant(id, typeof(TId)));

                    var dbModelQuery = FilterForDirectReadDbModelCollection(GetDbSet(db))
                                       .Where(Expression.Lambda <Func <TDbModel, bool> >(whereExpressionBody, whereExpressionParam));
                    var dbMetaDataQuery = SelectDbMetaData(db, session, dbModelQuery);

                    var currentModelData = (await dbModelQuery
                                            .Join(dbMetaDataQuery,
                                                  dbModel => dbModel.Id,
                                                  dbModelMetaData => dbModelMetaData.Id,
                                                  (dbModel, dbModelMetaData) => new
                    {
                        DbModel = dbModel,
                        DbModelMetaData = dbModelMetaData
                    })
                                            .SingleOrDefaultAsync())
                                           ?? throw new ApiErrorException(TranslateApiError(ApiNotFoundError.Create(typeof(TModel).Name, model.Id)));

                    currentDbModel = currentModelData.DbModel;
                    currentModel   = DbModelToModel(currentModelData.DbModelMetaData);
                    currentModel.AttachService(Service, session);
                }

                using (benchmarkSection.CreateBenchmark("Permission check"))
                {
                    if (!PermissionResolverHelper.CanAccessRecord(session.PermissionResolver, AccessType.Update, currentModel))
                    {
                        throw new ApiErrorException(
                                  TranslateApiError(new ApiForbiddenNoRightsError(string.Format(Resources.ServiceCrudNode_Update,
                                                                                                typeof(TModel).Name))));
                    }
                }

                using (benchmarkSection.CreateBenchmark("UpdateDbModel"))
                {
                    var updatedDbModel = await UpdateDbModel(db, session, currentDbModel, model, updatedProperties);

                    // ReSharper disable once SuspiciousTypeConversion.Global
                    if (updatedDbModel is IOptimisticLockable lockableDbModel)
                    {
                        db.Entry(updatedDbModel).OriginalValues[nameof(IOptimisticLockable.SysStartTime)] = lockableDbModel.SysStartTime;
                    }
                }

                using (benchmarkSection.CreateBenchmark("SaveChangesAsync"))
                {
                    try
                    {
                        await db.SaveChangesAsync(state);
                    }
                    catch (DbUpdateConcurrencyException)
                    {
                        throw new ApiErrorException(new ApiOptimisticLockingError <TModel>(
                                                        string.Format(Resources.ServiceCrudNode_OptimisticLocking, typeof(TModel).Name)));
                    }
                    catch (DbUpdateException e)
                    {
                        throw TranslateDbUpdateExceptionCore(e);
                    }
#if !NET_CORE
                    catch (DbEntityValidationException e)
                    {
                        throw TranslateDbEntityValidationException(e);
                    }
#endif
                }

                using (benchmarkSection.CreateBenchmark("InternalGetByIdAsync"))
                {
                    model = (await InternalGetByIdAsync(db, session, id, false, false, benchmarkSection))
                            ?? throw new Exception($"Could not find element by id after update (Entity = {typeof(TModel).Name}, Id = {id}).");
                }

                return(model);
            }
        }
示例#9
0
        /// <inheritdoc />
        public async Task <TModel[]> InternalBatchCreateAsync(
            TDbContext db,
            TSession session,
            TState state,
            TModel[] models,
            BenchmarkSection benchmarks)
        {
            if (models == null)
            {
                throw new ArgumentNullException(nameof(models));
            }

            using (var benchmarkSection = benchmarks.CreateSection($"{nameof(InternalBatchCreateAsync)}<{typeof(TModel).Name}>"))
            {
                using (benchmarkSection.CreateBenchmark("Permission check"))
                {
                    if (models.Any(model => !PermissionResolverHelper.CanAccessRecord(session.PermissionResolver, AccessType.Create, model)))
                    {
                        throw new ApiErrorException(TranslateApiError(new ApiForbiddenNoRightsError(
                                                                          string.Format(Resources.ServiceCrudNode_Create, typeof(TModel).Name))));
                    }
                }

                TDbModel[] dbModels;
                using (benchmarkSection.CreateBenchmark("CreateDbModel"))
                {
                    dbModels = new TDbModel[models.Length];
                    for (var i = 0; i < models.Length; i++)
                    {
                        dbModels[i] = await CreateDbModel(db, session, models[i]);
                    }
                }

                const int batchSize = 500;

                using (benchmarkSection.CreateBenchmark("AddRange,SaveChangesAsync"))
                {
                    var batchCount = dbModels.Length / batchSize + ((dbModels.Length % batchSize) == 0 ? 0 : 1);
                    for (var i = 0; i < batchCount; i++)
                    {
                        GetDbSet(db).AddRange(dbModels.Skip(batchSize * i).Take(batchSize));

                        try
                        {
                            await db.SaveChangesAsync(state);
                        }
                        catch (DbUpdateException e)
                        {
                            throw TranslateDbUpdateExceptionCore(e);
                        }
#if !NET_CORE
                        catch (DbEntityValidationException e)
                        {
                            throw TranslateDbEntityValidationException(e);
                        }
#endif
                    }
                }

                using (benchmarkSection.CreateBenchmark("InternalGetByIdsAsync"))
                {
                    models = await InternalGetByIdsAsync(db, session, dbModels.Select(dbModel => dbModel.Id).ToArray(), false, false, benchmarkSection);

                    if (models.Any(m => m == null))
                    {
                        throw new Exception($"Could not find element by id after batch creation (Entity = {typeof(TModel).Name}).");
                    }
                }

                return(models);
            }
        }
示例#10
0
        /// <inheritdoc />
        public async Task <TModel[]> InternalGetByIdsAsync(
            TDbContext db,
            TSession session,
            TId[] ids,
            bool tryCache               = true,
            bool addToCache             = true,
            BenchmarkSection benchmarks = null)
        {
            async Task <TModel[]> DbTask(TId[] idParam)
            {
                var mapping = idParam
                              .Select((id, idx) => new
                {
                    Idx = idx,
                    Id  = id
                })
                              .GroupBy(x => x.Id)
                              .ToDictionary(x => x.Key, x => x.Select(_ => _.Idx).ToArray());
                var queryIds = mapping.Keys.ToArray();

                var dbSet       = GetDbSet(db).AsNoTracking();
                var dbDataQuery = FilterForDirectReadDbModelCollection(dbSet);

                dbDataQuery = dbDataQuery.Where(d => queryIds.Contains(d.Id));
                var dataMetaDataQuery = SelectDbMetaData(db, session, dbDataQuery);

                var dbResults = await dataMetaDataQuery.ToArrayAsync();

                var taskModels = new TModel[idParam.Length];

                foreach (var dbResult in dbResults)
                {
                    if (!mapping.TryGetValue(dbResult.Id, out var indices))
                    {
                        continue;
                    }

                    var model = DbModelToModel(dbResult);

                    foreach (var idx in indices)
                    {
                        taskModels[idx] = model;
                    }
                }

                return(taskModels);
            }

            TModel[] models;
            if (CacheById != null)
            {
                if (tryCache)
                {
                    models = await CacheById.GetOrAddManyAsync(ids, DbTask);
                }
                else
                {
                    models = await DbTask(ids);

                    if (addToCache)
                    {
                        await CacheById.AddOrUpdateManyAsync(models.ToDictionary(m => m.Id));
                    }
                }
            }
            else
            {
                models = await DbTask(ids);
            }

            for (var i = 0; i < models.Length; i++)
            {
                if (models[i] == null)
                {
                    continue;
                }

                models[i].AttachService(Service, session);

                if (!PermissionResolverHelper.CanAccessRecord(session.PermissionResolver, AccessType.Read, models[i]))
                {
                    models[i] = null;
                }
            }

            return(models);
        }
示例#11
0
        /// <inheritdoc />
        public async Task <TModel> InternalGetByIdAsync(
            TDbContext db,
            TSession session,
            TId id,
            bool tryCache               = true,
            bool addToCache             = true,
            BenchmarkSection benchmarks = null)
        {
            if (id == null)
            {
                return(null);
            }

            async Task <TModel> DbTask(TId idParam)
            {
                var dbSet       = GetDbSet(db).AsNoTracking();
                var dbDataQuery = FilterForDirectReadDbModelCollection(dbSet);

                var whereExpressionParam = Expression.Parameter(typeof(TDbModel), "x");
                var whereExpressionBody  = Expression.Equal(Expression.Property(whereExpressionParam, nameof(IId <TId> .Id)), Expression.Constant(idParam, typeof(TId)));

                dbDataQuery = dbDataQuery.Where(Expression.Lambda <Func <TDbModel, bool> >(whereExpressionBody, whereExpressionParam));
                var dataMetaDataQuery = SelectDbMetaData(db, session, dbDataQuery);

                var dbResult = await dataMetaDataQuery.SingleOrDefaultAsync();

                return(dbResult == null
                    ? null
                    : DbModelToModel(dbResult));
            }

            TModel model;

            if (CacheById != null)
            {
                if (tryCache)
                {
                    model = await CacheById.GetOrAddAsync(id, DbTask);
                }
                else
                {
                    model = await DbTask(id);

                    if (addToCache)
                    {
                        await CacheById.AddOrUpdateAsync(id, model);
                    }
                }
            }
            else
            {
                model = await DbTask(id);
            }

            model?.AttachService(Service, session);

            if (model != null && !PermissionResolverHelper.CanAccessRecord(session.PermissionResolver, AccessType.Read, model))
            {
                return(null);
            }

            return(model);
        }