简体   繁体   English

使用在LINQ-To-SQL中返回表达式的方法

[英]Using a method returning an expression in LINQ-To-SQL

I'm trying to add a computed column to my linq object created from an SQL table. 我正在尝试将计算列添加到从SQL表创建的linq对象中。 I can't do this in the database. 我不能在数据库中这样做。

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

I'd like to be able to use it as part of a where clause like below: 我希望能够将它作为where子句的一部分使用,如下所示:

where sh.TransactionDateTime >= startDate

startDate is a DateTime and sh is my History_SHIP object. startDate是一个DateTimesh是我的History_SHIP对象。

I'd also like to be able to easily use it in a select statement too (I'm happy to create another property that does a TranslationDateTime.Compile()() ). 我也希望能够在select语句中轻松使用它(我很乐意创建另一个执行TranslationDateTime.Compile()()属性。

The problem I have with the where clause is that the LHS in a Expression<Func<DateTime>> and the RHS is a DateTime , so it complains. 我对where子句的问题是Expression<Func<DateTime>>中的LHS和RHS是DateTime ,所以它抱怨。


I have seen this link http://www.codeproject.com/Articles/32968/QueryMap-Custom-translation-of-LINQ-expressions but don't want additional dependencies for this one property (for now anyway). 我已经看到这个链接http://www.codeproject.com/Articles/32968/QueryMap-Custom-translation-of-LINQ-expressions但是不希望这个属性有其他依赖关系(现在无论如何)。

Yes, that isn't going to be happy, for various reasons; 是的,出于各种原因,这不会令人满意;

  • firstly, the LINQ interpreter can handle that directly - it will need help 首先,LINQ解释器可以直接处理 - 它需要帮助
  • secondly, the property as implemented returns something in relation to this , but in reality we need something in relation to a ParameterExpression (aka sh ) 其次,实现的属性返回与this ,但实际上我们需要与ParameterExpression (aka sh )相关的东西

The easiest thing to do is probably to add an extension method that lets you filter on this conveniently, for example by re-writing an Expression : 最简单的方法是添加一个扩展方法,让您可以方便地对此进行过滤,例如通过重写Expression

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

with implementation: 实施:

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

What this does is merge two expression-trees, ie 这样做是合并两个表达式树,即

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

and: 和:

when => when > DateTime.Now

replacing all when with the body from the first expression (and using the parameter from the first expression) ie creating 更换所有when与所述主体从所述第一表达(以及使用来自所述第一表达的参数),即产生

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

怎么样...

where sh.TransactionDateTime.Compile().Invoke() >= startDate 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM