根据上下文

时间:2017-06-01 12:53:08

标签: c# linq linq-to-entities expression

我有一个使用DbFunctions类来计算日期的表达式。它适用于linq-to-entities,但我想将此表达式重用于非db功能。是否有可能检测表达式是否在db上下文中进行评估并使用相应的实现?我已经看到了涉及模拟对象的单元测试的解决方案,但我需要在常见的业务逻辑中使用这个表达式,因此模拟看起来不是一个好的解决方案。

这是我的表达:

public static Expression<Func<Transaction, bool>> Expired(int expirationPeriod)
{
    return s => s.Status == Status.Created && DbFunctions.AddMinutes(s.UpdateDateUTC, expirationPeriod) < DateTime.UtcNow;
}

我希望能够做到这样的事情:

public static Expression<Func<Transaction, bool>> Expired(int expirationPeriod)
{
    return s => s.Status == Status.Created && MyCustomResolver.AddMinutes(s.UpdateDateUTC, expirationPeriod) < DateTime.UtcNow;
}

其中MyCustomResolver将根据上下文使用DbFunctionsDateTime实现。

2 个答案:

答案 0 :(得分:0)

interface ICustomResolver
{
    DateTime AddMinutes(DateTime, int);
}

public class DbCustomResolver : ICustomResolver
{
    public DateTime AddMinutes(DateTime time, int minutes)
    {
        return DbFunctions.AddMinutes(time, minutes);
    }
}

public class NonDbCustomResolver : ICustomResolver
{
    public DateTime AddMinutes(DateTime time, int minutes)
    {
        return time.AddMinutes(minutes);
    }
}


ICustomResolver MyCustomResolver = 
   amIUsingDB ? new DbCustomResolver() : new NonDbCustomResolver();

现在,我想象一个人可以在AddMinutes内即时做出决定,但为什么呢?做if()一次而不是每次都这样做会更好。

答案 1 :(得分:0)

最后我使用了以下方法:

  1. 定义具有DbFunction属性的函数。这样,如果在Linq-to-Entities表达式或C#函数中使用,如果在非db上下文中执行,它将使用相应的SQL函数

    /// <summary>
    /// Utilize functions for both Linq-to-Entities and non-db context
    /// </summary>
    public static class MyCustomResolver
    {
        [DbFunction("Edm", "AddMinutes")]
        public static DateTime? AddMinutes(DateTime? timeValue, int addValue)
        {
            return timeValue?.AddMinutes(addValue);
        }
    }
    
  2. 使用上面定义的辅助函数构建表达式

    public static Expression<Func<Transaction, bool>> Expired(int expirationPeriod)
    {
        return s => s.Status == Status.Created && MyCustomResolver.AddMinutes(s.UpdateDateUTC, expirationPeriod) < DateTime.UtcNow;
    }