C# IMongoCollection<;T>;当我传入Func的谓词时抛出一个<;T、 布尔>;
我正在尝试对ASP.NET核心web控制器进行单元测试。下面是原始数据访问的情况:C# IMongoCollection<;T>;当我传入Func的谓词时抛出一个<;T、 布尔>;,c#,mongodb,asp.net-core,mongodb-.net-driver,C#,Mongodb,Asp.net Core,Mongodb .net Driver,我正在尝试对ASP.NET核心web控制器进行单元测试。下面是原始数据访问的情况: var-database=configuration.GetSection(“MongoDb:database”).Value; var mongoSettings=new MongoCollectionSettings(){AssignIdOnInsert=true}; var users=client.GetDatabase(database.GetCollection(“用户”,mongoSettings)
var-database=configuration.GetSection(“MongoDb:database”).Value;
var mongoSettings=new MongoCollectionSettings(){AssignIdOnInsert=true};
var users=client.GetDatabase(database.GetCollection(“用户”,mongoSettings);
var user=users.Find(u=>u.EmailAddress==EmailAddress).SingleOrDefault();
这个很好用。它不容易进行单元测试(Find
不能用Moq进行模拟),我更喜欢一层间接层而不是数据访问,所以我尝试重构成一个存储库类,如下所示:
公共接口IRepository
{
T SingleOrDefault(Func谓词);
}
公共类MongoRepository:IRepository
{
// ...
公共T SingleOrDefault(Func谓词)
{
var objects=client.GetDatabase(this.databaseName).GetCollection(this.repositoryName,this.settings);
var toReturn=objects.Find(o=>predicate(o)==true);
回归回归;
}
}
当我将控制器更新为使用MongoRepository
时,它会抛出:
var usersRepo=newmongorepository(this.configuration,this.client);
var user=usersRepo.SingleOrDefault(u=>u.EmailAddress==EmailAddress);
具体地说,在存储库代码中,objects.Find(o=>predicate(o)==true)
引发异常:MongoDB.Driver.dll中发生了类型为“System.InvalidOperationException”的异常,但未在用户代码中处理:“不支持调用(值(System.Func
2[AutoDungeons.Web.Models.user,System.Boolean]),{document。”`
我不知道如何解决这个问题。我怀疑谓词Func
的定义不正确,因为如果我只调用objects.Find(o=>true)
,它将返回第一个对象,而不会出现任何问题
下面是完整的异常堆栈
An exception of type 'System.InvalidOperationException' occurred in MongoDB.Driver.dll but was not handled in user code: 'Invoke(value(System.Func`2[AutoDungeoners.Web.Models.User,System.Boolean]), {document}) is not supported.'
at MongoDB.Driver.Linq.Translators.PredicateTranslator.GetFieldExpression(Expression expression)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.TranslateComparison(Expression variableExpression, ExpressionType operatorType, ConstantExpression constantExpression)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.TranslateComparison(BinaryExpression binaryExpression)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate[TDocument](Expression`1 predicate, IBsonSerializer`1 parameterSerializer, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Driver.ExpressionFilterDefinition`1.Render(IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Driver.MongoCollectionImpl`1.CreateFindOperation[TProjection](FilterDefinition`1 filter, FindOptions`2 options)
at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass41_0`1.<FindSync>b__0(IClientSessionHandle session)
at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
at MongoDB.Driver.FindFluent`2.ToCursor(CancellationToken cancellationToken)
at MongoDB.Driver.IAsyncCursorSourceExtensions.SingleOrDefault[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)
at MongoDB.Driver.IFindFluentExtensions.SingleOrDefault[TDocument,TProjection](IFindFluent`2 find, CancellationToken cancellationToken)
MongoDB.Driver.dll中发生类型为“System.InvalidOperationException”的异常,但未在用户代码中处理:“不支持调用(值(System.Func`2[AutoDungeons.Web.Models.user,System.Boolean]),{document}。”
位于MongoDB.Driver.Linq.Translators.PredicateTranslator.GetFieldExpression(表达式)
在MongoDB.Driver.Linq.Translators.PredicateTranslator.TranslateComparison(表达式变量表达式,表达式类型运算符类型,常量表达式)
位于MongoDB.Driver.Linq.Translators.PredicateTranslator.TranslateComparison(二进制表达式二进制表达式)
位于MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(表达式节点)
位于MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(表达式节点,IBMSOnSerializerRegistry serializerRegistry)
在MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate[TDocument](表达式`1谓词,IBMONSerializer`1参数序列化器,IBMONSerializerRegistry serializerRegistry)
位于MongoDB.Driver.ExpressionFilterDefinition`1.Render(IBMOSonSerializer`1 documentSerializer,IBMOSonSerializerRegistry serializerRegistry)
在MongoDB.Driver.MongoCollectionImpl`1.CreateFindOperation[Tproject](过滤器定义`1过滤器,FindOperations`2选项)
在MongoDB.Driver.MongoCollectionImpl`1.FindSync[tProject](IClientSessionHandle会话,FilterDefinition`1筛选器,FindOptions`2选项,CancellationToken CancellationToken)
在MongoDB.Driver.MongoCollectionImpl`1.c__显示Class41_0`1.b__0(IClientSessionHandle会话)
在MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 Func,CancellationToken CancellationToken)
在MongoDB.Driver.MongoCollectionImpl`1.FindSync[tProject](FilterDefinition`1过滤器,FindOptions`2选项,CancellationToken CancellationToken)
在MongoDB.Driver.FindFluent`2.ToCursor(CancellationToken CancellationToken)
在MongoDB.Driver.IAsyncCursorSourceExtensions.SingleOrDefault[TDocument](IAsyncCursorSource`1 source,CancellationToken CancellationToken)
在MongoDB.Driver.IFindFluentExtensions.SingleOrDefault[TDocument,tProject](IFindFluent`2查找,取消令牌取消令牌)
这里可以使用的查找(…)
方法的唯一实现是:
请记住,这只适用于那些可以翻译成MongoDB查询语言的表达式
u=>u.EmailAddress==EmailAddress
看起来不错。EmailAddress的类型是什么?出于好奇,如果您尝试简化为var toReturn=objects.Find(predicate).SingleOrDefault()代码>我不知道它是如何生成查询的,但我想知道它是否不喜欢您调用谓词而不仅仅是作为参数提供它。@ScottannenEmailAddress
只是一个字符串。我认为objects.Find(predicate)
无法编译,因为它试图将System.Something.Expression>
转换为Func
。在传入Func
之前,如何将其转换为表达式@这导致了同样的例外。你的解释是有道理的。除了必须传入Func
而不是谓词的问题之外,此代码不编译-谓词(o)
不适用于Func
。另外,请参见上面Scott的评论:转换为表达式
会引发相同的异常。@nightblade9这是我的错,对不起-不要运行谓词,只传递表达式即可。修改了我的答案哇,真的行了!我有点惊讶(我根据注释做了类似的事情——只是在内部将Func
转换为Expression
,然后抛出)。非常感谢!
public static IFindFluent<TDocument, TDocument> Find<TDocument>(this IMongoCollection<TDocument> collection, Expression<Func<TDocument, bool>> filter, FindOptions options = null)
public T SingleOrDefault(Expression<Func<T, bool>> predicate)
{
var objects = client.GetDatabase(this.databaseName).GetCollection<T>(this.repositoryName, this.settings);
var toReturn = objects.Find(predicate).SingleOrDefault();
return toReturn;
}