编译C#Linq Expression <func <t >>并查询Mongo

时间:2019-01-25 22:28:02

标签: c# mongodb linq lambda mongorepository

我已经从一名前雇员那里继承了一些代码,该雇员使用已编译的Linq表达式和MongoRepository library(位于MongoDB C#驱动程序之上)查询mongo DB。

这需要很长时间才能运行-通常大约需要6分钟(!),并且会导致使用它们的控制器方法出现问题。

因此,我简化了代码并删除了对.Compile() lambda表达式的调用,这似乎解决了这个问题(现在需要<10s才能运行)。

我的问题是:为什么在查询mongo时编译此表达式会引起问题?

这是原始代码的要旨(被黑掉了,所以出于上下文,抱歉):

public class BaseMongoRepository<T> : MongoRepository<T, Guid> where T : IEntity<Guid> {

    protected BaseMongoRepository(string connectionString) : base(connectionString) { }

    protected bool IsSatisfiedBy(T entity) {
        Expression<Func<T, bool>> func = x => x != null && x.ToString() == "foo"; // query was passed in, but you get the idea
        var predicate = func.Compile(); // THIS LINE??
        return predicate(entity);
    }

    public IEnumerable<T> Find() {
        return base.collection.AsQueryable().Where(IsSatisfiedBy);
    }
}

我将其简化为仅使用常规谓词Func

public IEnumerable<T> Find() {
    return base.collection.AsQueryable().Where(x => x != null && x.ToString() == "foo");
}

任何想法都值得赞赏!

2 个答案:

答案 0 :(得分:1)

提供程序可以将表达式转换为真正的sql查询,但是不能解释委托。
这段代码中的predicate变量:

Expression<Func<T, bool>> func = x => x != null && x.ToString() == "foo";
var predicate = func.Compile();

基本上与以下内容相同:

Func<T, bool> predicate = x => x != null && x.ToString() == "foo";

使用此类委托时,数据库中的所有数据都将传输到内存中,然后应用谓词。

伪代码示例:

// Using the delegate:
var data = dbContext.Users.Where(usr => IsSatisfiedBy(usr)).ToList();
// This will result in the following steps:
var userList = ExecuteQuery("SELECT * FROM Users"); // all users are fetched.
var satisfied = userList.Where(usr => IsSatisfiedBy(usr))

// Using an expression:
var data = dbContext.Users.Where(usr => usr.Name == "foo");
// This will result in the following step:
var satisfied = ExecuteQuery("SELECT * FROM Users WHERE Name = 'foo'"); // Filtered before returned to caller.

答案 1 :(得分:-1)

性能问题的原因是记录相关对象的所有记录,然后将其过滤掉。首先,您需要创建查询并从mongo db注册。

审查代码 https://github.com/fsefacan/MongoDbRepository