Skip to content

Commit bf03f5a

Browse files
committed
Avoid double param type guessing and better NULL parameter handling
1 parent 4decb54 commit bf03f5a

File tree

3 files changed

+65
-33
lines changed

3 files changed

+65
-33
lines changed

src/NHibernate/IQuery.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@
66

77
namespace NHibernate
88
{
9+
// 6.0 TODO add to IQuery
10+
internal interface IQueryNextVer : IQuery
11+
{
12+
/// <summary>
13+
/// Bind a value to a named query parameter
14+
/// </summary>
15+
/// <param name="name">The name of the parameter</param>
16+
/// <param name="val">The possibly null parameter value</param>
17+
/// <param name="type">The NHibernate <see cref="IType"/>.</param>
18+
/// <param name="preferMetadataType">If true supplied type is used only if parameter metadata is missing</param>
19+
IQuery SetParameter(string name, object val, IType type, bool preferMetadataType);
20+
}
21+
922
/// <summary>
1023
/// An object-oriented representation of a NHibernate query.
1124
/// </summary>

src/NHibernate/Impl/AbstractQueryImpl.cs

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace NHibernate.Impl
1919
/// <summary>
2020
/// Abstract implementation of the IQuery interface.
2121
/// </summary>
22-
public abstract partial class AbstractQueryImpl : IQuery
22+
public abstract partial class AbstractQueryImpl : IQuery, IQueryNextVer
2323
{
2424
private readonly string queryString;
2525
protected readonly ISessionImplementor session;
@@ -242,17 +242,33 @@ public IQuery SetParameter(int position, object val, IType type)
242242

243243
public IQuery SetParameter(string name, object val, IType type)
244244
{
245-
if (!parameterMetadata.NamedParameterNames.Contains(name))
246-
{
247-
if (shouldIgnoredUnknownNamedParameters)//just ignore it
248-
return this;
249-
throw new ArgumentException("Parameter " + name + " does not exist as a named parameter in [" + QueryString + "]");
250-
}
251-
else
252-
{
253-
namedParameters[name] = new TypedValue(type, val, false);
245+
return SetParameter(name, val, type, false);
246+
}
247+
248+
//TODO 6.0: Add to IQuery interface
249+
public IQuery SetParameter(string name, object val, IType type, bool preferMetadataType)
250+
{
251+
if (CheckParameterIgnored(name))
254252
return this;
253+
254+
if (type == null || preferMetadataType)
255+
{
256+
type = parameterMetadata.GetNamedParameterExpectedType(name) ?? type ?? ParameterHelper.GuessType(val, session.Factory);
255257
}
258+
259+
namedParameters[name] = new TypedValue(type, val, false);
260+
return this;
261+
}
262+
263+
private bool CheckParameterIgnored(string name)
264+
{
265+
if (parameterMetadata.NamedParameterNames.Contains(name))
266+
return false;
267+
268+
if (shouldIgnoredUnknownNamedParameters) //just ignore it
269+
return true;
270+
271+
throw new ArgumentException("Parameter " + name + " does not exist as a named parameter in [" + QueryString + "]");
256272
}
257273

258274
public IQuery SetParameter<T>(int position, T val)
@@ -289,29 +305,7 @@ public IQuery SetParameter<T>(string name, T val)
289305

290306
public IQuery SetParameter(string name, object val)
291307
{
292-
if (!parameterMetadata.NamedParameterNames.Contains(name))
293-
{
294-
if (shouldIgnoredUnknownNamedParameters)//just ignore it
295-
return this;
296-
}
297-
298-
if (val == null)
299-
{
300-
IType type = parameterMetadata.GetNamedParameterExpectedType(name);
301-
if (type == null)
302-
{
303-
throw new ArgumentNullException("val",
304-
"A type specific Set(name, val) should be called because the Type can not be guessed from a null value.");
305-
}
306-
307-
SetParameter(name, val, type);
308-
}
309-
else
310-
{
311-
SetParameter(name, val, DetermineType(name, val));
312-
}
313-
314-
return this;
308+
return SetParameter(name, val, null, true);
315309
}
316310

317311
public IQuery SetParameter(int position, object val)

src/NHibernate/Linq/DefaultQueryProvider.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,14 @@ protected virtual object ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery
253253
#pragma warning restore 618
254254
}
255255

256+
//TODO 6.0: Remove
256257
private static void SetParameters(IQuery query, IDictionary<string, NamedParameter> parameters)
257258
{
259+
if (query is IQueryNextVer impl)
260+
{
261+
SetParameters(impl, parameters);
262+
return;
263+
}
258264
foreach (var parameterName in query.NamedParameters)
259265
{
260266
// The parameter type will be taken from the parameter metadata
@@ -274,6 +280,25 @@ private static void SetParameters(IQuery query, IDictionary<string, NamedParamet
274280
}
275281
}
276282

283+
//TODO 6.0: Replace with
284+
//private static void SetParameters(IQuery query, IDictionary<string, NamedParameter> parameters)
285+
private static void SetParameters(IQueryNextVer query, IDictionary<string, NamedParameter> parameters)
286+
{
287+
foreach (var parameterName in query.NamedParameters)
288+
{
289+
// The parameter type will be taken from the parameter metadata
290+
var parameter = parameters[parameterName];
291+
if (parameter.IsCollection)
292+
{
293+
query.SetParameterList(parameter.Name, (IEnumerable) parameter.Value);
294+
}
295+
else
296+
{
297+
query.SetParameter(parameter.Name, parameter.Value, parameter.Type, parameter.IsGuessedType);
298+
}
299+
}
300+
}
301+
277302
public virtual void SetResultTransformerAndAdditionalCriteria(IQuery query, NhLinqExpression nhExpression, IDictionary<string, Tuple<object, IType>> parameters)
278303
{
279304
if (nhExpression.ExpressionToHqlTranslationResults != null)

0 commit comments

Comments
 (0)