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);
}
}
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。那就定下来吧。