在.NET 6 Web API的MongoDB单例类中实现Linq查询函数
.NET 6 Web API中MongoReader单例类新增Linq表达式查询方法
我在.NET 6 Web API中实现了MongoReader单例类,用于查询MongoDB集合。由于应用需要查询3个不同数据库的多个集合,现有方法仅支持接收FilterDefinition<T>参数,因此希望新增支持Linq表达式的查询方法,期望调用方式为:await _reader.QueryCollectionLinqAsync<RandomClass>("DatabaseName.CollectionName", t => t.fieldName == fieldValue, limit, batchSize)
原MongoReader单例类代码
public class MongoReader { private MongoClient _client; public MongoReader(string connectionString) { ConventionPack pack = new ConventionPack(); pack.Add(new IgnoreExtraElementsConvention(true)); ConventionRegistry.Register("My Solution Conventions", pack, t => true); _client = new MongoClient(connectionString); } public async Task<List<T>> QueryCollection<T>(string collection, FilterDefinition<T> filter,int limit = 50,int batchSize = 50) where T : class { string[] collectionInformation = collection.Split('.'); string collectionName = collectionInformation[1]; string collectionDatabase = collectionInformation[0]; List<T> list = new List<T> (); FindOptions<T> findOptions = new FindOptions<T>() { Limit = limit , BatchSize = batchSize }; IAsyncCursor<T> cursor = await _client.GetDatabase(collectionDatabase).GetCollection<T>(collectionName).FindAsync(filter, findOptions); list = await cursor.ToListAsync(); return list; } }
最初非工作代码(使用Func<T,bool>参数)
使用Func<T,bool>作为Where条件参数时,无法调用ToListAsync()。原因在于Func<T,bool>是委托类型,会触发客户端内存过滤,无法被MongoDB的Linq提供器解析为数据库端执行的查询语句:
public async Task<List<T>> QueryCollection<T>(string collection, Func<T,bool> predicate, int limit = 50, int batchSize = 50) where T : class { string[] collectionInformation = collection.Split('.'); string collectionName = collectionInformation[1]; string collectionDatabase = collectionInformation[0]; List<T> list = new List<T>(); AggregateOptions options = new AggregateOptions() { BatchSize = batchSize }; return await _client.GetDatabase(collectionDatabase).GetCollection<T>(collectionName).AsQueryable(options).Where(predicate).Take(limit).ToListAsync(); }
最终工作代码(改用Expression<Func<T,bool>>参数)
将参数类型改为Expression<Func<T,bool>>后问题解决,因为表达式树可以被MongoDB的Linq提供器解析为对应的MongoDB查询语句,在数据库端完成过滤操作:
public async Task<List<T>> QueryCollection<T>(string collection, Expression<Func<T,bool>> predicate, int limit = 50, int batchSize = 50) where T : class { string[] collectionInformation = collection.Split('.'); string collectionName = collectionInformation[1]; string collectionDatabase = collectionInformation[0]; List<T> list = new List<T>(); AggregateOptions options = new AggregateOptions() { BatchSize = batchSize }; return await _client.GetDatabase(collectionDatabase).GetCollection<T>(collectionName).AsQueryable<T>(options).Where(predicate).ToListAsync(); }
内容的提问来源于stack exchange,提问作者Carlos Siestrup
相关产品推荐
相关产品推荐

