如何在C#中用另一个表达式创建表达式?

时间:2014-10-10 09:38:35

标签: c# sql sql-server linq linq-expressions

我试图将股票Linq写入SQL查询等等,而且我发现我必须使用表达式而不是lambdas。

如果你不这样做,它会尝试将你的Linq直接转换为SQL,但它不起作用。

以表格上的主键为例。我们都被命名为不同的东西,但我想写一个标准的Linq WHERE子句,它使用一个表达式来选择正确的字段。

我写了以下测试代码:

    static void Main(string[] args)
    {
        using (var ss = new DataScope()
        {
            var db = DataScope.DatabaseConnection;
            var pk = 2;
            var sql = db.Beats.AsQueryable();
            sql = sql.Where(Filter(pk));
            var res = sql.ToList();
        }
    }

    static Expression<Func<Beat, bool>> Filter(int pk)
    {
        return e => e.BeatID > pk;
    }

代码是主要工作,PKID过滤器(int)过滤器,我可以将其转换为通用代码,更多派生属性基于每个表返回表达式。

但这有点受限,我只想定义指向PK字段的表达式,并从中构建更多的股票表达式。

否则,如果我想要PKGreaterThan和PKEquals,我必须为每个表定义两次。 我需要十几个,而且有数百个表。

让每个表定义指向关键字段的表达式(PK,GUID,唯一字符串,创建日期时间等)将更加简洁

但我不知道如何。

到目前为止,我提出的最好的(并且它没有丝毫工作)是:

    static Expression<Func<Beat, int>> PKExpression
    {
        get { return e => e.BeatID; }
    }

    static Expression<Func<Beat, bool>> SuperFilter(int pk)
    {
        var gt = Expression.GreaterThan(PKExpression, Expression.Constant(pk));
        return e => gt;
    }

我如何在Expression.GreaterThan

中包裹Expression<Func<Beat, int>>

2 个答案:

答案 0 :(得分:2)

我认为你必须通过Expression.Lambda<Func<Beat, bool>>

将其转换为Lambda Expression
ParameterExpression param = Expression.Parameter(typeof(Beat));
var gt = Expression.GreaterThan(Expression.Call(PKExpression,param), Expression.Constant(pk));
LambdaExpression condition =Expression.Lambda<Func<Beat, bool>>(gt, param);
return condition;

答案 1 :(得分:1)

站在Mehdi的肩膀上,我设法提出以下内容:

class Program
{
    static void Main(string[] args)
    {
        using (var ss = new DataScope(@"connString"))
        {
            var db = DataScope.DatabaseConnection;
            var pk = 2;
            var sql = db.Beats.AsQueryable();
            sql = sql.Where(PKGreaterThan(pk));
            var res = sql.ToList();
        }
    }

    static string PKName { get { return "BeatID"; } }

    static PropertyInfo PKProperty()
    {
        var output = typeof(Beat).GetProperties().Where(p => p.Name == PKName).SingleOrDefault();
        return output;
    }

    static Expression<Func<Beat, bool>> PKGreaterThan(int pk)
    {
        var beatParameter = Expression.Parameter(typeof(Beat));
        var beatPKProperty = Expression.Property(beatParameter, PKProperty());
        var beatPKGreaterThanPK = Expression.GreaterThan(beatPKProperty, Expression.Constant(pk));
        var output = Expression.Lambda<Func<Beat, bool>>(beatPKGreaterThanPK, beatParameter);
        return output;
    }
}

它现在位于一个通用基类中,类型T是sql行类的linq。 您现在要做的就是覆盖PKName属性,所有PK表达式都使用通用的SELECT子句和连接。