Linq to Entities 日期部分优化
Posted
技术标签:
【中文标题】Linq to Entities 日期部分优化【英文标题】:Linq to Entities Date Part Optimization 【发布时间】:2015-05-31 22:54:09 【问题描述】:我正在尝试根据网站管理仪表板的日期字段的一部分(来自区间分析图表)创建向下钻取。
var drilldownQuery = DataManager.DataSessions
.Include("Location")
.Include("Quote.Carriers")
.Include("Drivers")
.Include("Vehicles")
.Where(session =>
session.Timestamp >= Model.FromDate &&
session.Timestamp < through
);
if (!String.IsNullOrWhiteSpace(Model.DrillDown))
drilldownQuery = drilldownQuery.ToList()
.Where(session =>
IntervalSelector(session) == Model.DrillDown);
public string IntervalSelector(DataSession session)
switch (Model.SelectedInterval)
case TimeInterval.Hourly:
return session.Timestamp.Hour.ToString("D2");
case TimeInterval.Weekday:
return ((int)session.Timestamp.DayOfWeek).ToString();
case TimeInterval.Weekly:
return session.Timestamp.Date.AddDays(-(int)session.Timestamp.DayOfWeek).ToString("yyyy/MM/dd");
case TimeInterval.Monthly:
return session.Timestamp.Date.ToString("yyyy/MM");
case TimeInterval.Annual:
return session.Timestamp.Year.ToString("D4");
default:
return session.Timestamp.Date.ToString("yyyy/MM/dd");
当然,这在较大的日期范围内表现很差。我希望避免“ToList()”调用,以便在数据库而不是内存中执行向下钻取标准。这就是我卡住的地方,特别是在深入研究每小时和工作日标准时。
IntervalSelector 还用于对图形查询进行分组以及向下钻取。我愿意使用单独的选择器进行向下钻取,无论怎样提高它的性能。图形查询也执行 ToList,但性能很好,因为它不需要包含。
var graphQuery = DataManager.DataSessions
.Where(session =>
session.Timestamp >= Model.FromDate &&
session.Timestamp < through);
我想更好的方法是将 switch 语句移到 Linq 之外,如下所示:
switch (Model.SelectedInterval)
case TimeInterval.Hourly:
int selectedHour = int.Parse(Model.DrillDown);
drilldownQuery = drilldownQuery
.Where(session => session.Timestamp.Hour == selectedHour);
// thoughts on this? any better way?
break;
case TimeInterval.Weekday:
var selectedWeekday = int.Parse(Model.DrillDown) + 1;
// convert to sql dayofweek (Sun = 1)
drilldownQuery =
drilldownQuery.Where(
session => SqlFunctions
.DatePart("weekday", session.Timestamp) ==
selectedWeekday);
// get a NotSupportedException here.
// This function can only be invoked from Linq to Entities
break;
case TimeInterval.Weekly:
case TimeInterval.Monthly:
case TimeInterval.Annual:
default:
// handle these by adjusting the from & through dates?
【问题讨论】:
这可能会在codereview.stackexchange.com 上得到更好的接收。请记住,在使用 EF 上下文的 linq 语句中执行的任何操作都将转换为 SQL。因此,如果您认为在 sql server 之外执行该操作会更好,那么我绝对建议将这些操作/操作保留在 linq-to-entities 语句之外 这就是我想要做的。我希望在 sql server 中处理它,但我无法到达那里。这就是我寻求帮助的原因。 @JNYRanger 这段代码中哪个变量是你的 EF 上下文?是数据管理器吗?另外,您使用的是延迟加载还是急切加载? @JNYRanger - 是的,DataManager 是上下文的子类。我渴望加载子表(保险报价,所以会话,位置,司机,车辆,运营商等)。这就是为什么我需要避免过早的 .ToList() 【参考方案1】:我刚刚解决了这个问题。这是给需要它的其他人的:
if (!String.IsNullOrWhiteSpace(model.DrillDown))
switch (model.SelectedInterval)
case TimeInterval.Weekly:
model.FromDate = DateTime.ParseExact(model.DrillDown,"yyyy/MM/dd",CultureInfo.InvariantCulture);
model.ThroughDate = model.FromDate.AddDays(6);
break;
case TimeInterval.Monthly:
model.FromDate = DateTime.ParseExact(model.DrillDown+"/01", "yyyy/MM/dd", CultureInfo.InvariantCulture);
model.ThroughDate = model.FromDate.AddMonths(1).AddDays(-1);
break;
case TimeInterval.Annual:
model.FromDate = DateTime.ParseExact(model.DrillDown + "/01/01", "yyyy/MM/dd", CultureInfo.InvariantCulture);
model.ThroughDate = model.FromDate.AddYears(1).AddDays(-1);
break;
case TimeInterval.Daily:
model.FromDate = DateTime.ParseExact(model.DrillDown, "yyyy/MM/dd", CultureInfo.InvariantCulture);
model.ThroughDate = model.FromDate;
break;
var through = model.ThroughDate.AddDays(1);
var drilldownQuery = DataManager.DataSessions
.Include("Location")
.Include("Quote.Carriers")
.Include("Drivers")
.Include("Vehicles")
.Where(session =>
session.Timestamp >= model.FromDate &&
session.Timestamp < through
);
if (!String.IsNullOrWhiteSpace(model.DrillDown))
switch (model.SelectedInterval)
case TimeInterval.Hourly:
int selectedHour = int.Parse(model.DrillDown);
drilldownQuery = drilldownQuery.Where(session => session.Timestamp.Hour == selectedHour);
break;
case TimeInterval.Weekday:
var selectedWeekday = (DayOfWeek) int.Parse(model.DrillDown);
drilldownQuery =
drilldownQuery.Where(
session => session.Timestamp.DayOfWeek == selectedWeekday);
break;
return drilldownQuery;
【讨论】:
哈哈我正要发表评论,建议做一些非常相似的事情,但你打败了我。干得好!以上是关于Linq to Entities 日期部分优化的主要内容,如果未能解决你的问题,请参考以下文章
LINQ to Entities 异常中不支持指定的类型成员“日期”
LINQ to Entities 不支持指定的类型成员“日期”。 DbFunctions.TruncateTime()