Skip to content

Commit 1464f48

Browse files
fredericDelaportehazzik
authored andcommitted
NH-3919 - Use DateTime2 for dialects supporting it.
* NHibernate date time types (datetime, timestamp, localdatetime, utcdatetime, dbtimestamp) use db type datetime2 if dialect supports it. * NHibernate type datetime2 is obsolete. * Add test for NH-3984 by Ralf Kornelius
1 parent 168d2f7 commit 1464f48

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+994
-111
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using System;
12+
using System.Linq;
13+
using NHibernate.Dialect;
14+
using NUnit.Framework;
15+
using NHibernate.Linq;
16+
17+
namespace NHibernate.Test.NHSpecificTest.NH3984
18+
{
19+
using System.Threading.Tasks;
20+
[TestFixture]
21+
public class FixtureAsync : BugTestCase
22+
{
23+
protected override void OnTearDown()
24+
{
25+
using (var s = OpenSession())
26+
using (var tx = s.BeginTransaction())
27+
{
28+
s.CreateSQLQuery("delete from LogEntry").ExecuteUpdate();
29+
tx.Commit();
30+
}
31+
}
32+
33+
protected override bool AppliesTo(Dialect.Dialect dialect)
34+
{
35+
return dialect is MsSql2008Dialect;
36+
}
37+
38+
[Test]
39+
public async Task ShouldBePossibleToReadMillisecondsFromDatetime2ViaCreateSQLQueryAsync()
40+
{
41+
var now = DateTime.UtcNow;
42+
43+
using (var session = OpenSession())
44+
using (var transaction = session.BeginTransaction())
45+
{
46+
var entry = new LogEntry { Text = "Test", CreatedAt = now };
47+
await (session.SaveAsync(entry));
48+
49+
await (session.FlushAsync());
50+
await (transaction.CommitAsync());
51+
}
52+
53+
using (var session = OpenSession())
54+
{
55+
var datetimeViaQuery = await (session
56+
.Query<LogEntry>()
57+
.Select(x => x.CreatedAt)
58+
.SingleAsync());
59+
60+
Assert.That(datetimeViaQuery.Millisecond, Is.EqualTo(now.Millisecond));
61+
62+
var datetimeViaCreateSqlQuery = (await (session
63+
.CreateSQLQuery("SELECT CreatedAt FROM LogEntry")
64+
.ListAsync()))
65+
.Cast<DateTime>()
66+
.Single();
67+
68+
Assert.That(datetimeViaCreateSqlQuery.Millisecond, Is.EqualTo(now.Millisecond));
69+
}
70+
}
71+
72+
[Test]
73+
public async Task ShouldBePossibleToReadTicksFromDatetime2ViaCreateSQLQueryAsync()
74+
{
75+
var now = DateTime.Now;
76+
77+
using (var session = OpenSession())
78+
using (var transaction = session.BeginTransaction())
79+
{
80+
var entry = new LogEntry { Text = "Test", CreatedAt = now };
81+
await (session.SaveAsync(entry));
82+
83+
await (session.FlushAsync());
84+
await (transaction.CommitAsync());
85+
}
86+
87+
using (var session = OpenSession())
88+
{
89+
var datetimeViaQuery = await (session
90+
.Query<LogEntry>()
91+
.Select(x => x.CreatedAt)
92+
.SingleAsync());
93+
94+
Assert.That(datetimeViaQuery.Ticks, Is.EqualTo(now.Ticks));
95+
96+
var datetimeViaCreateSqlQuery = (await (session
97+
.CreateSQLQuery("SELECT CreatedAt FROM LogEntry")
98+
.ListAsync()))
99+
.Cast<DateTime>()
100+
.Single();
101+
102+
Assert.That(datetimeViaCreateSqlQuery.Ticks, Is.EqualTo(now.Ticks));
103+
}
104+
}
105+
}
106+
}

src/NHibernate.Test/Async/TypesTest/DateTime2TypeFixture.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace NHibernate.Test.TypesTest
2020
/// TestFixtures for the <see cref="DateTimeType"/>.
2121
/// </summary>
2222
[TestFixture]
23+
[Obsolete]
2324
public class DateTime2TypeFixtureAsync
2425
{
2526
[Test]
@@ -39,4 +40,4 @@ public async Task SeedAsync()
3940
Assert.IsTrue(await (type.SeedAsync(null, CancellationToken.None)) is DateTime, "seed should be DateTime");
4041
}
4142
}
42-
}
43+
}

src/NHibernate.Test/Async/TypesTest/DateTimeTypeFixture.cs

Lines changed: 191 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,18 @@
99

1010

1111
using System;
12+
using System.Collections.Generic;
13+
using System.Data;
14+
using System.Data.Common;
15+
using System.Linq;
16+
using NHibernate.Cfg;
17+
using NHibernate.Driver;
18+
using NHibernate.Engine;
19+
using NHibernate.SqlCommand;
20+
using NHibernate.SqlTypes;
21+
using NHibernate.Tool.hbm2ddl;
1222
using NHibernate.Type;
23+
using NHibernate.Util;
1324
using NUnit.Framework;
1425

1526
namespace NHibernate.Test.TypesTest
@@ -25,20 +36,193 @@ public class DateTimeTypeFixtureAsync
2536
[Test]
2637
public async Task NextAsync()
2738
{
28-
DateTimeType type = (DateTimeType) NHibernateUtil.DateTime;
39+
var type = NHibernateUtil.DateTime;
2940
object current = DateTime.Parse("2004-01-01");
3041
object next = await (type.NextAsync(current, null, CancellationToken.None));
3142

32-
Assert.IsTrue(next is DateTime, "Next should be DateTime");
33-
Assert.IsTrue((DateTime) next > (DateTime) current,
34-
"next should be greater than current (could be equal depending on how quickly this occurs)");
43+
Assert.That(next, Is.TypeOf<DateTime>(), "next should be DateTime");
44+
Assert.That(next, Is.GreaterThan(current), "next should be greater than current");
3545
}
3646

3747
[Test]
3848
public async Task SeedAsync()
3949
{
40-
DateTimeType type = (DateTimeType) NHibernateUtil.DateTime;
41-
Assert.IsTrue(await (type.SeedAsync(null, CancellationToken.None)) is DateTime, "seed should be DateTime");
50+
var type = NHibernateUtil.DateTime;
51+
Assert.That(await (type.SeedAsync(null, CancellationToken.None)), Is.TypeOf<DateTime>(), "seed should be DateTime");
4252
}
4353
}
44-
}
54+
55+
[TestFixture]
56+
public class DateTimeSqlTypeFixtureAsync : TypeFixtureBase
57+
{
58+
protected override string TypeName => "DateTime";
59+
private const int _dateId = 1;
60+
61+
protected override void Configure(Configuration configuration)
62+
{
63+
base.Configure(configuration);
64+
65+
var driverClass = ReflectHelper.ClassForName(configuration.GetProperty(Cfg.Environment.ConnectionDriver));
66+
ClientDriverWithParamsStats.DriverClass = driverClass;
67+
68+
configuration.SetProperty(
69+
Cfg.Environment.ConnectionDriver,
70+
typeof(ClientDriverWithParamsStats).AssemblyQualifiedName);
71+
}
72+
73+
protected override void OnSetUp()
74+
{
75+
base.OnSetUp();
76+
77+
using (var s = OpenSession())
78+
using (var t = s.BeginTransaction())
79+
{
80+
var d = new DateTimeClass
81+
{
82+
Id = _dateId,
83+
LocalDateTimeValue = DateTime.Now.AddDays(-1),
84+
UtcDateTimeValue = DateTime.UtcNow.AddDays(-1),
85+
NormalDateTimeValue = DateTime.Now.AddDays(-1)
86+
};
87+
s.Save(d);
88+
t.Commit();
89+
}
90+
}
91+
92+
protected override void OnTearDown()
93+
{
94+
base.OnTearDown();
95+
96+
using (var s = OpenSession())
97+
using (var t = s.BeginTransaction())
98+
{
99+
s.CreateQuery("delete from DateTimeClass").ExecuteUpdate();
100+
t.Commit();
101+
}
102+
}
103+
104+
protected override void DropSchema()
105+
{
106+
(Sfi.ConnectionProvider.Driver as ClientDriverWithParamsStats)?.CleanUp();
107+
base.DropSchema();
108+
}
109+
110+
[Test]
111+
public Task DbHasExpectedTypeAsync()
112+
{
113+
try
114+
{
115+
var validator = new SchemaValidator(cfg);
116+
return validator.ValidateAsync();
117+
}
118+
catch (Exception ex)
119+
{
120+
return Task.FromException<object>(ex);
121+
}
122+
}
123+
124+
[Test]
125+
public async Task SaveUseExpectedSqlTypeAsync()
126+
{
127+
var driver = (ClientDriverWithParamsStats) Sfi.ConnectionProvider.Driver;
128+
129+
using (var s = OpenSession())
130+
using (var t = s.BeginTransaction())
131+
{
132+
var d = new DateTimeClass
133+
{
134+
Id = 2,
135+
LocalDateTimeValue = DateTime.Now,
136+
UtcDateTimeValue = DateTime.UtcNow,
137+
NormalDateTimeValue = DateTime.Now
138+
};
139+
driver.ClearStats();
140+
await (s.SaveAsync(d));
141+
await (t.CommitAsync());
142+
}
143+
144+
AssertSqlType(driver, 3);
145+
}
146+
147+
[Test]
148+
public async Task UpdateUseExpectedSqlTypeAsync()
149+
{
150+
var driver = (ClientDriverWithParamsStats) Sfi.ConnectionProvider.Driver;
151+
152+
using (var s = OpenSession())
153+
using (var t = s.BeginTransaction())
154+
{
155+
var d = await (s.GetAsync<DateTimeClass>(_dateId));
156+
d.LocalDateTimeValue = DateTime.Now;
157+
d.UtcDateTimeValue = DateTime.UtcNow;
158+
d.NormalDateTimeValue = DateTime.Now;
159+
driver.ClearStats();
160+
await (t.CommitAsync());
161+
}
162+
163+
AssertSqlType(driver, 3);
164+
}
165+
166+
[Test]
167+
public async Task QueryUseExpectedSqlTypeAsync()
168+
{
169+
if (!TestDialect.SupportsNonDataBoundCondition)
170+
Assert.Ignore("Dialect does not support the test query");
171+
172+
var driver = (ClientDriverWithParamsStats) Sfi.ConnectionProvider.Driver;
173+
174+
using (var s = OpenSession())
175+
using (var t = s.BeginTransaction())
176+
{
177+
var q = s
178+
.CreateQuery(
179+
"from DateTimeClass d where d.LocalDateTimeValue = :local and " +
180+
"d.UtcDateTimeValue = :utc and d.NormalDateTimeValue = :normal and " +
181+
":other1 = :other2")
182+
.SetDateTime("local", DateTime.Now)
183+
.SetDateTime("utc", DateTime.UtcNow)
184+
.SetDateTime("normal", DateTime.Now)
185+
.SetDateTime("other1", DateTime.Now)
186+
.SetDateTime("other2", DateTime.Now);
187+
driver.ClearStats();
188+
await (q.ListAsync<DateTimeClass>());
189+
await (t.CommitAsync());
190+
}
191+
192+
AssertSqlType(driver, 5);
193+
}
194+
195+
private void AssertSqlType(ClientDriverWithParamsStats driver, int expectedCount)
196+
{
197+
if (NHibernateUtil.DateTime.SqlTypes(Sfi).Any(t => Equals(t, SqlTypeFactory.DateTime2)))
198+
{
199+
Assert.That(
200+
driver.GetCount(SqlTypeFactory.DateTime),
201+
Is.EqualTo(0),
202+
"Found unexpected SqlTypeFactory.DateTime usages.");
203+
Assert.That(
204+
driver.GetCount(SqlTypeFactory.DateTime2),
205+
Is.EqualTo(expectedCount),
206+
"Unexpected SqlTypeFactory.DateTime2 usage count.");
207+
Assert.That(driver.GetCount(DbType.DateTime), Is.EqualTo(0), "Found unexpected DbType.DateTime usages.");
208+
Assert.That(
209+
driver.GetCount(DbType.DateTime2),
210+
Is.EqualTo(expectedCount),
211+
"Unexpected DbType.DateTime2 usage count.");
212+
}
213+
else
214+
{
215+
Assert.That(
216+
driver.GetCount(SqlTypeFactory.DateTime2),
217+
Is.EqualTo(0),
218+
"Found unexpected SqlTypeFactory.DateTime2 usages.");
219+
Assert.That(
220+
driver.GetCount(SqlTypeFactory.DateTime),
221+
Is.EqualTo(expectedCount),
222+
"Unexpected SqlTypeFactory.DateTime usage count.");
223+
Assert.That(driver.GetCount(DbType.DateTime2), Is.EqualTo(0), "Found unexpected DbType.DateTime2 usages.");
224+
Assert.That(driver.GetCount(DbType.DateTime), Is.EqualTo(expectedCount), "Unexpected DbType.DateTime usage count.");
225+
}
226+
}
227+
}
228+
}

src/NHibernate.Test/DebugSessionFactory.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ bool IMapping.HasNonIdentifierPropertyNamedId(string className)
179179
return ActualFactory.HasNonIdentifierPropertyNamedId(className);
180180
}
181181

182+
Dialect.Dialect IMapping.Dialect => ActualFactory.Dialect;
183+
182184
void IDisposable.Dispose()
183185
{
184186
ActualFactory.Dispose();
@@ -270,8 +272,6 @@ ISession ISessionFactory.GetCurrentSession()
270272

271273
ICollection<string> ISessionFactory.DefinedFilterNames => ActualFactory.DefinedFilterNames;
272274

273-
Dialect.Dialect ISessionFactoryImplementor.Dialect => ActualFactory.Dialect;
274-
275275
IInterceptor ISessionFactoryImplementor.Interceptor => ActualFactory.Interceptor;
276276

277277
QueryPlanCache ISessionFactoryImplementor.QueryPlanCache => ActualFactory.QueryPlanCache;

0 commit comments

Comments
 (0)