diff --git a/doc/reference/modules/persistent_classes.xml b/doc/reference/modules/persistent_classes.xml
index 57d279be08e..92355033151 100644
--- a/doc/reference/modules/persistent_classes.xml
+++ b/doc/reference/modules/persistent_classes.xml
@@ -254,12 +254,12 @@ namespace Eg
Persistent entities don't necessarily have to be represented as POCO classes
at runtime. NHibernate also supports dynamic models
- (using Dictionaries of Dictionarys at runtime) . With this approach, you don't
+ (using Dictionaries). With this approach, you don't
write persistent classes, only mapping files.
- The following examples demonstrates the representation using Maps (Dictionary).
+ The following examples demonstrates the representation using Dictionaries.
First, in the mapping file, an entity-name has to be declared
instead of a class name:
@@ -305,7 +305,7 @@ namespace Eg
- At runtime we can work with Dictionaries of Dictionaries:
+ At runtime we can work with Dictionaries:
+
+
+ A loaded dynamic entity can be manipulated as an IDictionary or
+ IDictionary<string, object>.
+
+
+ >();
+ ...
+}]]>
@@ -357,9 +371,9 @@ using(ITransaction tx = s.BeginTransaction())
- Users may also plug in their own tuplizers. Perhaps you require that a System.Collections.IDictionary
- implementation other than System.Collections.Hashtable be used while in the
- dynamic-map entity-mode; or perhaps you need to define a different proxy generation strategy
+ Users may also plug in their own tuplizers. Perhaps you require that a IDictionary
+ implementation other than System.Collections.Generic.Dictionary<string, object>
+ is used while in the dynamic-map entity-mode; or perhaps you need to define a different proxy generation strategy
than the one used by default. Both would be achieved by defining a custom tuplizer
implementation. Tuplizers definitions are attached to the entity or component mapping they
are meant to manage. Going back to the example of our customer entity:
diff --git a/src/NHibernate.Test/Async/EntityModeTest/Map/Basic/DynamicClassFixture.cs b/src/NHibernate.Test/Async/EntityModeTest/Map/Basic/DynamicClassFixture.cs
index 02635f0ebde..70b481243c7 100644
--- a/src/NHibernate.Test/Async/EntityModeTest/Map/Basic/DynamicClassFixture.cs
+++ b/src/NHibernate.Test/Async/EntityModeTest/Map/Basic/DynamicClassFixture.cs
@@ -10,8 +10,7 @@
using System.Collections;
using System.Collections.Generic;
-using NHibernate.Cfg;
-using NHibernate.Engine;
+using Antlr.Runtime.Misc;
using NUnit.Framework;
using NHibernate.Criterion;
@@ -29,7 +28,7 @@ protected override string MappingsAssembly
protected override IList Mappings
{
- get { return new string[] {"EntityModeTest.Map.Basic.ProductLine.hbm.xml"}; }
+ get { return new[] {"EntityModeTest.Map.Basic.ProductLine.hbm.xml"}; }
}
public delegate IDictionary SingleCarQueryDelegate(ISession session);
@@ -110,5 +109,84 @@ public async Task ShouldWorkWithCriteriaAsync()
await (t.CommitAsync(cancellationToken));
}
}
+
+ [Test]
+ public async Task ShouldWorkWithHQLAndGenericsAsync()
+ {
+ await (TestLazyDynamicClassAsync(
+ s => s.CreateQuery("from ProductLine pl order by pl.Description").UniqueResult>(),
+ s => s.CreateQuery("from Model m").List>()));
+ }
+
+ [Test]
+ public async Task ShouldWorkWithCriteriaAndGenericsAsync()
+ {
+ await (TestLazyDynamicClassAsync(
+ s => s.CreateCriteria("ProductLine").AddOrder(Order.Asc("Description")).UniqueResult>(),
+ s => s.CreateCriteria("Model").List>()));
+ }
+
+ public async Task TestLazyDynamicClassAsync(
+ Func> singleCarQueryHandler,
+ Func>> allModelQueryHandler, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ var cars = new Dictionary { ["Description"] = "Cars" };
+
+ var monaro = new Dictionary
+ {
+ ["ProductLine"] = cars,
+ ["Name"] = "Monaro",
+ ["Description"] = "Holden Monaro"
+ };
+
+ var hsv = new Dictionary
+ {
+ ["ProductLine"] = cars,
+ ["Name"] = "hsv",
+ ["Description"] = "Holden hsv"
+ };
+
+ var models = new List> {monaro, hsv};
+
+ cars["Models"] = models;
+
+ await (s.SaveAsync("ProductLine", cars, cancellationToken));
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ var cars = singleCarQueryHandler(s);
+ var models = (IList