【问题标题】:Problem with Linq query and date formatLinq 查询和日期格式的问题
【发布时间】:2010-06-16 16:00:02
【问题描述】:

我有一个使用 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 滥用的 cmets,但这不是我的问题。我的问题是,在从 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 子句如下所示:

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

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

我尝试了以下 where 子句:

where x.CreateDate == DateTime.Today

但仍然出现错误。

附加信息:

SQL Server 查询可视化工具:

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 不同的格式显示日期。

谢谢。

艾伦·T

【问题讨论】:

    标签: c# sql linq-to-sql


    【解决方案1】:

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

    原文:

    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

    【讨论】:

    • 嗨,大卫,我尝试了你的建议,但仍然出现错误。我在我的问题中添加了更多信息。
    • 嗨,Daivd,感谢您的链接。我不想在数据库级别设置任何东西,因为还有其他数据库正在运行。至于登录默认设置,我将用户的语言从英语更改为英式英语,并不高兴。关于每个连接,我不知道如何通过 Linq 实现这一点。我认为数据库服务器是问题所在,因为在开发服务器和实时服务器上运行 SQL 版本的查询时遇到相同的错误。
    • var 使代码的可读性降低。如果您从查询开始阅读,您可以看到使用了 myDate。如果你想知道 myDate 的类型,你需要查看它的声明。声明没有告诉你,所以现在你需要看看它的初始化。相反,第一个程序员可以将类型放入其中并为编译器和所有未来的程序员节省更多的推理步骤。
    • 您可以将鼠标悬停在 var 上,VS 会告诉您。
    【解决方案2】:

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

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

    【讨论】:

    • 如果你确实需要接受输入作为字符串并转换它,使用 dcp 的 sn-p。如果您不是绝对需要使用字符串,请避免使用。
    • 嗨,比尔,我从 DateTime.Now.Date 开始,遇到了同样的问题。弦乐是我的第二次尝试。有趣的是,如果我将字符串放在 where 子句中,它就可以工作!
    • 这很奇怪,但我猜在 linq 构建实际的 sql 查询时,它会将日期字符串输出为 en-US 而不是 en-GB。查看用于进行日期比较的输出 sql 会很有趣。
    【解决方案3】:

    你可以使用:

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

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

    【讨论】:

    • 您好,dcp,我尝试了您的建议,但仍然出现错误。我已将错误详细信息添加到我的问题中。
    【解决方案4】:

    正如比尔所说,不要使用字符串来表示日期。 LINQ to SQL 使用参数化查询来传递参数,因此您应该不会对语言环境有任何问题 - 前提是您的数据库字段和参数都是 both 日期。

    您可以通过将 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 类型的参数并返回了正确的条目。

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

    【讨论】:

    • 您好 Panagiotis,我收到以下错误:System.Data.SqlClient.SqlException:将 char 数据类型转换为日期时间数据类型导致日期时间值超出范围
    • 您能否发布由 LINQ to SQL 生成的整个语句,包括提供程序 cmets? LINQ 总是使用参数化查询来传递参数。它不应该创建您已经发布的 WHERE 语句。
    • 您好 Panagiotis,我已在我的问题中添加了更多信息。
    【解决方案5】:

    当你尝试这个时会发生什么

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

    【讨论】:

    • 嗨 Madhivanan,我收到以下错误:“System.InvalidCastException: Specified cast is not valid”
    【解决方案6】:

    我知道您可能检查过这个,但您能否验证以下内容:

    1. CreateDate 在数据库中被声明为 DateTime 或 DateTime2
    2. Linqed 类中的 CreateDate 属性声明为 .NET DateTime
    3. System.Linq.Mapping.ColumnAttribute 已在 Linqed up 类的 CreateDate 属性上正确定义。

    基于您在 LinqPad 中看到查询成功的事实,我怀疑 CreateDate 属性或该字段的 SQL 定义有问题。我真的很怀疑您的 Linq-to-SQL 输出显示“WHERE ([t0].[CreateDate] = '19/05/2010 00:00:00')”而不是“WHERE ([t0].[CreateDate ] = @p0)"。

    【讨论】:

    • 您好 mattmc3,我已在我的问题中添加了更多信息。
    猜你喜欢
    • 2019-05-20
    • 2017-04-21
    • 2021-07-08
    • 2011-07-29
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多