Skip to content

Commit c9975fb

Browse files
committed
NH-2319 - Add ability to query collections with AsQueryable()
1 parent 9527cb0 commit c9975fb

20 files changed

+735
-37
lines changed
Lines changed: 355 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,355 @@
1+
using System;
2+
using System.Linq;
3+
using NHibernate.Cfg;
4+
using NHibernate.Cfg.MappingSchema;
5+
using NHibernate.Collection;
6+
using NHibernate.Mapping.ByCode;
7+
using NUnit.Framework;
8+
9+
namespace NHibernate.Test.NHSpecificTest.NH2319
10+
{
11+
public abstract class FixtureBase : TestCaseMappingByCode
12+
{
13+
private Guid parantId;
14+
private Guid child1Id;
15+
16+
[Test]
17+
public void ShouldBeAbleToFindChildrenByName()
18+
{
19+
using (var session = OpenSession())
20+
using (session.BeginTransaction())
21+
{
22+
var parent = session.Get<Parent>(parantId);
23+
24+
Assert.That(parent, Is.Not.Null);
25+
26+
var filtered = parent.Children
27+
.AsQueryable()
28+
.Where(x => x.Name == "Jack")
29+
.ToList();
30+
31+
Assert.That(filtered, Has.Count.EqualTo(1));
32+
Assert.That(filtered[0].Id, Is.EqualTo(child1Id));
33+
}
34+
}
35+
36+
[Test]
37+
public void ShouldBeAbleToPerformComplexFiltering()
38+
{
39+
using (var session = OpenSession())
40+
using (session.BeginTransaction())
41+
{
42+
var parent = session.Get<Parent>(parantId);
43+
44+
Assert.NotNull(parent);
45+
46+
var filtered = parent.Children
47+
.AsQueryable()
48+
.Where(x => x.Name == "Piter")
49+
.SelectMany(x => x.GrandChildren)
50+
.Select(x => x.Id)
51+
.Count();
52+
53+
Assert.That(filtered, Is.EqualTo(2));
54+
}
55+
}
56+
57+
[Test]
58+
public void ShouldNotInitializeCollectionWhenPerformingQuery()
59+
{
60+
using (var session = OpenSession())
61+
using (session.BeginTransaction())
62+
{
63+
var parent = session.Get<Parent>(parantId);
64+
Assert.That(parent, Is.Not.Null);
65+
66+
var persistentCollection = (IPersistentCollection) parent.Children;
67+
68+
var filtered = parent.Children
69+
.AsQueryable()
70+
.Where(x => x.Name == "Jack")
71+
.ToList();
72+
73+
Assert.That(filtered, Has.Count.EqualTo(1));
74+
Assert.That(persistentCollection.WasInitialized, Is.False);
75+
}
76+
}
77+
78+
[Test]
79+
public void ShouldPerformSqlQueryEvenIfCollectionAlreadyInitialized()
80+
{
81+
using (var session = OpenSession())
82+
using (session.BeginTransaction())
83+
{
84+
var parent = session.Get<Parent>(parantId);
85+
Assert.That(parent, Is.Not.Null);
86+
87+
var loaded = parent.Children.ToList();
88+
Assert.That(loaded, Has.Count.EqualTo(2));
89+
90+
var countBeforeFiltering = session.SessionFactory.Statistics.QueryExecutionCount;
91+
92+
var filtered = parent.Children
93+
.AsQueryable()
94+
.Where(x => x.Name == "Jack")
95+
.ToList();
96+
97+
var countAfterFiltering = session.SessionFactory.Statistics.QueryExecutionCount;
98+
99+
Assert.That(filtered, Has.Count.EqualTo(1));
100+
Assert.That(countAfterFiltering, Is.EqualTo(countBeforeFiltering + 1));
101+
}
102+
}
103+
104+
[Test]
105+
public void TestFilter()
106+
{
107+
using (var session = OpenSession())
108+
using (session.BeginTransaction())
109+
{
110+
var parent = session.Get<Parent>(parantId);
111+
Assert.That(parent, Is.Not.Null);
112+
113+
var children = session.CreateFilter(parent.Children, "where this.Name = 'Jack'")
114+
.List<Child>();
115+
116+
Assert.That(children, Has.Count.EqualTo(1));
117+
}
118+
}
119+
120+
protected override void Configure(Configuration configuration)
121+
{
122+
configuration.SetProperty("show_sql", "true");
123+
configuration.SetProperty("generate_statistics", "true");
124+
}
125+
126+
protected override void OnSetUp()
127+
{
128+
using (var session = OpenSession())
129+
using (var transaction = session.BeginTransaction())
130+
{
131+
var parent1 = new Parent {Name = "Bob"};
132+
parantId = (Guid) session.Save(parent1);
133+
134+
var parent2 = new Parent {Name = "Martin"};
135+
session.Save(parent2);
136+
137+
var child1 = new Child
138+
{
139+
Name = "Jack",
140+
Parent = parent1
141+
};
142+
parent1.Children.Add(child1);
143+
child1Id = (Guid) session.Save(child1);
144+
145+
var child2 = new Child
146+
{
147+
Name = "Piter",
148+
Parent = parent1
149+
};
150+
parent1.Children.Add(child2);
151+
session.Save(child2);
152+
153+
var grandChild1 = new GrandChild
154+
{
155+
Name = "Kate",
156+
Child = child2
157+
};
158+
child2.GrandChildren.Add(grandChild1);
159+
session.Save(grandChild1);
160+
161+
var grandChild2 = new GrandChild
162+
{
163+
Name = "Mary",
164+
Child = child2
165+
};
166+
child2.GrandChildren.Add(grandChild2);
167+
session.Save(grandChild2);
168+
169+
var child3 = new Child
170+
{
171+
Name = "Jack",
172+
Parent = parent2
173+
};
174+
parent2.Children.Add(child3);
175+
session.Save(child3);
176+
177+
session.Flush();
178+
transaction.Commit();
179+
}
180+
}
181+
182+
protected override void OnTearDown()
183+
{
184+
using (var session = OpenSession())
185+
using (var transaction = session.BeginTransaction())
186+
{
187+
session.Delete("from System.Object");
188+
189+
session.Flush();
190+
transaction.Commit();
191+
}
192+
}
193+
}
194+
195+
[TestFixture]
196+
public class BagFixture : FixtureBase
197+
{
198+
protected override HbmMapping GetMappings()
199+
{
200+
var mapper = new ModelMapper();
201+
mapper.Class<Parent>(rc =>
202+
{
203+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
204+
rc.Property(x => x.Name);
205+
rc.Bag(x => x.Children,
206+
map => map.Cascade(Mapping.ByCode.Cascade.All | Mapping.ByCode.Cascade.DeleteOrphans),
207+
rel => rel.OneToMany());
208+
});
209+
210+
mapper.Class<Child>(rc =>
211+
{
212+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
213+
rc.Property(x => x.Name);
214+
rc.ManyToOne(x => x.Parent);
215+
rc.Bag(x => x.GrandChildren, map => map.Cascade(Mapping.ByCode.Cascade.All | Mapping.ByCode.Cascade.DeleteOrphans), rel => rel.OneToMany());
216+
});
217+
218+
mapper.Class<GrandChild>(rc =>
219+
{
220+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
221+
rc.Property(x => x.Name);
222+
rc.ManyToOne(x => x.Child, x => x.Column("child_id"));
223+
});
224+
225+
return mapper.CompileMappingForAllExplicitlyAddedEntities();
226+
}
227+
228+
}
229+
230+
[TestFixture]
231+
public class SetFixture : FixtureBase
232+
{
233+
protected override HbmMapping GetMappings()
234+
{
235+
var mapper = new ModelMapper();
236+
mapper.Class<Parent>(rc =>
237+
{
238+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
239+
rc.Property(x => x.Name);
240+
rc.Set(x => x.Children,
241+
map => map.Cascade(Mapping.ByCode.Cascade.All | Mapping.ByCode.Cascade.DeleteOrphans),
242+
rel => rel.OneToMany());
243+
});
244+
245+
mapper.Class<Child>(rc =>
246+
{
247+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
248+
rc.Property(x => x.Name);
249+
rc.ManyToOne(x => x.Parent);
250+
rc.Set(x => x.GrandChildren,
251+
map => map.Cascade(Mapping.ByCode.Cascade.All | Mapping.ByCode.Cascade.DeleteOrphans),
252+
rel => rel.OneToMany());
253+
});
254+
255+
mapper.Class<GrandChild>(rc =>
256+
{
257+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
258+
rc.Property(x => x.Name);
259+
rc.ManyToOne(x => x.Child, x => x.Column("child_id"));
260+
});
261+
262+
return mapper.CompileMappingForAllExplicitlyAddedEntities();
263+
}
264+
}
265+
266+
[TestFixture]
267+
public class ListFixture : FixtureBase
268+
{
269+
protected override HbmMapping GetMappings()
270+
{
271+
var mapper = new ModelMapper();
272+
mapper.Class<Parent>(rc =>
273+
{
274+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
275+
rc.Property(x => x.Name);
276+
rc.List(
277+
x => x.Children,
278+
list =>
279+
{
280+
list.Cascade(Mapping.ByCode.Cascade.All | Mapping.ByCode.Cascade.DeleteOrphans);
281+
list.Index(i => i.Column("i"));
282+
},
283+
rel => rel.OneToMany());
284+
});
285+
286+
mapper.Class<Child>(rc =>
287+
{
288+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
289+
rc.Property(x => x.Name);
290+
rc.ManyToOne(x => x.Parent);
291+
rc.List(
292+
c => c.GrandChildren,
293+
list =>
294+
{
295+
list.Cascade(Mapping.ByCode.Cascade.All | Mapping.ByCode.Cascade.DeleteOrphans);
296+
list.Index(i => i.Column("i"));
297+
},
298+
rel => rel.OneToMany());
299+
});
300+
301+
mapper.Class<GrandChild>(rc =>
302+
{
303+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
304+
rc.Property(x => x.Name);
305+
rc.ManyToOne(x => x.Child, x => x.Column("child_id"));
306+
});
307+
308+
return mapper.CompileMappingForAllExplicitlyAddedEntities();
309+
}
310+
}
311+
312+
[TestFixture]
313+
public class IdBagFixture : FixtureBase
314+
{
315+
protected override HbmMapping GetMappings()
316+
{
317+
var mapper = new ModelMapper();
318+
mapper.Class<Parent>(rc =>
319+
{
320+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
321+
rc.Property(x => x.Name);
322+
rc.IdBag(
323+
x => x.Children,
324+
list =>
325+
{
326+
list.Cascade(Mapping.ByCode.Cascade.All | Mapping.ByCode.Cascade.DeleteOrphans);
327+
},
328+
rel => rel.ManyToMany());
329+
});
330+
331+
mapper.Class<Child>(rc =>
332+
{
333+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
334+
rc.Property(x => x.Name);
335+
//rc.ManyToOne(x => x.Parent);
336+
rc.IdBag(
337+
c => c.GrandChildren,
338+
list =>
339+
{
340+
list.Cascade(Mapping.ByCode.Cascade.All | Mapping.ByCode.Cascade.DeleteOrphans);
341+
},
342+
rel => rel.ManyToMany());
343+
});
344+
345+
mapper.Class<GrandChild>(rc =>
346+
{
347+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
348+
rc.Property(x => x.Name);
349+
//rc.ManyToOne(x => x.Child, x => x.Column("child_id"));
350+
});
351+
352+
return mapper.CompileMappingForAllExplicitlyAddedEntities();
353+
}
354+
}
355+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace NHibernate.Test.NHSpecificTest.NH2319
5+
{
6+
class Parent
7+
{
8+
public virtual Guid Id { get; set; }
9+
public virtual string Name { get; set; }
10+
public virtual ICollection<Child> Children { get; set; } = new List<Child>();
11+
}
12+
13+
class Child
14+
{
15+
public virtual Parent Parent { get; set; }
16+
public virtual Guid Id { get; set; }
17+
public virtual string Name { get; set; }
18+
public virtual ICollection<GrandChild> GrandChildren { get; set; } = new List<GrandChild>();
19+
}
20+
class GrandChild
21+
{
22+
public virtual Child Child { get; set; }
23+
public virtual Guid Id { get; set; }
24+
public virtual string Name { get; set; }
25+
}
26+
}

0 commit comments

Comments
 (0)