【问题标题】:Is there a way to use AutoMapper for mongo c# projection expression when using aggregate()?有没有办法在使用聚合()时将 AutoMapper 用于 mongo c# 投影表达式?
【发布时间】:2021-09-02 02:11:18
【问题描述】:

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

而不是手动为投影进行映射

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

我想用 AutoMapper 来做映射

var projection = Builders<Model>.Projection.Expression(x => _mapper.Map<ViewModel>(x));

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

var result = mongoCollection
   .Find(Builders<Model>.Filter.Empty)
   .Project(projection)
   .ToList();

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

var result = mongoCollection
   .Aggregate()
   .Project(projection)
   .ToList();

它正在抛出 ArgumentOutOfRangeException

发生异常:CLR/System.ArgumentOutOfRangeException 抛出异常:'System.ArgumentOutOfRangeException' in System.Private.CoreLib.dll:'索引超出范围。一定是 非负数且小于集合的大小。'

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

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

【问题讨论】:

  • 您可以尝试使用 ProjectTo 生成的表达式,但就 AM 而言,这不是一个受支持的方案,所以您是您自己的一个。
  • @LucianBargaoanu 不幸的是 IAggregateFluent 不支持 ProjectTo()。
  • 显然 :) 但是检查the execution plan
  • 哦,我明白了,但我担心这超出了我的表达能力……你能给我举个例子,如何或在哪里连接它?
  • 实际上我可以像这样运行一些尴尬的东西,但这会引发同样的异常。 var projection = Builders.Projection.Expression(x => _mapper.ProjectTo(Enumerable.Repeat(x, 1).AsQueryable(), null).Expression);

标签: c# mongodb automapper


【解决方案1】:

也许派对有点晚了,但我设法融入了它。 var projection = Builders&lt;Model&gt;.Projection.Expression(x =&gt; _mapper.Map&lt;ViewModel&gt;(x)); 的问题在于它是客户端投影。

为了将 automapper 用于服务器端投影,必须将 automapper 生成的 IQueryable&lt;T&gt; 转换回 IMongoQueryable&lt;T&gt;

我的扩展方法:

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>;
}

用法:

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
  • 2011-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多