Построить выражение фильтра MongoDB из выражения поля: `Выражение Выражение > ` - PullRequest
0 голосов
/ 11 апреля 2020

Я пишу стандартную c службу, которая для T должна найти запись в базе данных mongodb на основе предоставленного поля id Expression<Func<T, string>>.

Модель выглядит примерно так:

struct TestEntity{
    public string Id { get; set; }
}

служба выглядит примерно так:

class Repository<T> {
    private readonly Expression<Func<T, string>> _idField;
    private readonly IMongoCollection<T> _collection;

    public Repository(Expression<Func<T, string>> idField, IMongoCollection<T> collection)
    {
        _idField= idField;
        _collection = collection;
    }

    public T Find(string id) {
        Func<T, string> idAccessor = _idField.Compile();
        FilterDefinition<T> filter = new ExpressionFilterDefinition<T>(
            // the mongodb filter takes an Expression<Func<T, bool>>
            entity => idAccessor(entity) == id);
        return _collection.Find(filter).First();
    }
}

Однако mongodb, похоже, не в состоянии правильно справиться с этим выражение. Я получаю следующую ошибку:

System.InvalidOperationException: Invoke (значение (System.Func`2 [TestEntity, System.String]), {document}) не поддерживается.

Я подозреваю, что не могу скомпилировать выражение id для функции и просто использовать его для построения другого выражения. Если это правда, то мой вопрос: как бы я превратил Expression<Func<T, string>> в Expression<Func<T, bool>>?

1 Ответ

0 голосов
/ 11 апреля 2020

Я смог добиться этого, вручную разобрав выражение и снова собрав его. в основном, создайте новое лямбда-выражение с тем же параметром, но оберните тело в Expression.Equal(), например:

Expression<Func<T, bool>> filterExpr = Expression.Lambda<Func<T, bool>>(
    Expression.Equal(_idField.Body, Expression.Constant(id)),
    _idField.Parameters.First());
...