Skip to content

Commit 07aab2e

Browse files
authored
Reuse joins generated by Where and OrderBy methods when fetching for Linq provider (#2496)
Fixes #871
1 parent 73d9854 commit 07aab2e

File tree

4 files changed

+513
-4
lines changed

4 files changed

+513
-4
lines changed

src/NHibernate.Test/Async/Linq/EagerLoadTests.cs

+226
Original file line numberDiff line numberDiff line change
@@ -381,5 +381,231 @@ public async Task WhereAfterFetchAndSingleOrDefaultAsync()
381381

382382
Assert.IsTrue(NHibernateUtil.IsInitialized(order.Shipper));
383383
}
384+
385+
[Test]
386+
public async Task WhereReuseJoinsAsync()
387+
{
388+
OrderLine orderLine;
389+
using (var logSpy = new SqlLogSpy())
390+
{
391+
orderLine = (await (db.OrderLines
392+
.Where(o => o.Order.Customer.ContactName == "Maria Anders")
393+
.Fetch(o => o.Order).ThenFetch(o => o.Customer)
394+
.ToListAsync()))
395+
.First();
396+
397+
var sql = logSpy.GetWholeLog();
398+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(2));
399+
Assert.That(GetTotalOccurrences(sql, "inner join"), Is.EqualTo(2));
400+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order), Is.True);
401+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order.Customer), Is.True);
402+
}
403+
404+
session.Clear();
405+
using (var logSpy = new SqlLogSpy())
406+
{
407+
orderLine = (await (db.OrderLines
408+
.Where(o => o.Order.Customer.ContactName == "Maria Anders")
409+
.Fetch(o => o.Order)
410+
.ToListAsync()))
411+
.First();
412+
413+
var sql = logSpy.GetWholeLog();
414+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(2));
415+
Assert.That(GetTotalOccurrences(sql, "inner join"), Is.EqualTo(2));
416+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order), Is.True);
417+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order.Customer), Is.False);
418+
}
419+
420+
session.Clear();
421+
using (var logSpy = new SqlLogSpy())
422+
{
423+
orderLine = (await (db.OrderLines
424+
.Where(o => o.Order.OrderLines.Any(l => l.Product.Name == "Tofu"))
425+
.Fetch(o => o.Order).ThenFetch(o => o.Customer)
426+
.ToListAsync()))
427+
.First();
428+
429+
var sql = logSpy.GetWholeLog();
430+
sql = sql.Substring(0, sql.IndexOf("where"));
431+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(2));
432+
Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(2));
433+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order), Is.True);
434+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order.Customer), Is.True);
435+
}
436+
437+
using (var logSpy = new SqlLogSpy())
438+
{
439+
(await (db.Employees
440+
.Where(o => o.Superior.Superior.Superior.FirstName != null)
441+
.Fetch(o => o.Superior)
442+
.ToListAsync()))
443+
.FirstOrDefault();
444+
445+
var sql = logSpy.GetWholeLog();
446+
Assert.That(GetTotalOccurrences(sql, ","), Is.EqualTo(31), "Only the first level should be fetched.");
447+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(3));
448+
Assert.That(GetTotalOccurrences(sql, "inner join"), Is.EqualTo(3));
449+
}
450+
451+
using (var logSpy = new SqlLogSpy())
452+
{
453+
(await (db.Employees
454+
.Where(o => o.Superior.FirstName != null)
455+
.Fetch(o => o.Superior).ThenFetch(o => o.Superior).ThenFetch(o => o.Superior)
456+
.ToListAsync()))
457+
.FirstOrDefault();
458+
459+
var sql = logSpy.GetWholeLog();
460+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(3));
461+
Assert.That(GetTotalOccurrences(sql, "inner join"), Is.EqualTo(1));
462+
Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(2));
463+
}
464+
}
465+
466+
[Test]
467+
public async Task OrderByReuseJoinsAsync()
468+
{
469+
OrderLine orderLine;
470+
using (var logSpy = new SqlLogSpy())
471+
{
472+
orderLine = (await (db.OrderLines
473+
.Where(o => o.Order.OrderId == 10248)
474+
.OrderBy(o => o.Order.Customer.ContactName)
475+
.Fetch(o => o.Order).ThenFetch(o => o.Customer)
476+
.ToListAsync()))
477+
.First();
478+
479+
var sql = logSpy.GetWholeLog();
480+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(2));
481+
Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(2));
482+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order), Is.True);
483+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order.Customer), Is.True);
484+
}
485+
486+
session.Clear();
487+
using (var logSpy = new SqlLogSpy())
488+
{
489+
orderLine = (await (db.OrderLines
490+
.Where(o => o.Order.OrderId == 10248)
491+
.OrderBy(o => o.Order.Customer.ContactName)
492+
.Fetch(o => o.Order)
493+
.ToListAsync()))
494+
.First();
495+
496+
var sql = logSpy.GetWholeLog();
497+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(2));
498+
Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(2));
499+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order), Is.True);
500+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order.Customer), Is.False);
501+
}
502+
503+
using (var logSpy = new SqlLogSpy())
504+
{
505+
(await (db.Employees
506+
.OrderBy(o => o.Superior.Superior.Superior.FirstName)
507+
.Fetch(o => o.Superior)
508+
.ToListAsync()))
509+
.FirstOrDefault();
510+
511+
var sql = logSpy.GetWholeLog();
512+
Assert.That(GetTotalOccurrences(sql, ","), Is.EqualTo(31), "Only the first level should be fetched.");
513+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(3));
514+
Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(3));
515+
}
516+
517+
using (var logSpy = new SqlLogSpy())
518+
{
519+
(await (db.Employees
520+
.OrderBy(o => o.Superior.FirstName)
521+
.Fetch(o => o.Superior).ThenFetch(o => o.Superior).ThenFetch(o => o.Superior)
522+
.ToListAsync()))
523+
.FirstOrDefault();
524+
525+
var sql = logSpy.GetWholeLog();
526+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(3));
527+
Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(3));
528+
}
529+
}
530+
531+
[Test]
532+
public async Task WhereAndOrderByReuseJoinsAsync()
533+
{
534+
OrderLine orderLine;
535+
using (var logSpy = new SqlLogSpy())
536+
{
537+
orderLine = (await (db.OrderLines
538+
.Where(o => o.Order.Customer.ContactName == "Maria Anders")
539+
.OrderBy(o => o.Order.Customer.ContactName)
540+
.Fetch(o => o.Order).ThenFetch(o => o.Customer)
541+
.ToListAsync()))
542+
.First();
543+
544+
var sql = logSpy.GetWholeLog();
545+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(2));
546+
Assert.That(GetTotalOccurrences(sql, "inner join"), Is.EqualTo(2));
547+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order), Is.True);
548+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order.Customer), Is.True);
549+
}
550+
551+
session.Clear();
552+
using (var logSpy = new SqlLogSpy())
553+
{
554+
orderLine = (await (db.OrderLines
555+
.Where(o => o.Order.Customer.ContactName == "Maria Anders")
556+
.OrderBy(o => o.Order.Customer.ContactName)
557+
.Fetch(o => o.Order)
558+
.ToListAsync()))
559+
.First();
560+
561+
var sql = logSpy.GetWholeLog();
562+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(2));
563+
Assert.That(GetTotalOccurrences(sql, "inner join"), Is.EqualTo(2));
564+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order), Is.True);
565+
Assert.That(NHibernateUtil.IsInitialized(orderLine.Order.Customer), Is.False);
566+
}
567+
568+
using (var logSpy = new SqlLogSpy())
569+
{
570+
(await (db.Employees
571+
.Where(o => o.Superior.Superior.Superior.FirstName != null)
572+
.OrderBy(o => o.Superior.Superior.Superior.FirstName)
573+
.Fetch(o => o.Superior)
574+
.ToListAsync()))
575+
.FirstOrDefault();
576+
577+
var sql = logSpy.GetWholeLog();
578+
Assert.That(GetTotalOccurrences(sql, ","), Is.EqualTo(31), "Only the first level should be fetched.");
579+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(3));
580+
Assert.That(GetTotalOccurrences(sql, "inner join"), Is.EqualTo(3));
581+
}
582+
583+
using (var logSpy = new SqlLogSpy())
584+
{
585+
(await (db.Employees
586+
.Where(o => o.Superior.FirstName != null)
587+
.OrderBy(o => o.Superior.FirstName)
588+
.Fetch(o => o.Superior).ThenFetch(o => o.Superior).ThenFetch(o => o.Superior)
589+
.ToListAsync()))
590+
.FirstOrDefault();
591+
592+
var sql = logSpy.GetWholeLog();
593+
Assert.That(GetTotalOccurrences(sql, "join"), Is.EqualTo(3));
594+
Assert.That(GetTotalOccurrences(sql, "inner join"), Is.EqualTo(1));
595+
Assert.That(GetTotalOccurrences(sql, "left outer join"), Is.EqualTo(2));
596+
}
597+
}
598+
599+
[Test]
600+
public async Task FetchBeforeSelectAsync()
601+
{
602+
var result = await (db.Orders
603+
.Where(o => o.OrderId == 10248)
604+
.Fetch(x => x.Customer)
605+
.Select(x => new {x.Customer.ContactName})
606+
.ToListAsync());
607+
608+
Assert.True(result.Any());
609+
}
384610
}
385611
}

0 commit comments

Comments
 (0)