Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 根据上下文将DbFunctions切换到非db实现_C#_Linq_Linq To Entities_Expression - Fatal编程技术网

C# 根据上下文将DbFunctions切换到非db实现

C# 根据上下文将DbFunctions切换到非db实现,c#,linq,linq-to-entities,expression,C#,Linq,Linq To Entities,Expression,我有一个表达式,它使用DbFunctions类来计算日期。它适用于linq to entities,但我想将此表达式用于非db功能。是否可以检测表达式是否在db上下文中求值并使用相应的实现?我见过涉及模拟对象的单元测试解决方案,但我需要通用业务逻辑中的这个表达式,所以模拟看起来不是一个好的解决方案 以下是我的表达: public static Expression<Func<Transaction, bool>> Expired(int expirationPeriod)

我有一个表达式,它使用
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;
}
公共静态表达式已过期(int expirationPeriod)
{
返回s=>s.Status==Status.Created&&DbFunctions.AddMinutes(s.UpdateDateUTC,expirationPeriod)
我希望能够做到以下几点:

public static Expression<Func<Transaction, bool>> Expired(int expirationPeriod)
{
    return s => s.Status == Status.Created && MyCustomResolver.AddMinutes(s.UpdateDateUTC, expirationPeriod) < DateTime.UtcNow;
}
公共静态表达式已过期(int expirationPeriod)
{
返回s=>s.Status==Status.Created&&MyCustomResolver.AddMinutes(s.UpdateDateUTC,expirationPeriod)
其中,
MyCustomResolver
将根据上下文使用
DbFunctions
DateTime
实现

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()
,而不是每次都做。

最后,我使用了以下方法:

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

    /// <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);
        }
    }
    
    //
    ///利用Linq to实体和非db上下文的函数
    /// 
    公共静态类MyCustomResolver
    {
    [DbFunction(“Edm”、“AddMinutes”)]
    公共静态DateTime?AddMinutes(DateTime?timeValue,int addValue)
    {
    返回时间值?.AddMinutes(addValue);
    }
    }
    
  • 使用上面定义的helper函数生成表达式

    public static Expression<Func<Transaction, bool>> Expired(int expirationPeriod)
    {
        return s => s.Status == Status.Created && MyCustomResolver.AddMinutes(s.UpdateDateUTC, expirationPeriod) < DateTime.UtcNow;
    }
    
    公共静态表达式已过期(int expirationPeriod)
    {
    返回s=>s.Status==Status.Created&&MyCustomResolver.AddMinutes(s.UpdateDateUTC,expirationPeriod)

  • 问题是,在表达式内部,我没有关于是否为db调用的信息,所以问题是如何检测实际上下文(这个
    amIUsingDB
    值),而不每次都显式传递它,比如“为什么”,实际表达式更复杂,每次为db和非db上下文编写两个单独的实现对我来说似乎是一种开销,因此我想知道是否可以选择特定方法的正确实现(如
    AddMinutes
    )当表达式依赖于实际上下文时,@Random-justice--对两个注释都有效。这就是我将
    amIUsingDB
    的求值移到函数之外的原因。您可以将
    MyCustomResolver
    设置为您需要的解析程序,以了解该信息,然后再也不用担心它了。请注意,这样一来,您在问题中给出的
    Expired
    方法可以按照您的意愿工作。但是如何实际评估
    amIUsingDB
    值呢?或者这是不可能的,我必须在使用表达式之前显式地设置它?那么,您必须显式地将
    MyCustomResolver
    设置为正确的对象。你怎么做/什么时候做取决于你自己。在代码中的某个时刻,您知道是否正在使用db。那就定下来吧。