我们正在研究使用EF6 / MSSQL的解决方案,在该解决方案中,我们可以根据用户查询输入(例如5分钟四舍五入,10等)对日期/时间进行四舍五入
查询示例为:
(这只是模型,并不代表任何功能)
from item in context.MyView
select item.DataTimeStamp.RoundToNearest(TimeSpan.FromMinutes(5))
很显然,RoundToNearest(TimeSpan)不存在,并且与实体框架不兼容。
我想我将用VisitMethodCall实现一个ExpressionVisitor,并在请求RoundToNearest方法时应用我的Expression,但是我似乎做不到。
我们正在动态建立查询,因此我们可以使用聚合(分组依据等)。上面的用法仅用于概念证明。
如果我们想使用扩展方法将自己的公式添加到列中,这将转换为SQL表达式,我们该怎么做?
我到目前为止所拥有的(当然不起作用)
public static DateTime RoundToNearest(this DateTime date, TimeSpan period)
{
throw new NotSupportedException("This method should not be called directly. This will be called by an expression visitor");
}
class DbFunctionsBinder : ExpressionVisitor
{
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Object == null || node.Object.Type != typeof(DateTime)) return base.VisitMethodCall(node);
switch (node.Method.Name)
{
case nameof(RoundToNearest):
return Expr((DateTime timeValue, TimeSpan roundValue) => timeValue.Date) // Code Later
.WithParameters(Visit(node.Object), Visit(node.Arguments[0]));
}
return base.VisitMethodCall(node);
}
}
一旦知道,我将努力从此SQL语句中创建等效的表达式:
select top 10000
(
CAST(
-- Round with Truncate Round(value,0,1)
ROUND(
CAST(DataTimeStamp AS FLOAT) * (1440/5.0),0,1)/(1440/5.0)
as Datetime)
) as TheRoundedTime
from DataSourceTable
其中显示的5.0值将是传递给扩展方法的TimeSpan上TotalMinutes的十进制值。
此刻,我出错了:
抛出异常:mscorlib.dll中的'System.NotSupportedException' LINQ to Entities无法识别方法'System.DateTime RoundToNearest(System.DateTime,System.TimeSpan)'方法,并且该方法无法转换为商店表达式。
注意:
谢谢!