2010-06-16 4 views
2

У меня есть консольное приложение C#, написанное с использованием Visual Studio 2008.Проблема с запросом Linq и форматом даты

Моя культура системы - en-GB. У меня есть запрос Linq, который выглядит следующим образом:

var myDate = "19-May-2010"; 

var cus = from x in _dataContext.testTable 
    where x.CreateDate == Convert.ToDateTime(myDate) 
    select x; 

В результате SQL-запрос генерирует и ошибки, потому что она возвращает даты, как «19/05/2010», который он интерпретирует как неправильную дату. По какой-то причине, несмотря на то, что моя системная культура настроена на en-GB, похоже, что она пытается заинтриговать ее как дату в США.

Любые идеи, как я обойти это?

Редактировать: Спасибо за комментарии о магических строках и var злоупотреблениях, но это не моя проблема. Моя проблема заключается в том, что при преобразовании из Linq в SQL даты интерпретируются как даты формата США (19/05/2010 интерпретируется как: месяц девятнадцатый, день 5 и год 2010), что приводит к следующей ошибке:

System.Data.SqlClient.SqlException: The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value 

где положение полученного запроса SQL выглядит следующим образом:

WHERE ([t0].[CreateDate] = '19/05/2010 00:00:00') 

Пожалуйста, обратите внимание, что точно такой же запрос Linq отлично работает в LINQPad.

Я попытался следующие, где положение:

where x.CreateDate == DateTime.Today 

и все еще получаю ошибку.

Дополнительная информация:

запросов SQL Server Visualizer:

SELECT [t0].[field1], [t0].[field2], [t0].[field3] AS [field4], [t0].[field5] 
FROM [dbo].[table] AS [t0] 
WHERE ([t0].[CreateDateTime] = '19/05/2010 00:00:00') 

Original query: 
SELECT [t0].[field1], [t0].[field2], [t0].[field3] AS [field4], [t0].[field5] 
FROM [dbo].[table] AS [t0] 
WHERE ([t0].[CreateDateTime] = @p0) 
------------------------------- 
@p0 [DateTime]: 19/05/2010 00:00:00 

LINQPad:

-- Region Parameters 
DECLARE @p0 DateTime SET @p0 = '2010-05-19 00:00:00.000' 
-- EndRegion 
SELECT [t0].[field1], [t0].[field2], [t0].[field3] AS [field4], [t0].[field5] 
FROM [table] AS [t0] 
WHERE ([t0].[CreateDateTime] = @p0) 

Выше я заметил, что LINQPad представляет дату в другом формате VS.

Спасибо.

Alan T

ответ

2

Не отправлять локальные строки в базу данных и запрашивать базу данных для преобразования эти строки в DateTimes. Только не надо.

Первоначально:

var myDate = "19-May-2010"; 

var cus = from x in _dataContext.testTable 
    where x.CreateDate == Convert.ToDateTime(myDate) 
    select x; 
  • Не злоупотребляйте вар.
  • Отдельные действия, которые вы собираетесь иметь место в базе данных от действий, которые вы намерены происходить локально

Итак ...

string myInput = "19-May-2010"; 
DateTime myDate = Convert.ToDateTime(myInput); 

IQueryable<TestTable> cus = 
    from x in _dataContext.testTable 
    where x.CreateDate == myDate 
    select x; 

В ответ на обновление.

  • Похоже, что ваше приложение отправляет правильно отформатированные даты, но использует соединение, которое ожидает неверно отформатированные даты.
  • Вы можете изменить каждое соединение или вы можете изменить настройки по умолчанию в Логин в: http://support.microsoft.com/kb/173907
+0

Привет, Дэвид, я попробовал ваше предложение и до сих пор получил ошибку. Я добавил дополнительную информацию к моему вопросу. –

+0

Привет, Дайв, спасибо за ссылку. Я не хочу ничего устанавливать на уровне базы данных, так как есть другие базы данных. Что касается параметров входа в систему, я сменил язык для пользователя с английского на английский, без радости. Что касается каждого соединения, я не знаю, как добиться этого через Linq. Я думаю, что сервер базы данных является проблемой, поскольку я получаю те же ошибки при запуске SQL-версии запроса на сервере разработки и в реальном времени. –

+1

Почему нет ошибок? – Hans

1

Вы можете использовать:

x.CreateDate == DateTime.ParseExact(myDate, "dd-MMM-yyyy", System.Globalization.CultureInfo.InvariantCulture); 

Это предполагает, конечно, что ваша дата в БД совпадает с вашим полем MyDate (т.е. если у вас есть время, включенную с датой, вы будете необходимо изменить выше, чтобы включить временную часть).

+0

Привет, dcp, я попробовал ваше предложение и все еще получил ошибку. Я добавил детали ошибки к моему вопросу. –

2

Короткий ответ - «не использовать строки для представления дат».

Предполагая, что столбец CreateDate является дата-сервером SQL Server, вы сможете просто сравнить свой класс с классом .NET DateTime.

+0

Если вам действительно нужно принять ввод как строку и преобразовать его, используйте фрагмент dcp.Если вам не обязательно использовать строки, избегайте их. – Bill

+0

Привет, Билл, я начал с DateTime.Now.Date и имел те же проблемы. Струны были моей второй попыткой. Интересно, если я поместил строку в предложение where, это сработает! –

+0

Это странно, но я думаю, что под обложками, когда linq создает фактический sql-запрос, он выводит строку даты как en-US вместо en-GB. Было бы интересно увидеть выходной sql для сравнения даты и даты. – Bill

0

Как сказал Билл, не используйте строки для представления дат. LINQ to SQL использует параметризованные запросы для передачи параметров, поэтому у вас не должно быть проблем с локалями - при условии, что поле вашей базы данных и ваш параметр равны как.

Вы можете проверить сгенерированный оператор SQL, прикрепив TextWriter объективистские (как Console.Out) к DataContext Вход property.The следующий код

using(var datacontext=new DatesDataContext()) 
{ 
    var myDate=DateTime.Today; 
    //Or, to specify a date without string parsing 
    //var myDate=new DateTime(2010,6,16); 
    var dates = from date in datacontext.DateTables 
     where date.DateField == myDate     
     select date; 

    datacontext.Log = Console.Out; 
    foreach (var date in dates) 
    { 
     Console.WriteLine(date.DateField); 
    } 
} 

произвел этот запрос

SELECT [t0].[DateField] 
FROM [dbo].[DateTable] AS [t0] 
WHERE [t0].[DateField] = @p0 
-- @p0: Input DateTime (Size = -1; Prec = 0; Scale = 0) [6/16/2010 12:00:00 AM] 
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1 

Как вам см., запрос имеет параметр типа DateTime и возвращает правильные записи.

В чем именно вы столкнулись? Вы получаете исключение или получаете неправильные результаты? Если вы не получили результатов, возможно, ваше поле базы данных содержит значение времени, и в этом случае оно не будет соответствовать параметру, который содержит только значение даты

+0

Привет Panagiotis, я получаю следующую ошибку: System.Data.SqlClient.SqlException: преобразование типа данных char в тип данных datetime привело к значению даты и времени вне диапазона –

+0

Можете ли вы опубликовать весь оператор, созданный LINQ к SQL, включая комментарии поставщика? LINQ всегда использует параметризованные запросы для передачи параметров. Он не должен был создавать оператор WHERE, который вы уже опубликовали. –

+0

Привет Panagiotis, я добавил больше информации на мой вопрос. –

0

Что происходит, когда вы попробуете это

var myDate = "20100519"; 

var cus = from x in _dataContext.testTable 
    where x.CreateDate == Convert.ToDateTime(myDate) 
    select x; 
+0

Привет, Madhivanan, я получил следующую ошибку: «System.InvalidCastException: Указанный приказ недействителен» –

0

Я знаю, что вы, вероятно, проверил это, но вы можете проверить следующее:

  1. CreateDate объявлен как DateTime или datetime2 в базе
  2. Th e Свойство CreateDate в вашем классе Linqed объявляется как .NET DateTime
  3. Свойство System.Linq.Mapping.ColumnAttribute определено правильно в свойстве CreateDate в вашем классе Linqed.

Основываясь на том, что вы видите успех с запросом в LinqPad, я подозреваю, что что-то не так с свойством CreateDate или с определением SQL этого поля. Я ДЕЙСТВИТЕЛЬНО подозрительно, что ваш вывод Linq-to-SQL говорит «WHERE ([t0]. [CreateDate] = '19/05/2010 00:00:00 ')» вместо «WHERE ([t0].] [CreateDate ] = @ p0) ".

+0

Привет mattmc3, я добавил больше информации на мой вопрос. –

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