Skip to content

Commit d14ea68

Browse files
authored
Merge pull request #490 from oskarb/fix-odbc-test-failures
Fix many odbc test failures
2 parents f0f5a21 + 7980ce1 commit d14ea68

File tree

7 files changed

+66
-7
lines changed

7 files changed

+66
-7
lines changed

build-common/common-project.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,16 @@
164164
<namespace prefix="hbm" uri="urn:nhibernate-configuration-2.2" />
165165
</namespaces>
166166
</xmlpoke>
167+
168+
<!-- Make sure the property exists - it's only set for some scenarios. -->
169+
<property name="nhibernate.odbc.explicit_datetime_scale" value="" unless="${property::exists('nhibernate.odbc.explicit_datetime_scale')}"/>
170+
<xmlpoke file="${app.config}"
171+
xpath="//*/hbm:property[@name='odbc.explicit_datetime_scale']"
172+
value="${nhibernate.odbc.explicit_datetime_scale}">
173+
<namespaces>
174+
<namespace prefix="hbm" uri="urn:nhibernate-configuration-2.2" />
175+
</namespaces>
176+
</xmlpoke>
167177
</target>
168178

169179
<target name="common.remove-connection-settings-from-app-config">

build-common/teamcity-hibernate.cfg.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,7 @@
2222
<property name="command_timeout">444</property>
2323
<property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
2424
<property name="adonet.wrap_result_sets">false</property>
25+
26+
<property name="odbc.explicit_datetime_scale"></property>
2527
</session-factory>
2628
</hibernate-configuration>

src/NHibernate/Cfg/Environment.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ public static string Version
181181
public const string OrderUpdates = "order_updates";
182182

183183
public const string QueryModelRewriterFactory = "query.query_model_rewriter_factory";
184+
185+
/// <summary>
186+
/// This may need to be set to 3 if you are using the OdbcDriver with MS SQL Server 2008+.
187+
/// </summary>
188+
public const string OdbcDateTimeScale = "odbc.explicit_datetime_scale";
184189

185190
/// <summary>
186191
/// If this setting is set to false, exceptions in IInterceptor.BeforeTransactionCompletion bubble to the caller of ITransaction.Commit and abort the commit.
@@ -378,4 +383,4 @@ private static IBytecodeProvider CreateCustomBytecodeProvider(string assemblyQua
378383
}
379384
}
380385
}
381-
}
386+
}

src/NHibernate/Driver/OdbcDriver.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Data;
34
using System.Data.Odbc;
45
using NHibernate.SqlTypes;
6+
using NHibernate.Util;
7+
using Environment = NHibernate.Cfg.Environment;
58

69
namespace NHibernate.Driver
710
{
@@ -13,6 +16,23 @@ namespace NHibernate.Driver
1316
/// </remarks>
1417
public class OdbcDriver : DriverBase
1518
{
19+
private static readonly IInternalLogger Log = LoggerProvider.LoggerFor(typeof(OdbcDriver));
20+
21+
private byte? _dbDateTimeScale;
22+
23+
24+
public override void Configure(IDictionary<string, string> settings)
25+
{
26+
base.Configure(settings);
27+
28+
// Explicit scale for DbType.DateTime. Seems required for at least MS SQL Server 2008+.
29+
_dbDateTimeScale = PropertiesHelper.GetByte(Environment.OdbcDateTimeScale, settings, null);
30+
if (_dbDateTimeScale != null && Log.IsInfoEnabled)
31+
{
32+
Log.Info(string.Format("Will use scale {0} for DbType.DateTime parameters.", _dbDateTimeScale));
33+
}
34+
}
35+
1636
public override IDbConnection CreateConnection()
1737
{
1838
return new OdbcConnection();
@@ -38,8 +58,11 @@ public override string NamedPrefix
3858
get { return String.Empty; }
3959
}
4060

41-
private static void SetVariableLengthParameterSize(IDbDataParameter dbParam, SqlType sqlType)
61+
private void SetVariableLengthParameterSize(IDbDataParameter dbParam, SqlType sqlType)
4262
{
63+
if (Equals(sqlType, SqlTypeFactory.DateTime) && _dbDateTimeScale != null)
64+
dbParam.Scale = _dbDateTimeScale.Value;
65+
4366
// Override the defaults using data from SqlType.
4467
if (sqlType.LengthDefined)
4568
{
@@ -59,4 +82,4 @@ protected override void InitializeParameter(IDbDataParameter dbParam, string nam
5982
SetVariableLengthParameterSize(dbParam, sqlType);
6083
}
6184
}
62-
}
85+
}

src/NHibernate/Util/PropertiesHelper.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ public static bool GetBoolean(string property, IDictionary<string, string> prope
2020
return GetBoolean(property, properties, false);
2121
}
2222

23+
public static byte? GetByte(string property, IDictionary<string, string> properties, byte? defaultValue)
24+
{
25+
string toParse;
26+
properties.TryGetValue(property, out toParse);
27+
byte result;
28+
return byte.TryParse(toParse, out result) ? result : defaultValue;
29+
}
30+
2331
public static int GetInt32(string property, IDictionary<string, string> properties, int defaultValue)
2432
{
2533
string toParse;
@@ -67,4 +75,4 @@ public static IDictionary<string, string> ToDictionary(string property, string d
6775
return map;
6876
}
6977
}
70-
}
78+
}

src/NHibernate/nhibernate-configuration.xsd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
<xs:enumeration value="order_updates" />
121121
<xs:enumeration value="query.query_model_rewriter_factory" />
122122
<xs:enumeration value="linqtohql.generatorsregistry" />
123+
<xs:enumeration value="odbc.explicit_datetime_scale" />
123124
</xs:restriction>
124125
</xs:simpleType>
125126
</xs:attribute>
@@ -229,4 +230,4 @@
229230
<xs:attribute name="use" type="xs:boolean" />
230231
</xs:complexType>
231232
</xs:element>
232-
</xs:schema>
233+
</xs:schema>

teamcity.build

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,18 @@
4646
</target>
4747

4848
<target name="setup-teamcity-sqlServerOdbc">
49-
<property name="nhibernate.connection.driver_class" value="NHibernate.Driver.OdbcDriver" />
50-
<property name="nhibernate.connection.connection_string" value="Driver={SQL Server Native Client 11.0};Server=.\SQLExpress;Database=nhibernateOdbc;Trusted_Connection=yes" />
49+
<property name="nhibernate.connection.driver_class" value="NHibernate.Driver.OdbcDriver" />
50+
<property name="nhibernate.odbc.explicit_datetime_scale" value="3" />
51+
<!-- We need to use a dialect that avoids mapping DbType.Time to TIME on MSSQL. On modern SQL Server
52+
this becomes TIME(7). Later, such values cannot be read back over ODBC. The
53+
error we get is "System.ArgumentException : Unknown SQL type - SS_TIME_EX.". I don't know for certain
54+
why this occurs, but MS docs do say that for a client "compiled using a version of SQL Server Native
55+
Client prior to SQL Server 2008", TIME(7) cannot be converted back to the client. Assuming that .Net's
56+
OdbcDriver would be considered a "client compiled with a previous version", it would make sense. Anyway,
57+
using the MsSql2005Dialect avoids these test failures. -->
58+
<property name="nhibernate.dialect" value="NHibernate.Dialect.MsSql2005Dialect" />
59+
<!-- The OdbcDriver inherits SupportsMultipleOpenReaders=true from DriverBase, which requires Mars_Connection=yes for SQL Server. -->
60+
<property name="nhibernate.connection.connection_string" value="Driver={SQL Server Native Client 11.0};Server=.\SQLExpress;Database=nhibernateOdbc;Trusted_Connection=yes;Mars_Connection=yes;" />
5161
<property name="NHibernate.Test.IgnoreFail" value="true" />
5262
<property name="teamcity.last.result" value="${root.dir}/lib/teamcity/sqlServerOdbc/NHibernate.Test.last-results.xml" />
5363
</target>

0 commit comments

Comments
 (0)