C# Mongo 数据库驱动程序 - 方法调用的表达式不起作用

C# Mongo DB driver - expression with method call not working

我正在尝试查询一些数据并通过发送表达式(C# mongo 驱动程序版本 2.7.3)投影到属性较少的 class。 我试图理解为什么特定表达式失败。 失败极大地限制了用户编写通用投影,并迫使他在每次调用中都以内联方式编写投影。 这是一个简化的例子:

private IMongoCollection<MyOriginalClass> _collection;

class MyOriginalClass // imagine this class has many more properties
{
  public int ID { get; set; }
}

class MyProjectedClass
{
  public int ID { get; set; }
}

void DoWork()
{
  var data1 = GetData(lib => new MyProjectedClass { ID = lib.ID }); // succeeds
  var data2 = GetData(lib => ToProjected(lib)); // Fails in mongo driver: Index was out of range. Must be non-negative and less than the size of the collection.Parameter name: index
}

IEnumerable<MyProjectedClass> GetData(Expression<Func<MyOriginalClass, MyProjectedClass>> projection)
{       
  return _collection
      .Aggregate()
      .Project(Builders<MyOriginalClass>.Projection.Expression(projection))
      .ToList();
}

MyProjectedClass ToProjected(MyOriginalClass orig)
{
    return new MyProjectedClass {ID = orig.ID};
}

第一次(成功)使用是一个表达式,mongo 驱动程序可以在运行时查看它以了解 ID = lib.ID。具体这里是NewExpression.

例如Visual Studio 允许在调试器下进行表达式可视化,对于第一个它显示:

.Lambda #Lambda1<System.Func`2[ConsoleApp1.Program+MyOriginalClass,ConsoleApp1.Program+MyProjectedClass]>(ConsoleApp1.Program+MyOriginalClass $lib)
{
    .New ConsoleApp1.Program+MyProjectedClass(){
        ID = $lib.ID
    }
}

第二次(失败)使用是一个仅调用 ToProjected 的表达式,ToProjected 正在编译到 IL 中,并且在运行时 mongo 驱动程序无法检索 ID = lib.ID (至少不像表达式那样简单)。具体这里是MethodCallExpression。而第二个表达式的可视化是:

.Lambda #Lambda1<System.Func`2[ConsoleApp1.Program+MyOriginalClass,ConsoleApp1.Program+MyProjectedClass]>(ConsoleApp1.Program+MyOriginalClass $lib)
{
    .Call ConsoleApp1.Program.ToProjected($lib)
}

ToProject 可以重写为:

Expression<Func<MyOriginalClass, MyProjectedClass>> ToProjected()
{
    return lib => new MyProjectedClass { ID = lib.ID };
}

并用作:

var data2 = GetData(ToProjected());