【发布时间】:2016-10-26 20:29:31
【问题描述】:
使用System.Linq.Dynamic(在此处管理https://github.com/kahanu/System.Linq.Dynamic),我正在尝试使用实体框架6(或更高版本)捕获DateTime 上的DayOfWeek 字段以用于聚合目的。
之前求过类似的东西,帮了大忙,Dynamic Linq + Entity Framework: datetime modifications for dynamic select
Entity Framework 支持使用
获取DayOfWeek
SqlFunctions.DatePart("dw", datetime?)
或者我们可以使用类似
的东西做一些更需要的事情DbFunctions.DiffDays(date?, date?).
想法:
Getting the DayOfWeek in Linq to Entities
我发现这很有趣,我喜欢它,因为它不使用 SqlFunctions,这可能会让我受限于 SQL Server。此外,开发人员可以控制一周的第一天是什么,而无需查询 SQL Server 属性以查找其配置方式(第一天)。
出于实验目的,我一直在尝试在 VisitMember() 覆盖中实现这一点:
protected override Expression VisitMember(MemberExpression node)
{
if (node.Type == typeof(System.DayOfWeek))
{
var firstSunday = new DateTime(1753, 1, 7);
var firstSundayExpression = Expression.Constant(firstSunday, typeof(DateTime?));
var timeValue = node.Expression;
if (timeValue.Type != typeof(DateTime?)) timeValue = Expression.Convert(timeValue, typeof(DateTime?));
var methodCall = Expression.Call(
typeof(DbFunctions), "DiffDays", Type.EmptyTypes, firstSundayExpression, timeValue);
return Expression.Convert(methodCall, typeof(int?));
}
return base.VisitMember(node);
}
使用上面的想法,我想我可以包装这个表达式,然后将模值应用于输入时间,但我什至无法让这个表达式更进一步。
我觉得我错过了如何构建表达式的基本部分。我遇到的错误
参数类型不匹配
在 System.Linq.Expressions.Expression.Bind(MemberInfo 成员,表达式表达式)
在 System.Linq.Expressions.ExpressionVisitor.Visit[T](ReadOnlyCollection1 nodes, Func2 elementVisitor)
在 System.Linq.Expressions.ExpressionVisitor.VisitMemberInit(MemberInitExpression 节点)
在 System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression`1 节点)
在 System.Linq.Expressions.ExpressionVisitor.VisitUnary(UnaryExpression 节点)
在 System.Linq.Expressions.ExpressionVisitor.VisitArguments(IArgumentProvider 节点)
在 System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression 节点)
在 Path\QueryableExtensions.cs:line 48 中的 QueryableExtensions.DbFunctionsBinder.VisitMethodCall(MethodCallExpression 节点)
在 Path\QueryableExtensions.cs:line 13 中的 BindDbFunctions(IQueryable source)
在 Path\AggregateHelper.cs:line 811 中的 AggregateHelper.d__15.MoveNext()--- 从先前抛出异常的位置结束堆栈跟踪
在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)
在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)
在 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
在 Path\AggregationPluginServiceHelper.cs:line 199 中的 AggregationPluginServiceHelper.d__9.MoveNext()
我知道我可以做到这一点是我编写了内联编译的查询。这很好用。但这是专门使用动态库的。
示例用法如下:
var grouping = select.GroupBy("new (DateTimeColumn.DayOfWeek)", "it");
有没有更好的方法来获取星期几?我知道这可能在文化上有所不同,所以我相信与星期日不同的日子模数(上面的链接想法)是正确的方法。
【问题讨论】:
-
您在查询后没有计算这个是有原因的吗?在您调用动态 linq 后,这样做可能会更容易
标签: c# linq entity-framework-6 expression-trees dynamic-linq