2012-02-03 2 views
0

Я пытаюсь выбрать записи из таблицы на основе даты с использованием Linq to SQL. К сожалению, дата разбита на две таблицы: таблица «Часы» имеет день, а соответствующая таблица JobTime имеет месяц и год в двух столбцах.LINQ to SQL выбор записей и преобразование дат

У меня есть следующий запрос:

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 в SQL Server Profiler, я вижу:

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' 

Я вижу, что он не проходит в даты, чтобы искать правильно, но я не уверен, как это исправить.

Может ли кто-нибудь помочь?

Спасибо, Эмма

ответ

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 и сравнить их (как целые числа).

Смежные вопросы