我有一个 MongoDB 数据库,其中包含一些集合,每个集合都存储特定类型的对象。我正在尝试实现一个通用选择函数,以根据类型对特定集合进行操作,如以下定义:
object[] Select<T>(Func<T, bool> condition)
例如,如果其中一个对象类型是 Person
类,我将实现以下内容:
object[] Select<T>(Func<T, bool> condition)
{
if (typeof(T) == typeof(Person))
{
Func<Person, bool> f = (Person p) =>
{
return true;
};
return this.collectionPersons.AsQueryable().Where(p=>f(p)).ToArray();
}
else // ...
}
这段代码可以编译,但是当我尝试运行它时,我得到一个 System.ArgumentException
Additional information: Unsupported filter:
Invoke(value(System.Func`2[Person,System.Boolean]), {document}).
在仔细阅读 API 文档后,我的印象是通常不可能使用抽象类型的 lambda 表达式(如上例),但只能使用
FilterDefinitionBuilder
比如Gt()
, Eq()
等。
我很好奇我是否理解正确,或者是否存在使用抽象谓词查询集合的可能性(我对 MongoDB C# 驱动程序还很陌生)。
最佳答案
当然,您可以使用 Lambda 表达式作为参数。驱动程序会将您的表达式转化为简单的过滤器,不可能翻译每个表达式,但如果可能的话,它会起作用。 我真的不明白你在样本中做了什么,你没有使用你的条件
您的函数不应采用 Func 而应采用 Expression 作为参数:
public static T[] Select<T>(IMongoCollection<T> collection,
Expression<Func<T, bool>> condition)
{
if (typeof(T) == typeof(Person))
{
return collection.AsQueryable().Where(condition).ToArray();
}
return null;
}
你可以用表达式来调用它:
var res = Select(this.collectionPersons, x => x.FirstName == "a3");
如果你只想查询所有项目,就像它看起来那样,你可以这样做:
return this.collectionPersons.Find(p=>true).ToArray();
而且您必须在 usings 中提及所有命名空间:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Linq;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
关于c# - 带有 C# : finding elements with custom predicate 的 MongoDB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42031543/