Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit d3f63cc

Browse files
committed
Issue #211: Ensure the DateTime is UTC
For MS SQL Server
1 parent 75976eb commit d3f63cc

File tree

3 files changed

+179
-112
lines changed

3 files changed

+179
-112
lines changed

src/ServiceStack.OrmLite.SqlServer/SqlServerOrmLiteDialectProvider.cs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ public override object ConvertDbValue(object value, Type type)
9999
return dateTimeValue - timeSpanOffset;
100100
}
101101

102+
if (_ensureUtc && type == typeof (DateTime))
103+
{
104+
var result = (DateTime)base.ConvertDbValue(value, type);
105+
return DateTime.SpecifyKind(result, DateTimeKind.Utc);
106+
}
107+
102108
if (type == typeof(byte[]))
103109
return value;
104110

@@ -111,7 +117,7 @@ public override object ConvertDbValue(object value, Type type)
111117
}
112118

113119

114-
public override string GetQuotedValue(object value, Type fieldType)
120+
public override string GetQuotedValue(object value, Type fieldType)
115121
{
116122
if (value == null) return "NULL";
117123

@@ -122,7 +128,9 @@ public override string GetQuotedValue(object value, Type fieldType)
122128
}
123129
if (fieldType == typeof(DateTime))
124130
{
125-
var dateValue = (DateTime)value;
131+
var dateValue = (DateTime)value;
132+
if (_ensureUtc && dateValue.Kind == DateTimeKind.Local)
133+
dateValue = dateValue.ToUniversalTime();
126134
const string iso8601Format = "yyyyMMdd HH:mm:ss.fff";
127135
return base.GetQuotedValue(dateValue.ToString(iso8601Format), typeof(string));
128136
}
@@ -143,16 +151,22 @@ public override string GetQuotedValue(object value, Type fieldType)
143151
return base.GetQuotedValue(value, fieldType);
144152

145153

146-
}
147-
148-
protected bool _useDateTime2;
149-
public void UseDatetime2(bool shouldUseDatetime2)
150-
{
151-
_useDateTime2 = shouldUseDatetime2;
152-
DateTimeColumnDefinition = shouldUseDatetime2 ? "datetime2" : "datetime";
153-
base.DbTypeMap.Set<DateTime>(shouldUseDatetime2 ? DbType.DateTime2 : DbType.DateTime, DateTimeColumnDefinition);
154-
base.DbTypeMap.Set<DateTime?>(shouldUseDatetime2 ? DbType.DateTime2 : DbType.DateTime, DateTimeColumnDefinition);
155-
}
154+
}
155+
156+
protected bool _useDateTime2;
157+
public void UseDatetime2(bool shouldUseDatetime2)
158+
{
159+
_useDateTime2 = shouldUseDatetime2;
160+
DateTimeColumnDefinition = shouldUseDatetime2 ? "datetime2" : "datetime";
161+
base.DbTypeMap.Set<DateTime>(shouldUseDatetime2 ? DbType.DateTime2 : DbType.DateTime, DateTimeColumnDefinition);
162+
base.DbTypeMap.Set<DateTime?>(shouldUseDatetime2 ? DbType.DateTime2 : DbType.DateTime, DateTimeColumnDefinition);
163+
}
164+
165+
protected bool _ensureUtc;
166+
public void EnsureUtc(bool shouldEnsureUtc)
167+
{
168+
_ensureUtc = shouldEnsureUtc;
169+
}
156170

157171
public override long GetLastInsertId(IDbCommand dbCmd)
158172
{
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
using System.Data;
3+
using System.Linq;
4+
using NUnit.Framework;
5+
using ServiceStack.OrmLite.SqlServer;
6+
7+
namespace ServiceStack.OrmLite.SqlServerTests
8+
{
9+
internal class EnsureUtcTests : OrmLiteTestBase
10+
{
11+
[Test]
12+
public void SaveDateTimeToDatabase()
13+
{
14+
var dbFactory = new OrmLiteConnectionFactory(base.ConnectionString, SqlServerOrmLiteDialectProvider.Instance);
15+
SqlServerOrmLiteDialectProvider.Instance.EnsureUtc(true);
16+
17+
using (var db = dbFactory.OpenDbConnection())
18+
{
19+
var dateTime = new DateTime(2012, 1, 1, 1, 1, 1, DateTimeKind.Local);
20+
var x = InsertAndSelectDateTime(db, dateTime);
21+
Assert.AreEqual(DateTimeKind.Utc, x.Test.Kind);
22+
Assert.AreEqual(x.Test.ToUniversalTime(), dateTime.ToUniversalTime());
23+
Assert.AreEqual(x.Test.ToLocalTime(), dateTime.ToLocalTime());
24+
25+
dateTime = new DateTime(2012, 1, 1, 1, 1, 1, DateTimeKind.Utc);
26+
x = InsertAndSelectDateTime(db, dateTime);
27+
Assert.AreEqual(DateTimeKind.Utc, x.Test.Kind);
28+
Assert.AreEqual(x.Test.ToUniversalTime(), dateTime.ToUniversalTime());
29+
Assert.AreEqual(x.Test.ToLocalTime(), dateTime.ToLocalTime());
30+
31+
dateTime = new DateTime(2012, 1, 1, 1, 1, 1, DateTimeKind.Unspecified);
32+
x = InsertAndSelectDateTime(db, dateTime);
33+
Assert.AreEqual(DateTimeKind.Utc, x.Test.Kind);
34+
Assert.AreEqual(x.Test.ToUniversalTime(), dateTime);
35+
Assert.AreEqual(x.Test.ToLocalTime(), dateTime.ToLocalTime());
36+
}
37+
}
38+
39+
private static DateTimeObject InsertAndSelectDateTime(IDbConnection db, DateTime dateTime)
40+
{
41+
db.DropAndCreateTable<DateTimeObject>();
42+
db.Insert(new DateTimeObject {Test = dateTime});
43+
var x = db.Select<DateTimeObject>().First();
44+
return x;
45+
}
46+
47+
private class DateTimeObject
48+
{
49+
public DateTime Test { get; set; }
50+
}
51+
}
52+
}
Lines changed: 101 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,108 @@
1-
<?xml version="1.0" encoding="utf-8"?>
2-
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3-
<PropertyGroup>
4-
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5-
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6-
<ProductVersion>8.0.30703</ProductVersion>
7-
<SchemaVersion>2.0</SchemaVersion>
8-
<ProjectGuid>{96793C11-2A99-4217-8946-3E0DB9534A4D}</ProjectGuid>
9-
<OutputType>Library</OutputType>
10-
<AppDesignerFolder>Properties</AppDesignerFolder>
11-
<RootNamespace>ServiceStack.OrmLite.SqlServerTests</RootNamespace>
12-
<AssemblyName>ServiceStack.OrmLite.SqlServerTests</AssemblyName>
13-
<FileAlignment>512</FileAlignment>
14-
</PropertyGroup>
15-
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16-
<DebugSymbols>true</DebugSymbols>
17-
<DebugType>full</DebugType>
18-
<Optimize>false</Optimize>
19-
<OutputPath>bin\Debug\</OutputPath>
20-
<DefineConstants>DEBUG;TRACE</DefineConstants>
21-
<ErrorReport>prompt</ErrorReport>
22-
<WarningLevel>4</WarningLevel>
23-
</PropertyGroup>
24-
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25-
<DebugType>pdbonly</DebugType>
26-
<Optimize>true</Optimize>
27-
<OutputPath>bin\Release\</OutputPath>
28-
<DefineConstants>TRACE</DefineConstants>
29-
<ErrorReport>prompt</ErrorReport>
30-
<WarningLevel>4</WarningLevel>
31-
</PropertyGroup>
32-
<ItemGroup>
33-
<Reference Include="nunit.framework">
34-
<HintPath>..\..\lib\tests\nunit.framework.dll</HintPath>
35-
</Reference>
36-
<Reference Include="ServiceStack.Common">
37-
<HintPath>..\..\lib\ServiceStack.Common.dll</HintPath>
38-
</Reference>
39-
<Reference Include="ServiceStack.Interfaces">
40-
<HintPath>..\..\lib\ServiceStack.Interfaces.dll</HintPath>
41-
</Reference>
42-
<Reference Include="ServiceStack.Text">
43-
<HintPath>..\..\lib\ServiceStack.Text.dll</HintPath>
44-
</Reference>
45-
<Reference Include="System" />
46-
<Reference Include="System.ComponentModel.DataAnnotations" />
47-
<Reference Include="System.configuration" />
48-
<Reference Include="System.Core" />
49-
<Reference Include="System.Xml.Linq" />
50-
<Reference Include="System.Data.DataSetExtensions" />
51-
<Reference Include="Microsoft.CSharp" />
52-
<Reference Include="System.Data" />
53-
<Reference Include="System.Xml" />
54-
</ItemGroup>
55-
<ItemGroup>
56-
<Compile Include="Datetime2Tests.cs" />
57-
<Compile Include="InsertParam_GetLastInsertId.cs" />
58-
<Compile Include="NestedTransactions.cs" />
59-
<Compile Include="EnumTests.cs" />
60-
<Compile Include="Expressions\AdditiveExpressionsTest.cs" />
61-
<Compile Include="Expressions\Author.cs" />
62-
<Compile Include="Expressions\AuthorUseCase.cs" />
63-
<Compile Include="Expressions\ConditionalExpressionTest.cs" />
64-
<Compile Include="Expressions\EqualityExpressionsTest.cs" />
65-
<Compile Include="Expressions\ExpressionsTestBase.cs" />
66-
<Compile Include="Expressions\LogicalExpressionsTest.cs" />
67-
<Compile Include="Expressions\MultiplicativeExpressionsTest.cs" />
68-
<Compile Include="Expressions\OrmLiteCountTests.cs" />
69-
<Compile Include="Expressions\PrimaryExpressionsTest.cs" />
70-
<Compile Include="Expressions\RelationalExpressionsTest.cs" />
71-
<Compile Include="Expressions\StringFunctionTests.cs" />
72-
<Compile Include="Expressions\TestType.cs" />
73-
<Compile Include="Expressions\UnaryExpressionsTest.cs" />
74-
<Compile Include="ForeignKeyAttributeTests.cs" />
75-
<Compile Include="OrmLiteTestBase.cs" />
76-
<Compile Include="SqlServerExpressionVisitorQueryTest.cs" />
77-
<Compile Include="Properties\AssemblyInfo.cs" />
78-
<Compile Include="TypeWithByteArrayFieldTests.cs" />
79-
<Compile Include="UnicodeTests.cs" />
80-
<Compile Include="UpdateTests.cs" />
81-
<Compile Include="UseCase\SimpleUseCase.cs" />
82-
<Compile Include="UseCase\TestEntity.cs" />
83-
</ItemGroup>
84-
<ItemGroup>
85-
<ProjectReference Include="..\ServiceStack.OrmLite.SqlServer\ServiceStack.OrmLite.SqlServer.csproj">
86-
<Project>{1887DC99-9139-43E3-A7AA-6D74714B3A5D}</Project>
87-
<Name>ServiceStack.OrmLite.SqlServer</Name>
88-
</ProjectReference>
89-
<ProjectReference Include="..\ServiceStack.OrmLite\ServiceStack.OrmLite.csproj">
90-
<Project>{96179AC6-F6F1-40C3-9FDD-4F6582F54C5C}</Project>
91-
<Name>ServiceStack.OrmLite</Name>
92-
</ProjectReference>
93-
</ItemGroup>
94-
<ItemGroup>
95-
<None Include="app.config">
96-
<SubType>Designer</SubType>
97-
</None>
98-
</ItemGroup>
99-
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6+
<ProductVersion>8.0.30703</ProductVersion>
7+
<SchemaVersion>2.0</SchemaVersion>
8+
<ProjectGuid>{96793C11-2A99-4217-8946-3E0DB9534A4D}</ProjectGuid>
9+
<OutputType>Library</OutputType>
10+
<AppDesignerFolder>Properties</AppDesignerFolder>
11+
<RootNamespace>ServiceStack.OrmLite.SqlServerTests</RootNamespace>
12+
<AssemblyName>ServiceStack.OrmLite.SqlServerTests</AssemblyName>
13+
<FileAlignment>512</FileAlignment>
14+
</PropertyGroup>
15+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16+
<DebugSymbols>true</DebugSymbols>
17+
<DebugType>full</DebugType>
18+
<Optimize>false</Optimize>
19+
<OutputPath>bin\Debug\</OutputPath>
20+
<DefineConstants>DEBUG;TRACE</DefineConstants>
21+
<ErrorReport>prompt</ErrorReport>
22+
<WarningLevel>4</WarningLevel>
23+
</PropertyGroup>
24+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25+
<DebugType>pdbonly</DebugType>
26+
<Optimize>true</Optimize>
27+
<OutputPath>bin\Release\</OutputPath>
28+
<DefineConstants>TRACE</DefineConstants>
29+
<ErrorReport>prompt</ErrorReport>
30+
<WarningLevel>4</WarningLevel>
31+
</PropertyGroup>
32+
<ItemGroup>
33+
<Reference Include="nunit.framework">
34+
<HintPath>..\..\lib\tests\nunit.framework.dll</HintPath>
35+
</Reference>
36+
<Reference Include="ServiceStack.Common">
37+
<HintPath>..\..\lib\ServiceStack.Common.dll</HintPath>
38+
</Reference>
39+
<Reference Include="ServiceStack.Interfaces">
40+
<HintPath>..\..\lib\ServiceStack.Interfaces.dll</HintPath>
41+
</Reference>
42+
<Reference Include="ServiceStack.Text">
43+
<HintPath>..\..\lib\ServiceStack.Text.dll</HintPath>
44+
</Reference>
45+
<Reference Include="System" />
46+
<Reference Include="System.ComponentModel.DataAnnotations" />
47+
<Reference Include="System.configuration" />
48+
<Reference Include="System.Core" />
49+
<Reference Include="System.Xml.Linq" />
50+
<Reference Include="System.Data.DataSetExtensions" />
51+
<Reference Include="Microsoft.CSharp" />
52+
<Reference Include="System.Data" />
53+
<Reference Include="System.Xml" />
54+
</ItemGroup>
55+
<ItemGroup>
56+
<Compile Include="Datetime2Tests.cs" />
57+
<Compile Include="EnsureUtcTest.cs" />
58+
<Compile Include="InsertParam_GetLastInsertId.cs" />
59+
<Compile Include="NestedTransactions.cs" />
60+
<Compile Include="EnumTests.cs" />
61+
<Compile Include="Expressions\AdditiveExpressionsTest.cs" />
62+
<Compile Include="Expressions\Author.cs" />
63+
<Compile Include="Expressions\AuthorUseCase.cs" />
64+
<Compile Include="Expressions\ConditionalExpressionTest.cs" />
65+
<Compile Include="Expressions\EqualityExpressionsTest.cs" />
66+
<Compile Include="Expressions\ExpressionsTestBase.cs" />
67+
<Compile Include="Expressions\LogicalExpressionsTest.cs" />
68+
<Compile Include="Expressions\MultiplicativeExpressionsTest.cs" />
69+
<Compile Include="Expressions\OrmLiteCountTests.cs" />
70+
<Compile Include="Expressions\PrimaryExpressionsTest.cs" />
71+
<Compile Include="Expressions\RelationalExpressionsTest.cs" />
72+
<Compile Include="Expressions\StringFunctionTests.cs" />
73+
<Compile Include="Expressions\TestType.cs" />
74+
<Compile Include="Expressions\UnaryExpressionsTest.cs" />
75+
<Compile Include="ForeignKeyAttributeTests.cs" />
76+
<Compile Include="OrmLiteTestBase.cs" />
77+
<Compile Include="SqlServerExpressionVisitorQueryTest.cs" />
78+
<Compile Include="Properties\AssemblyInfo.cs" />
79+
<Compile Include="TypeWithByteArrayFieldTests.cs" />
80+
<Compile Include="UnicodeTests.cs" />
81+
<Compile Include="UpdateTests.cs" />
82+
<Compile Include="UseCase\SimpleUseCase.cs" />
83+
<Compile Include="UseCase\TestEntity.cs" />
84+
</ItemGroup>
85+
<ItemGroup>
86+
<ProjectReference Include="..\ServiceStack.OrmLite.SqlServer\ServiceStack.OrmLite.SqlServer.csproj">
87+
<Project>{1887DC99-9139-43E3-A7AA-6D74714B3A5D}</Project>
88+
<Name>ServiceStack.OrmLite.SqlServer</Name>
89+
</ProjectReference>
90+
<ProjectReference Include="..\ServiceStack.OrmLite\ServiceStack.OrmLite.csproj">
91+
<Project>{96179AC6-F6F1-40C3-9FDD-4F6582F54C5C}</Project>
92+
<Name>ServiceStack.OrmLite</Name>
93+
</ProjectReference>
94+
</ItemGroup>
95+
<ItemGroup>
96+
<None Include="app.config">
97+
<SubType>Designer</SubType>
98+
</None>
99+
</ItemGroup>
100+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
100101
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
101102
Other similar extension points exist, see Microsoft.Common.targets.
102103
<Target Name="BeforeBuild">
103104
</Target>
104105
<Target Name="AfterBuild">
105106
</Target>
106-
-->
107+
-->
107108
</Project>

0 commit comments

Comments
 (0)