// Protected methods protected virtual async Task ProcessBatchAsync(List <BatchItem <TKey, TEntity> > batch, CancellationToken cancellationToken) { await using var dbContext = CreateDbContext(); var keys = new HashSet <TKey>(); foreach (var item in batch) { if (!item.TryCancel(cancellationToken)) { keys.Add(item.Input); } } var pEntity = Expression.Parameter(typeof(TEntity), "e"); var eKey = KeyExtractorExpressionBuilder.Invoke(pEntity); var eBody = Expression.Call(Expression.Constant(keys), ContainsMethod, eKey); var eLambda = (Expression <Func <TEntity, bool> >)Expression.Lambda(eBody, pEntity); var entities = await dbContext.Set <TEntity>() .Where(eLambda) .ToDictionaryAsync(KeyExtractor, cancellationToken) .ConfigureAwait(false); foreach (var item in batch) { entities.TryGetValue(item.Input, out var entity); item.SetResult(Result.Value(entity) !, CancellationToken.None); } }
public DbEntityResolver(Options?options, IServiceProvider services) : base(services) { options ??= new(); BatchProcessorFactory = options.BatchProcessorFactory ?? (self => new AsyncBatchProcessor <TKey, TEntity> { MaxBatchSize = 16, ConcurrencyLevel = Math.Min(HardwareInfo.ProcessorCount, 4), BatchingDelayTaskFactory = cancellationToken => Task.Delay(1, cancellationToken), BatchProcessor = self.ProcessBatch, }); _batchProcessorLazy = new Lazy <AsyncBatchProcessor <TKey, TEntity> >( () => BatchProcessorFactory.Invoke(this)); using var dbContext = CreateDbContext(); var entityType = dbContext.Model.FindEntityType(typeof(TEntity)); var key = entityType.FindPrimaryKey(); KeyExtractorExpressionBuilder = options.KeyExtractorExpressionBuilder ?? (eEntity => Expression.PropertyOrField(eEntity, key.Properties.Single().Name)); var pEntity = Expression.Parameter(typeof(TEntity), "e"); var eBody = KeyExtractorExpressionBuilder.Invoke(pEntity); KeyExtractor = (Func <TEntity, TKey>)Expression.Lambda(eBody, pEntity).Compile(); QueryTransformer = options.QueryTransformer ?? (q => q); PostProcessor = options.PostProcessor ?? (_ => {}); }