动态predicates为LINQ到实体查询 [英] Dynamic predicates for Linq-to-Entity queries

查看:101
本文介绍了动态predicates为LINQ到实体查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的LINQ到实体查询工作正常:

The following Linq-to-Entities query works fine:

var query = repository.Where(r => r.YearProp1.HasValue &&
                                  r.YearProp1 >= minYear &&
                                  r.YearProp1 <= maxYear);

我的数据库有十几列的所有报告期内相关的信息(短?数据类型)。我想重复使用相同的LINQ到实体逻辑所有这些列。是这样的:

My database has a dozen or so columns that all report year-related information (short? data type). I want to reuse the same Linq-to-Entities logic for all these columns. Something like:

Func<RepoEntity, short?> fx = GetYearPropertyFunction();
var query = repository.Where(r => fx(r).HasValue &&
                                  fx(r) >= minYear &&
                                  fx(r) <= maxYear);

这导致错误:

LINQ实体无法识别方法
  System.Nullable`1 [System.Int16] FX(RepoEntity)的方法,这
  方法不能被翻译成店前pression。

LINQ to Entities does not recognize the method 'System.Nullable`1[System.Int16] fx(RepoEntity)' method, and this method cannot be translated into a store expression.

我明白为什么我得到的错误,但我想知道如果有不涉及重复code十几次只是为了改变该SQL查询是经营性的解决方法。

I understand why I am getting the error, but am wondering if there is a workaround that doesn't involve duplicating code a dozen times just to change the property on which the SQL query is operating.

我会在多个查询重用的功能,所以我想我的问题的一般版本是:有没有一种方法,以一个简单的属性的getter lambda表达式转换为防爆pression了可以通过消耗LINQ到实体?

I would be reusing the function in more than one query, so I guess the general version of my question is: Is there a way to convert a simple property-getter lambda function to an Expression that can be consumed by Linq-to-Entities?

推荐答案

大厦关闭拉斐尔Althaus先生'的答案,但加入您最初要找的通用选择:

Building off of Raphaël Althaus' answer, but adding the generic selector you were originally looking for:

public static class Examples
{
    public static Expression<Func<MyEntity, short?>> SelectPropertyOne()
    {
        return x => x.PropertyOne;
    }

    public static Expression<Func<MyEntity, short?>> SelectPropertyTwo()
    {
        return x => x.PropertyTwo;
    }

    public static Expression<Func<TEntity, bool>> BetweenNullable<TEntity, TNull>(Expression<Func<TEntity, Nullable<TNull>>> selector, Nullable<TNull> minRange, Nullable<TNull> maxRange) where TNull : struct
    {
        var param = Expression.Parameter(typeof(TEntity), "entity");
        var member = Expression.Invoke(selector, param);

        Expression hasValue = Expression.Property(member, "HasValue");
        Expression greaterThanMinRange = Expression.GreaterThanOrEqual(member,
                                             Expression.Convert(Expression.Constant(minRange), typeof(Nullable<TNull>)));
        Expression lessThanMaxRange = Expression.LessThanOrEqual(member,
                                          Expression.Convert(Expression.Constant(maxRange), typeof(Nullable<TNull>)));

        Expression body = Expression.AndAlso(hasValue,
                      Expression.AndAlso(greaterThanMinRange, lessThanMaxRange));

        return Expression.Lambda<Func<TEntity, bool>>(body, param);
    }
}

可能会略有使用像你要找的原始查询:

Could be used somewhat like the original query you were looking for:

Expression<Func<MyEntity, short?>> whatToSelect = Examples.SelectPropertyOne;

var query = Context
            .MyEntities
            .Where(Examples.BetweenNullable<MyEntity, short>(whatToSelect, 0, 30));

这篇关于动态predicates为LINQ到实体查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆