我有一个使用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
答案 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;
因此...
string myInput = "19-May-2010";
DateTime myDate = Convert.ToDateTime(myInput);
IQueryable<TestTable> cus =
from x in _dataContext.testTable
where x.CreateDate == myDate
select x;
响应更新。
答案 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)
我知道您可能已经检查了这一点,但是您可以验证以下内容:
基于您在LinqPad中看到查询成功的事实,我怀疑CreateDate属性或该字段的SQL定义有问题。我真的怀疑你的Linq-to-SQL输出说“WHERE([t0]。[CreateDate] = '19 / 05/2010 00:00:00')”而不是“WHERE([t0]。[CreateDate] ] = @ p0)“。