c# - 从 LINQ to SQL 调用 SQL Server 存储过程时无法将 nvarchar 转换为日期时间

标签 c# sql-server linq wcf localization

我有一个应用程序服务器连接到另一台使用 SQL Server 2008R2 的服务器。两台服务器的 GUI 都是法语,并且日期和数字格式都是法语。 SQL Server 和用于执行命令语言的用户也设置为法语(全部默认)。但是,我将 WCF 服务中的格式设置为“en-GB”,方法是将其放入 web.config 中:

我在 LINQ to SQL dbcontext 文件中包含了一个存储过程,并且传递了一个日期参数,但没有将其转换为字符串(因为 ORM 将其识别为日期)。

事情进展顺利,直到今天早些时候,程序停止执行并抛出异常,指出字符串无法转换为日期。

我使用 SQL Profiler 跟踪了该查询,发现它正在执行以下查询:

declare @p9 int
set @p9=NULL
exec sp_executesql N'EXEC @RETURN_VALUE = [GIS].[GetOnlineTrackingRecords] 
@CompanyId = @p0, @EntityIds = @p1, @MinDate = @p2, @MinRecordId = @p3, @TrackingType = @p4, @TrackAllEntities = @p5', N'@p0 int,@p1 varchar(8000),@p2 datetime,@p3 bigint,@p4 tinyint,@p5 bit,@RETURN_VALUE int output',
@p0=1,@p1='168',@p2='2013-10-24 16:36:28.690',@p3=NULL,@p4=1,@p5=0,@RETURN_VALUE=@p9 output 
select @p9

(@p2 的主要问题)

包装我的存储过程的 ORM 方法如下所示:

[global::System.Data.Linq.Mapping.FunctionAttribute(Name= "GIS.GetOnlineTrackingRecords")]
public ISingleResult<FMS2.Framework.TrackEntities.GetOnlineTrackingRecordsResult> GetOnlineTrackingRecords([global::System.Data.Linq.Mapping.ParameterAttribute(Name="CompanyId", DbType="Int")] System.Nullable<int> companyId, [global::System.Data.Linq.Mapping.ParameterAttribute(Name="EntityIds", DbType="VarChar(MAX)")] string entityIds, [global::System.Data.Linq.Mapping.ParameterAttribute(Name="MinDate", DbType="DateTime")] System.Nullable<System.DateTime> minDate, [global::System.Data.Linq.Mapping.ParameterAttribute(Name="MinRecordId", DbType="BigInt")] System.Nullable<long> minRecordId, [global::System.Data.Linq.Mapping.ParameterAttribute(Name="TrackingType", DbType="TinyInt")] System.Nullable<byte> trackingType, [global::System.Data.Linq.Mapping.ParameterAttribute(Name="TrackAllEntities", DbType="Bit")] System.Nullable<bool> trackAllEntities)
    {
        IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), companyId, entityIds, minDate, minRecordId, trackingType, trackAllEntities);
        return ((ISingleResult<FMS2.Framework.TrackEntities.GetOnlineTrackingRecordsResult>)(result.ReturnValue));
    }

当我尝试在 SQL Server Management Studio 中执行相同的查询时,它失败了,但它在我的计算机上成功运行(使用英语 SQL Server)。在我将 SQL Server 引擎的语言和用户默认语言更改为 us_english 后,它运行得很好,但只能从 SQL Server 运行,并且当从我的 WCF 应用程序调用时,它仍然失败并显示相同的错误消息。我已经使用 sys.dm_exec_sessions 和 SQL Profiler 仔细检查了查询是否正在使用 us_english 语言的用户下执行。我读过从 'yyyy-MM-dd HH:mm:ss' 字符串到迄今为止的转换应该在任何机器上都能正常工作,但似乎不行:( 考虑到接触代码会非常困难,我接下来该怎么办...

谢谢

最佳答案

您不应该传递像 yyyy-mm-dd hh:mm:ss 这样的字符串。原因如下:

SET LANGUAGE FRENCH;
SELECT CONVERT(DATETIME, '2013-05-06');

这将返回 6 月 5 日,而不是 5 月 6 日,因为它被解释为 yyyy-dd-mm。如果您输入日期 ('2013-10-24'),您会收到错误消息,因为 SQL Server 不知道 24 月是什么。

现在,我不知道如何在 ORM 中执行操作,但理想情况下,您根本不应该传递字符串,因此格式并不重要。您应该传递日期/时间值,而不是字符串。

当你确实需要传递一个字符串时(你可能会再次因为我不知道你选择的 ORM 的局限性,我只知道没有一个 ORM 涵盖所有基础),你应该始终使用 100%明确的格式。尝试:

@p2='2013-10-24T16:36:28.690'
---------------^ that T is important

让我为 Alireza 解释一下原因。 From this document :

If a date and a time are displayed on the same line, then always write the date in front of the time. If a date and a time value are stored together in a single data field, then ISO 8601 suggests that they should be separated by a latin capital letter T, as in 19951231T235959.

添加 T 后,您将删除 SQL Server 以任何其他方式解释日期的能力。这并不是因为它是 T,甚至不是因为 ISO 8601 建议的内容,而是因为 SQL Server 中的代码简单地说,如果有 T,则将日期解释为 y-m-d,无论区域、区域设置、日期格式或语言设置如何。

关于c# - 从 LINQ to SQL 调用 SQL Server 存储过程时无法将 nvarchar 转换为日期时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19576938/

相关文章:

java - 通过 Java 获取创建和填充的 MSSQL 临时表的结果集

c# - 将一个数组的顺序与另一个数组匹配

sql - Linq to SQL 左外连接不

c# - 无法在 GridView 中持久化数据

c# - FluentValidation 中基于父数据的验证

sql-server - 存储过程中结果集的总数

.net - 使用.NET复制管理对象RMO的Powershell问题

c# - .net 框架错误 (HRESULT 0x8007000B)

c# - 在 Visual Studio 2015 中捕获解决方案事件

linq - LINQ 除外如何工作?