【问题标题】:Compiled C# Linq Expression<Func<T>> and querying Mongo编译 C# Linq Expression<Func<T>> 并查询 Mongo
【发布时间】:2019-01-25 22:28:01
【问题描述】:

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

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

所以我简化了代码并删除了对.Compile() lambda 表达式的调用,这似乎解决了问题(现在运行需要

我的问题是:为什么在查询 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");
}

最感谢的任何想法!

【问题讨论】:

  • 如果集合有 1,000,000 个实体,并且对于每个实体,它必须将表达式编译 成委托。这是一个相对耗时的操作,如果重复 1,000,000 次,执行这样的查询可能需要很长时间。将 Func 保存在字段或某些情况下的字典中会更合乎逻辑

标签: c# mongodb linq lambda mongorepository


【解决方案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.

【讨论】:

    【解决方案2】:

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

    查看源代码 https://github.com/fsefacan/MongoDbRepository

    【讨论】:

    • 您的答案对我来说似乎很不清楚。 记录所有记录是什么意思,注册是什么意思?你能详细说明一下吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多