Скомпилированное выражение C # Linqи запрашивая Монго - PullRequest
0 голосов
/ 26 января 2019

Я унаследовал некоторый код от бывшего сотрудника, который запрашивает базу данных mongo, используя скомпилированные выражения Linq и библиотеку MongoRepository (которая находится поверх драйвера MongoDB C #).

Это заняло много времени - обычно около 6 минут (!) И вызывало проблемы с методами контроллера, которые их использовали.

Итак, я упростил код и удалил вызов .Compile() лямбда-выражения, и это, похоже, решило проблему (теперь требуется <10 секунд). </p>

Мои вопросы: почему компиляция этого выражения вызывает проблемы при обращении к монго?

Это было суть исходного кода (взломан, так что из контекста извините):

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 голосов
/ 31 января 2019

Выражение может быть преобразовано поставщиком в реальный 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.
0 голосов
/ 26 января 2019

Причиной проблемы с производительностью является запись всех записей связанного объекта и их фильтрация. Сначала вам нужно создать запрос и зарегистрироваться от mongo db.

обзор кода союзы https://github.com/fsefacan/MongoDbRepository

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...