LINQ to SQL选择记录和转换日期

时间:2012-02-03 09:46:29

标签: sql linq

我正在尝试根据使用Linq to SQL的日期从表中选择记录。不幸的是,日期分为两个表 - 小时表有一天,相关的JobTime表有两列的月份和年份。

我有以下查询:

Dim qry = From h As Hour In ctx.Hours Where Convert.ToDateTime(h.day & "/" & h.JobTime.month & "/" & h.JobTime.year & " 00:00:00") > Convert.ToDateTime("01/01/2012 00:00:00")

这给了我错误“将表达式转换为数据类型datetime的算术溢出错误。”

查看SQL Server Profiler中的SQL查询,我看到:

exec sp_executesql N'SELECT [t0].[JobTimeID], [t0].[day], [t0].[hours] 
FROM [dbo].[tbl_pm_hours] AS [t0]
INNER JOIN [dbo].[tbl_pm_jobtimes] AS [t1] ON [t1].[JobTimeID] = [t0].[JobTimeID]
WHERE (CONVERT(DateTime,(((((CONVERT(NVarChar,[t0].[day])) + @p0) + (CONVERT(NVarChar,COALESCE([t1].[month],NULL)))) + @p1) + (CONVERT(NVarChar,COALESCE([t1].[year],NULL)))) + @p2)) > @p3',N'@p0 nvarchar(4000),@p1 nvarchar(4000),@p2 nvarchar(4000),@p3 datetime',@p0=N'/',@p1=N'/',@p2=N' 00:00:00',@p3='2012-01-31 00:00:00'

我可以看到它没有在日期中正确搜索,但我不确定如何纠正它。

有人可以帮忙吗?

谢谢, 艾玛

1 个答案:

答案 0 :(得分:0)

错误的直接原因可能与this issue有关。

正如那里所说,您使用的转换是构建查询的一种非常低效的方式。最重要的是,它是低效的,因为表达式不是sargable。即您在比较中使用数据库列中的计算值,禁用查询分析器使用索引跳转到单个列值。因此,您可以尝试通过解释直接原因来修复错误,但我认为最好以仅在比较中使用单列值的方式重写查询。

我在C#中解决了这个问题:

var cfg = new DateTime(12,6,12);
int year = 12, month = 6, day = 13; // Try some more values here.

// Date from components > datetime value?
bool gt = (
    year > cfg.Year || (
        (year == cfg.Year && month > cfg.Month) || (
            year == cfg.Year && month == cfg.Month && day > cfg.Day)
    )
);

你会发现它并不像最初看起来那么简单,但它确实有效。有更多的比较可以解决,但我确信使用索引的能力很容易超过这个。

更简单但不可思议的方法是使用可排序的日期,例如20120101并比较它们(作为整数)。