2009-11-04 2 views
1

Я использую Entity Framework, и у меня есть объект COMMENT. КОММЕНТАРИЙ имеет свойство DATEMODIFIED, которое является датой Nullable. Я пытаюсь построить запрос, который будет фильтровать ЗАМЕЧАНИЯ по дате, поэтому я создаю объект STARTDATE, и сделайте следующее:Сравнение DateTime в ObjectQuery.Where

Dim q As ObjectQuery(Of COMMENT) = _ 
    (From c In model.COMMENT Select c) 

If startDate.HasValue Then 
    q = q.Where(Function(c) startDate.Value <= c.DATEMODIFIED) 
End If 

Проблема заключается в том, что q.toList() не возвращает никаких комментариев, даже хотя я думаю, что так и должно быть. Все комментарии в базе данных имеют значения DATEMODIFIED, и даже если я передаю DateTime.MinValue как startDate, запрос все равно не соответствует никаким объектам.

я поставил точку останова перед Условный оператор и использовать Watch Window Visual Studio, чтобы попробовать и посмотреть, что происходит:

q.ToList()(0).DATEMODIFIED 'Returns the expected date 
startDate.Value    'Returns the expected date 
startDate.Value <= q.ToList()(0).DATEMODIFIED 'Returns True... 

Но однажды, когда он попадает в д = q.Where (сказуемое) часть , q.ToList() больше не возвращает никаких записей. Я в тупике.

+0

Посмотрите на ObjectQuery.ToTraceString() (или SQL Profiler) и разместите его здесь, с параметрами. –

+0

ВЫБОР 1 AS C1, "Extent1" .COMMENT_ID AS COMMENT_ID, "Extent1" .COMMENTS как комментарии, "Extent1" .SYS_GEN_FLAG А.С. SYS_GEN_FLAG, "Extent1" .ITEM_ID А.С. item_id, "Extent1" .MODIFIEDBY А.С. ModifiedBy, "Extent1" .DATEMODIFIED А.С. DATEMODIFIED, "Extent1" .COMPANY_ID AS company_id, "Extent1" .ORG_ID AS org_ID, "Extent1" .SUBTAB_ID AS SUBTAB_ID, "Extent1" .USER_ID AS USER_ID, «Extent1 ".COMPANY_SECTION AS COMPANY_SECTION FROM AIP.CO_COMMENT" Extent1 " WHERE (" Extent1 ".COMPANY_ID =: p__linq__49) И (" Extent1 ".DATEMODIFIED> = (CAST (: p__linq) __53 AS TIMESTAMP (9)))) – echo

+0

Очень полезно. Можете ли вы разместить значение objectQuery.Parameters («p__linq__53»)? –

ответ

2

UPDATE: К сожалению, я забыл, что с помощью LINQ для лиц, все WHERE выражений переводятся в SQL вызовов вместо того, чтобы после обработки в code-- поэтому предложения отладки ниже, не обязательно будут работать.

Поэтому я начал бы запускать сгенерированный оператор SQL в отношении вашей базы данных и проверять, действительно ли SQL, созданный вашим провайдером Entity Framework, возвращает ожидаемые данные. Комментарий @Craig Stuntz выше, безусловно, на правильном пути здесь, чтобы помочь вам в этом. Когда у вас есть параметризованный SQL, я бы попытался выполнить этот SQL непосредственно из вашего кода (используя System.Data.OracleClient) и подтвердив, что вы действительно получаете результаты от этого запроса. Не забудьте ввести те же значения параметров, которые вы получаете от ObjectQuery.Parameters. Кроме того, вы можете вставлять параметры в себя и выполнять запрос из своего клиентского приложения Oracle.

Если вы не получили результаты этого SQL, возможно, поставщик провайдера DevArt неправильно создает запрос.

вы можете игнорировать то, что ниже здесь, так как это относится к устранению неполадок LINQ к объектам, но не LINQ к Entities

Некоторые идеи для диагностики этого:

первых, попробуйте это в вашем окно просмотра:

q.Where(Function(c) startDate.Value <= c.DATEMODIFIED).Count() 

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

Далее, я хотел бы попробовать, чтобы определить ваш запрос LINQ немного differently-- вместо прилагая где() отдельно, попробуйте использовать два запроса, например:

Dim q As ObjectQuery(Of COMMENT) 
If startDate.HasValue Then 
    q = (From c In model.COMMENT Where startDate.Value <= c.DATEMODIFIED Select c) 
Else 
    q = (From c In model.COMMENT Select c) 
End If 

Если это работает, то что-то не так с тем, как предложение Where привязано к вашему существующему запросу LINQ - возможно, ошибка в провайдере сущностей СУБД?

Если это все еще не работает, следующим шагом, который я бы предпринял для диагностики, является проверка того, что код внутри предложения where вызывается, и проверка значений, переданных в этот код. Я не мог понять, как установить внутристрочные точки останова в VB, как это можно сделать на C#, но вы можете легко (временно) реорганизовать свою лямбду в отдельную функцию и установить там точку останова.Например:

Sub Main() 
    Dim testDate As Date = New Date(2005, 1, 1) 
    Dim x = New List(Of Date?) 
    x.Add(New Date(2009, 1, 1)) 
    x.Add(New Date(2008, 1, 1)) 
    x.Add(New Date(2007, 1, 1)) 
    x.Add(New Date(2006, 1, 1)) 
    x.Add(New Date(2005, 1, 1)) 
    x.Add(New Date(2004, 1, 1)) 
    x.Add(New Date(2003, 1, 1)) 
    x.Add(New Date(2002, 1, 1)) 
    x.Add(New Date(2001, 1, 1)) 
    Dim y = From n In x Select n 
    y = y.Where(Function(val) test(val, testDate)) 
    Dim z = y.ToArray() 
End Sub 

Function test(ByVal date1 As Date, ByVal date2 As Date) As Boolean 
    test = date1 >= date2 
End Function 

Проверьте значения, отправленные в вашу функцию сравнения, являются ли они действительными? Сравнивает ли сравнение то, что вы ожидаете от этого?

+0

Justin, спасибо за ваш ответ. Когда я попробовал ваше первое предложение, он сказал: «Оценка лямбда-выражений недействительна в отладчике». Однако q.tolist(). Count() действительно возвращает 0. Для вашего второго предложения переупорядочение запроса не имело никакого значения. Наконец, определив функцию «test()» и заменив ее на <= сравнение, вызванная Entity Framework выбрала исключение (немного перефразируемое здесь): System.NotSupportedException: LINQ to Entities не распознает метод 'Test' метод, и этот метод не может быть переведен в выражение хранилища – echo

+0

СУБД - это Oracle 10g, а поставщик EF - DevArt dotConnect для oracle. – echo