Skip to content

Commit 3017c72

Browse files
Support setting parameters with a dynamic object
Fixes #2009
1 parent 873feec commit 3017c72

File tree

6 files changed

+253
-0
lines changed

6 files changed

+253
-0
lines changed

src/NHibernate.Test/Async/Legacy/SQLFunctionsTest.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System;
1212
using System.Collections;
1313
using System.Collections.Generic;
14+
using System.Dynamic;
1415
using log4net;
1516
using NHibernate.Dialect;
1617
using NHibernate.Dialect.Function;
@@ -131,6 +132,49 @@ public async Task SetPropertiesAsync()
131132
s.Close();
132133
}
133134

135+
[Test]
136+
public async Task SetParametersWithDictionaryAsync()
137+
{
138+
using (var s = OpenSession())
139+
using (var t = s.BeginTransaction())
140+
{
141+
var simple = new Simple { Name = "Simple 1" };
142+
await (s.SaveAsync(simple, 10L));
143+
var q = s.CreateQuery("from s in class Simple where s.Name = :Name and s.Count = :Count");
144+
var parameters = new Dictionary<string, object>
145+
{
146+
{ nameof(simple.Name), simple.Name },
147+
{ nameof(simple.Count), simple.Count },
148+
};
149+
q.SetParameters(parameters);
150+
var results = await (q.ListAsync());
151+
Assert.That(results, Has.One.EqualTo(simple));
152+
await (s.DeleteAsync(simple));
153+
await (t.CommitAsync());
154+
}
155+
}
156+
157+
[Test]
158+
public async Task SetParametersWithDynamicAsync()
159+
{
160+
using (var s = OpenSession())
161+
using (var t = s.BeginTransaction())
162+
{
163+
var simple = new Simple { Name = "Simple 1" };
164+
await (s.SaveAsync(simple, 10L));
165+
var q = s.CreateQuery("from s in class Simple where s.Name = :Name and s.Count = :Count");
166+
dynamic parameters = new ExpandoObject();
167+
parameters.Name = simple.Name;
168+
parameters.Count = simple.Count;
169+
// Extension methods do not support dynamic, we must call it explicitly
170+
QueryExtensions.SetParameters(q, parameters);
171+
var results = await (q.ListAsync());
172+
Assert.That(results, Has.One.EqualTo(simple));
173+
await (s.DeleteAsync(simple));
174+
await (t.CommitAsync());
175+
}
176+
}
177+
134178
[Test]
135179
public async Task BrokenAsync()
136180
{

src/NHibernate.Test/Async/Legacy/SQLLoaderTest.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System;
1212
using System.Collections;
1313
using System.Collections.Generic;
14+
using System.Dynamic;
1415
using NHibernate.Dialect;
1516
using NHibernate.DomainModel;
1617
using NUnit.Framework;
@@ -152,6 +153,63 @@ public async Task FindBySQLPropertiesAsync()
152153
session.Close();
153154
}
154155

156+
[Test]
157+
public async Task FindBySQLDictionaryAsync()
158+
{
159+
using (var session = OpenSession())
160+
using (var tran = session.BeginTransaction())
161+
{
162+
var s = new Category { Name = nextLong.ToString() };
163+
nextLong++;
164+
await (session.SaveAsync(s));
165+
166+
s = new Category { Name = "WannaBeFound" };
167+
await (session.FlushAsync());
168+
169+
var query =
170+
session.CreateSQLQuery("select {category.*} from Category {category} where {category}.Name = :Name")
171+
.AddEntity("category", typeof(Category));
172+
var parameters = new Dictionary<string, object>
173+
{
174+
{ nameof(s.Name), s.Name }
175+
};
176+
query.SetParameters(parameters);
177+
var results = await (query.ListAsync());
178+
Assert.That(results, Is.Empty);
179+
180+
await (session.DeleteAsync("from Category"));
181+
await (tran.CommitAsync());
182+
}
183+
}
184+
185+
[Test]
186+
public async Task FindBySQLDynamicAsync()
187+
{
188+
using (var session = OpenSession())
189+
using (var tran = session.BeginTransaction())
190+
{
191+
var s = new Category { Name = nextLong.ToString() };
192+
nextLong++;
193+
await (session.SaveAsync(s));
194+
195+
s = new Category { Name = "WannaBeFound" };
196+
await (session.FlushAsync());
197+
198+
var query =
199+
session.CreateSQLQuery("select {category.*} from Category {category} where {category}.Name = :Name")
200+
.AddEntity("category", typeof(Category));
201+
dynamic parameters = new ExpandoObject();
202+
parameters.Name = s.Name;
203+
// Extension methods do not support dynamic, we must call it explicitly
204+
QueryExtensions.SetParameters(query, parameters);
205+
var results = await (query.ListAsync());
206+
Assert.That(results, Is.Empty);
207+
208+
await (session.DeleteAsync("from Category"));
209+
await (tran.CommitAsync());
210+
}
211+
}
212+
155213
[Test]
156214
public async Task FindBySQLAssociatedObjectAsync()
157215
{

src/NHibernate.Test/Legacy/SQLFunctionsTest.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Dynamic;
45
using log4net;
56
using NHibernate.Dialect;
67
using NHibernate.Dialect.Function;
@@ -137,6 +138,49 @@ public void SetProperties()
137138
s.Close();
138139
}
139140

141+
[Test]
142+
public void SetParametersWithDictionary()
143+
{
144+
using (var s = OpenSession())
145+
using (var t = s.BeginTransaction())
146+
{
147+
var simple = new Simple { Name = "Simple 1" };
148+
s.Save(simple, 10L);
149+
var q = s.CreateQuery("from s in class Simple where s.Name = :Name and s.Count = :Count");
150+
var parameters = new Dictionary<string, object>
151+
{
152+
{ nameof(simple.Name), simple.Name },
153+
{ nameof(simple.Count), simple.Count },
154+
};
155+
q.SetParameters(parameters);
156+
var results = q.List();
157+
Assert.That(results, Has.One.EqualTo(simple));
158+
s.Delete(simple);
159+
t.Commit();
160+
}
161+
}
162+
163+
[Test]
164+
public void SetParametersWithDynamic()
165+
{
166+
using (var s = OpenSession())
167+
using (var t = s.BeginTransaction())
168+
{
169+
var simple = new Simple { Name = "Simple 1" };
170+
s.Save(simple, 10L);
171+
var q = s.CreateQuery("from s in class Simple where s.Name = :Name and s.Count = :Count");
172+
dynamic parameters = new ExpandoObject();
173+
parameters.Name = simple.Name;
174+
parameters.Count = simple.Count;
175+
// Extension methods do not support dynamic, we must call it explicitly
176+
QueryExtensions.SetParameters(q, parameters);
177+
var results = q.List();
178+
Assert.That(results, Has.One.EqualTo(simple));
179+
s.Delete(simple);
180+
t.Commit();
181+
}
182+
}
183+
140184
[Test]
141185
public void Broken()
142186
{

src/NHibernate.Test/Legacy/SQLLoaderTest.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Dynamic;
45
using NHibernate.Dialect;
56
using NHibernate.DomainModel;
67
using NUnit.Framework;
@@ -140,6 +141,63 @@ public void FindBySQLProperties()
140141
session.Close();
141142
}
142143

144+
[Test]
145+
public void FindBySQLDictionary()
146+
{
147+
using (var session = OpenSession())
148+
using (var tran = session.BeginTransaction())
149+
{
150+
var s = new Category { Name = nextLong.ToString() };
151+
nextLong++;
152+
session.Save(s);
153+
154+
s = new Category { Name = "WannaBeFound" };
155+
session.Flush();
156+
157+
var query =
158+
session.CreateSQLQuery("select {category.*} from Category {category} where {category}.Name = :Name")
159+
.AddEntity("category", typeof(Category));
160+
var parameters = new Dictionary<string, object>
161+
{
162+
{ nameof(s.Name), s.Name }
163+
};
164+
query.SetParameters(parameters);
165+
var results = query.List();
166+
Assert.That(results, Is.Empty);
167+
168+
session.Delete("from Category");
169+
tran.Commit();
170+
}
171+
}
172+
173+
[Test]
174+
public void FindBySQLDynamic()
175+
{
176+
using (var session = OpenSession())
177+
using (var tran = session.BeginTransaction())
178+
{
179+
var s = new Category { Name = nextLong.ToString() };
180+
nextLong++;
181+
session.Save(s);
182+
183+
s = new Category { Name = "WannaBeFound" };
184+
session.Flush();
185+
186+
var query =
187+
session.CreateSQLQuery("select {category.*} from Category {category} where {category}.Name = :Name")
188+
.AddEntity("category", typeof(Category));
189+
dynamic parameters = new ExpandoObject();
190+
parameters.Name = s.Name;
191+
// Extension methods do not support dynamic, we must call it explicitly
192+
QueryExtensions.SetParameters(query, parameters);
193+
var results = query.List();
194+
Assert.That(results, Is.Empty);
195+
196+
session.Delete("from Category");
197+
tran.Commit();
198+
}
199+
}
200+
143201
[Test]
144202
public void FindBySQLAssociatedObject()
145203
{

src/NHibernate/Impl/AbstractQueryImpl.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,8 @@ public IQuery SetEnum(string name, Enum val)
651651
return this;
652652
}
653653

654+
// Since 5.3
655+
[Obsolete("This method was never surfaced to a query interface. Use the overload or extension method taking a generic dictionary instead.")]
654656
public IQuery SetProperties(IDictionary map)
655657
{
656658
string[] @params = NamedParameters;
@@ -674,6 +676,26 @@ public IQuery SetProperties(IDictionary map)
674676
return this;
675677
}
676678

679+
public IQuery SetProperties(IDictionary<string, object> map)
680+
{
681+
foreach (var namedParam in NamedParameters)
682+
{
683+
var obj = map[namedParam];
684+
switch (obj)
685+
{
686+
case null:
687+
break;
688+
case IEnumerable enumerable when !(enumerable is string):
689+
SetParameterList(namedParam, enumerable);
690+
break;
691+
default:
692+
SetParameter(namedParam, obj, DetermineType(namedParam, obj.GetType()));
693+
break;
694+
}
695+
}
696+
return this;
697+
}
698+
677699
public IQuery SetProperties(object bean)
678700
{
679701
System.Type clazz = bean.GetType();

src/NHibernate/QueryExtensions.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
using NHibernate.Impl;
4+
5+
namespace NHibernate
6+
{
7+
// 6.0 TODO: consider merging into IQuery.
8+
public static class QueryExtensions
9+
{
10+
/// <summary>
11+
/// Bind the keys values of the given dictionary to named parameters of the query,
12+
/// matching keys with parameter names and mapping value types to
13+
/// NHibernate types using heuristics.
14+
/// </summary>
15+
/// <param name="query">The query on which to set the parameters.</param>
16+
/// <param name="map">A dictionary of parameters values by names.</param>
17+
public static IQuery SetParameters(this IQuery query, IDictionary<string, object> map)
18+
{
19+
if (query is AbstractQueryImpl absQuery)
20+
{
21+
return absQuery.SetProperties(map);
22+
}
23+
24+
return query.SetProperties(map);
25+
}
26+
}
27+
}

0 commit comments

Comments
 (0)