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

时间:2012-04-03 14:31:57

标签: c# linq entity-framework sql-server-2005

问题详情:

  • SQL Server 2005;
  • 实体框架4.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做到这一点?是否可以(忽略日期,只使用时间)?

4 个答案:

答案 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)

其中lowerupperTotalMilliseconds个对象的TimeSpan属性。

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

注意:在EF6之前,DbFunctionsEntityFunctions

答案 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);

编辑2

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

答案 3 :(得分:-1)

如果表中有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);