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

本文关键字:表达式 创建 一个 另一个 | 更新日期: 2023-09-27 18:26:12

我正在尝试将stock Linq写入SQL查询等,我发现我必须使用表达式而不是lambdas。

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

以表上的主键为例。我们的名字都不一样,但我想写一个标准的LinqWHERE子句,它使用表达式来选择正确的字段。

我已经写了以下测试代码:

    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;
    }

代码是Main works,Filter(int)Filter by PKID,我可以将其转换为泛型代码,使用更多派生属性按表返回表达式。

但这有点有限,我只想定义指向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<Func<Beat, int>> 中包装Expression.GreaterThan

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

我认为您必须通过Expression.Lambda<Func<Beat, bool>> 将其转换为Lambda表达式

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;

站在迈赫迪的肩膀上,我成功地想出了以下东西:

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是linq-to-sql行类。现在所要做的就是重写PKName属性,并且所有PK表达式都使用泛型SELECT子句和联接。