是否可以使用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)
其中lower
和upper
是TimeSpan
对象的TotalMilliseconds
属性。
请注意,这在sql中非常低效! 每次比较都会重复日期function。 因此,请确保对一组数据进行比较,这些数据已被其他条件尽可能地限制。 首先在内存中获取数据然后进行比较甚至可能更好。
注意:在DbFunctions
之前, DbFunctions
是EntityFunctions
。
如果表中有date
和time
列(尽可能使用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品。 当你没有提供关于这个问题的大量信息时,我们当中任何一个人都不值得尝试帮助你