Linq查询和日期格式的问题

时间:2010-06-16 16:00:03

标签: c# sql linq-to-sql

我有一个使用Visual Studio 2008编写的C#控制台应用程序。

我的系统文化是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,它似乎也试图将其表示为en-US日期。

我是如何解决这个问题的?

编辑:感谢有关魔术字符串和var滥用的评论,但这不是我的问题。我的问题是,在从Linq到SQL的转换中,日期被解释为美国格式日期(19/05/2010被解释为:第19个月,第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子句如下所示:

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

请注意,完全相同的Linq查询在LinqPad中完美运行。

我尝试过以下where子句:

where x.CreateDate == DateTime.Today

仍然得到错误。

其他信息:

SQL Server Query 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

6 个答案:

答案 0 :(得分:2)

简短回答是“不要使用字符串来表示日期”。

假设CreateDate列是SQL Server日期时间,您应该能够与.NET DateTime类进行比较。

答案 1 :(得分:2)

不要将本地字符串发送到数据库并要求数据库将这些字符串转换为DateTimes。只是不要。

最初:

var myDate = "19-May-2010"; 

var cus = from x in _dataContext.testTable 
  where x.CreateDate == Convert.ToDateTime(myDate) 
  select x; 
  • 不要滥用var。
  • 您希望在本地发生的操作中打算在数据库中执行的单独操作

因此...

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

答案 2 :(得分:1)

您可以使用:

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

当然,这假定您在数据库中的日期与您的myDate字段匹配(即如果您在日期中包含时间,则需要修改上述日期以包括时间部分。)

答案 3 :(得分:0)

比尔说,不要用字符串来表示日期。 LINQ to SQL使用参数化查询来传递参数,因此您不应该对区域设置有任何问题 - 前提是您的数据库字段和参数都是日期。

您可以通过将TextWriter对象(如Console.Out)附加到DataContext的Log属性来检查生成的SQL语句。以下代码

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,并返回正确的条目。

您遇到的错误究竟是什么?你得到例外还是得到不正确的结果? 如果没有结果,则数据库字段可能包含时间值,在这种情况下,它将不匹配仅包含日期值的参数

答案 4 :(得分:0)

尝试此操作时会发生什么

var myDate = "20100519"; 

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

答案 5 :(得分:0)

我知道您可能已经检查了这一点,但是您可以验证以下内容:

  1. CreateDate在数据库中声明为DateTime或DateTime2
  2. Linqed类中的CreateDate属性声明为.NET DateTime
  3. System.Linq.Mapping.ColumnAttribute已在Linqed up类的CreateDate属性中正确定义。
  4. 基于您在LinqPad中看到查询成功的事实,我怀疑CreateDate属性或该字段的SQL定义有问题。我真的怀疑你的Linq-to-SQL输出说“WHERE([t0]。[CreateDate] = '19 / 05/2010 00:00:00')”而不是“WHERE([t0]。[CreateDate] ] = @ p0)“。