3

我正在尝试将计算列添加到从 SQL 表创建的 linq 对象中。我无法在数据库中执行此操作。

public partial class History_SHIP
{
    public Expression<Func<DateTime>> TransactionDateTime
    {
        get
        {
            return () => TransactionDate.AddMinutes(SqlMethods.DateDiffMinute(TransactionTime, new DateTime(1900, 1, 1)));
        }
    }
}

我希望能够将它用作 where 子句的一部分,如下所示:

where sh.TransactionDateTime >= startDate

startDate是一个DateTime并且sh是我的History_SHIP对象。

我也希望能够在 select 语句中轻松使用它(我很高兴创建另一个执行 a 的属性TranslationDateTime.Compile()())。

我对 where 子句的问题是 a 中的 LHSExpression<Func<DateTime>>和 RHS 是 a DateTime,所以它会抱怨。


我已经看到了这个链接http://www.codeproject.com/Articles/32968/QueryMap-Custom-translation-of-LINQ-expressions但不想要这个属性的额外依赖项(无论如何现在)。

4

2 回答 2

1

是的,由于各种原因,这不会让人高兴;

  • 首先,LINQ 解释器可以直接处理——它需要帮助
  • 其次,实现的属性返回与 相关的东西this,但实际上我们需要与 a ParameterExpression(aka sh)相关的东西

最简单的做法可能是添加一个扩展方法,让您可以方便地对此进行过滤,例如通过重写Expression

var filtered = source.WhereTransactionDate(when => when > DateTime.Now);

实施:

static class Utils
{
    static readonly Expression<Func<Foo, DateTime>> tranDateTime =
            x => x.TransactionDate.AddMinutes(SqlMethods.DateDiffMinute(
                     x.TransactionTime, new DateTime(1900, 1, 1)));

    public static IQueryable<Foo> WhereTransactionDate(
        this IQueryable<Foo> source,
        Expression<Func<DateTime, bool>> predicate)
    {
        var visited = SwapVisitor.Swap(predicate.Body,
              predicate.Parameters.Single(), tranDateTime.Body);
        var lambda = Expression.Lambda<Func<Foo, bool>>(
              visited, tranDateTime.Parameters);
        return source.Where(lambda);
    }

    class SwapVisitor : ExpressionVisitor
    {
        public static Expression Swap(Expression source,
             Expression from, Expression to)
        {
            return new SwapVisitor(from, to).Visit(source);
        }
        private SwapVisitor(Expression from, Expression to)
        {
            this.from = from;
            this.to = to;
        }
        readonly Expression from, to;
        public override Expression Visit(Expression node)
        {
            return node == from ? to : base.Visit(node);
        }
    }
}

这样做是合并两个表达式树,即

x => x.TransactionDate.AddMinutes(SqlMethods.DateDiffMinute(
                     x.TransactionTime, new DateTime(1900, 1, 1)))

和:

when => when > DateTime.Now

用第一个表达式中的主体替换所有when内容(并使用第一个表达式中的参数),即创建

x => x.TransactionDate.AddMinutes(SqlMethods.DateDiffMinute(
           x.TransactionTime, new DateTime(1900, 1, 1))) > DateTime.Now;
于 2012-10-10T08:54:13.457 回答
0

怎么样...

where sh.TransactionDateTime.Compile().Invoke() >= startDate 
于 2012-10-10T08:45:40.660 回答