问题详情:
我正在尝试使用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做到这一点?是否可以(忽略日期,只使用时间)?
答案 0 :(得分:3)
var filteredTimes = myContext.MyTable
.Where(r => SqlFunctions.DatePart("hour", r.DateField) >= 11 &&
SqlFunctions.DatePart("hour", r.DateField) <= 13);
您需要添加System.Data.Objects.SqlClient
才能获得SqlFunctions
。
答案 1 :(得分:0)
如果将日期值转换为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<double>()
.Select(d => d - Math.Floor(d))
.Where(... your comparisons
这转换为包含CAST([date column] AS float)
和Sql的FLOOR
函数的Sql。
发表评论后:
看起来很简单,但我找不到指示EF对CAST
中的单个属性进行Select()
的方法。只有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
是TotalMilliseconds
个对象的TimeSpan
属性。
请注意,这在sql中非常低效!每次比较都会重复日期功能。因此,请确保对一组数据进行比较,这些数据已被其他条件尽可能地限制。首先在内存中获取数据然后进行比较甚至可能更好。
注意:在EF6之前,DbFunctions
为EntityFunctions
。
答案 2 :(得分:-1)
- 您可以使用日期上的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<DateTime> dates = new List<DateTime>();
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);
是的,你似乎需要.ToList(),你应该已经弄明白了。我无法知道你有什么收藏品。当你没有提供关于这个问题的大量信息时,我们当中任何一个人都不值得尝试帮助你
答案 3 :(得分:-1)
如果表中有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);