是否可以使用linq运行查询来搜索一段时间?

问题详情:

  • SQL Server 2005;
  • entity framework4.0。

我正在尝试使用linq来运行一段时间的查询。 例:

我的服务器中有以下datetime数据:

 30/03/2012 12:53:22 30/03/2012 17:23:29 04/04/2012 11:10:14 04/04/2012 19:06:55 

我想运行一个查询,它将在时间(12:00和20:00)之间返回所有数据,并且查询必须返回给我以下数据:

 30/03/2012 12:53:22 30/03/2012 17:23:29 04/04/2012 19:06:55 

或者在(11:00和13:00)之间,查询必须返回给我以下数据:

 30/03/2012 12:53:22 04/04/2012 11:10:14 

我怎么能用linq做到这一点? 有可能(忽略日期,只使用时间)?

 var filteredTimes = myContext.MyTable .Where(r => SqlFunctions.DatePart("hour", r.DateField) >= 11 && SqlFunctions.DatePart("hour", r.DateField) <= 13); 

您需要包含System.Data.Objects.SqlClient才能获取SqlFunctions

如果将日期值转换为double并使用if的小数部分,则会得到一个介于0和1之间的数字,表示一天中的时间。 有了这个,测试时间间隔是微不足道的,例如13:45将是0,5729166667(或更确切地说:13:45.345是0,572920679)。

你可以这样做,因为EF(即4.3,我使用的版本)将Cast和甚至Math函数转换为SQL:

 mycontext.Data.Where(dt => dt.DateTime.HasValue) .Select(dt => dt.DateTime.Value).Cast() .Select(d => d - Math.Floor(d)) .Where(... your comparisons 

这转换为包含CAST([date column] AS float)和Sql的FLOOR函数的Sql。


你的意见后:

它看起来很简单,但我找不到指示EF在Select()的单个属性上执行CAST 。 只有Cast<>()函数被转换为CAST (sql),但它在一个集合上运行。

好吧,幸运的是,有另一种方式:

 mycontext.Data.Where(dt => dt.DateTime.HasValue) .Select(dt => new { Date = DbFunctions.TruncateTime(dt.DateTime.Value), Ms = DbFunctions.DiffMilliseconds( DbFunctions.TruncateTime(dt.DateTime.Value), dt.DateTime.Value) }) .Where(x => x.Ms > lower && x.Ms < upper) 

其中lowerupperTimeSpan对象的TotalMilliseconds属性。

请注意,这在sql中非常低效! 每次比较都会重复日期function。 因此,请确保对一组数据进行比较,这些数据已被其他条件尽可能地限制。 首先在内存中获取数据然后进行比较甚至可能更好。

注意:在DbFunctions之前, DbFunctionsEntityFunctions

如果表中有datetime列(尽可能使用SQL Server 2008),则可以直接在SQL中执行此操作。

因为情况并非如此,你必须这样做:

 // the first two lines can be omitted, if your bounds are already timespans var start = startDate.TimeOfDay; var end = endDate.TimeOfDay; var filteredItems = context.Items.ToList() .Where(x => x.DateTimeColumn.TimeOfDay >= start && x.DateTimeColumn.TimeOfDay <= end); 

– 您可以使用日期上的TimeOfDay属性来比较它们。

 string timeAsString = "13:00"; from f in TableRows where f.Date.TimeOfDay > DateTime.Parse("11-12-2012 "+timeAsString).TimeOfDay select f 

编辑

这里有一些你可以测试的代码为我运行:

  DateTime d = DateTime.Parse("12-12-2012 13:00"); List dates = new List(); dates.Add(DateTime.Parse("12-12-2012 13:54")); dates.Add(DateTime.Parse("12-12-2012 12:55")); dates.Add(DateTime.Parse("12-12-2012 11:34")); dates.Add(DateTime.Parse("12-12-2012 14:53")); var result = (from f in dates where f.TimeOfDay > d.TimeOfDay select f); 

编辑2

是的,你似乎需要.ToList(),你应该已经弄清楚了。 我无法知道你有什么collections品。 当你没有提供关于这个问题的大量信息时,我们当中任何一个人都不值得尝试帮助你