使用aggregate()时,有没有办法将AutoMapper用于mongo c#投影表达式?

nik*_*nik 1 c# mongodb automapper

我试图避免在使用 mongo c# 驱动程序 (v2.7.2) 聚合和投影时将模型手动映射到视图模型。

而不是手动进行投影映射

var projection = Builders<Model>.Projection.Expression(x => new ViewModel { 
   A = x.A, 
   B = x.B
   // ...more properties
});
Run Code Online (Sandbox Code Playgroud)

我想使用 AutoMapper 进行映射

var projection = Builders<Model>.Projection.Expression(x => _mapper.Map<ViewModel>(x));
Run Code Online (Sandbox Code Playgroud)

事实上,当我只是在像这样的 find() 操作上使用它时,这是有效的

var result = mongoCollection
   .Find(Builders<Model>.Filter.Empty)
   .Project(projection)
   .ToList();
Run Code Online (Sandbox Code Playgroud)

但是当我在aggregate()上使用相同的投影时

var result = mongoCollection
   .Aggregate()
   .Project(projection)
   .ToList();
Run Code Online (Sandbox Code Playgroud)

它抛出一个 ArgumentOutOfRangeException

发生异常:CLR/System.ArgumentOutOfRangeException 抛出异常:System.Private.CoreLib.dll 中的“System.ArgumentOutOfRangeException”:“索引超出范围。” 必须为非负数且小于集合的大小。

首先我想知道为什么使用 AutoMapper 进行映射适用于 find() 而不适用于aggregate()?

另外,是否可以在这种情况下以某种方式使用 AutoMapper,或者是否有其他方法可以映射到目标类而无需显式反序列化结果客户端?

小智 6

也许聚会有点晚了,但我设法整合它。问题在于var projection = Builders<Model>.Projection.Expression(x => _mapper.Map<ViewModel>(x));它是客户端投影。

为了使用 automapper 进行服务器端投影,必须将IQueryable<T>automapper 生成的结果转换回IMongoQueryable<T>.

我的扩展方法:

public static class MongoDbExtensions
{
    public static IMongoQueryable<TDestination> ProjectTo<TSource, TDestination>(this IMongoQueryable<TSource> query, AutoMapper.IMapper autoMapper) =>
            query.ProjectTo<TDestination>(autoMapper.ConfigurationProvider) as IMongoQueryable<TDestination>;
}
Run Code Online (Sandbox Code Playgroud)

用法:

private readonly IMongoCollection<Book> _books;
private readonly IMapper _mapper;
// ...
_books
            .AsQueryable()
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ProjectTo<Book, BookListDTO>(_mapper)
            .ToListAsync();
Run Code Online (Sandbox Code Playgroud)