Mercurial > pub > bltoolkit
diff UnitTests/Linq/JoinTest.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTests/Linq/JoinTest.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,814 @@ +using System; +using System.Linq; + +using BLToolkit.Data.DataProvider; +using BLToolkit.Data.Linq; +using BLToolkit.DataAccess; +using BLToolkit.Mapping; + +using NUnit.Framework; + +namespace Data.Linq +{ + using Model; + + [TestFixture] + public class JoinTest : TestBase + { + [Test] + public void InnerJoin1() + { + TestJohn(db => + from p1 in db.Person + join p2 in db.Person on p1.ID equals p2.ID + where p1.ID == 1 + select new Person { ID = p1.ID, FirstName = p2.FirstName }); + } + + [Test] + public void InnerJoin2() + { + TestJohn(db => + from p1 in db.Person + join p2 in db.Person on new { p1.ID, p1.FirstName } equals new { p2.ID, p2.FirstName } + where p1.ID == 1 + select new Person { ID = p1.ID, FirstName = p2.FirstName }); + } + + [Test] + public void InnerJoin3() + { + TestJohn(db => + from p1 in db.Person + join p2 in + from p2 in db.Person join p3 in db.Person on new { p2.ID, p2.LastName } equals new { p3.ID, p3.LastName } select new { p2, p3 } + on new { p1.ID, p1.FirstName } equals new { p2.p2.ID, p2.p2.FirstName } + where p1.ID == 1 + select new Person { ID = p1.ID, FirstName = p2.p2.FirstName, LastName = p2.p3.LastName }); + } + + [Test] + public void InnerJoin4() + { + TestJohn(db => + from p1 in db.Person + join p2 in db.Person on new { p1.ID, p1.FirstName } equals new { p2.ID, p2.FirstName } + join p3 in db.Person on new { p2.ID, p2.LastName } equals new { p3.ID, p3.LastName } + where p1.ID == 1 + select new Person { ID = p1.ID, FirstName = p2.FirstName, LastName = p3.LastName }); + } + + [Test] + public void InnerJoin5() + { + TestJohn(db => + from p1 in db.Person + join p2 in db.Person on new { p1.ID, p1.FirstName } equals new { p2.ID, p2.FirstName } + join p3 in db.Person on new { p1.ID, p2.LastName } equals new { p3.ID, p3.LastName } + where p1.ID == 1 + select new Person { ID = p1.ID, FirstName = p2.FirstName, LastName = p3.LastName }); + } + + [Test] + public void InnerJoin6() + { + TestJohn(db => + from p1 in db.Person + join p2 in from p3 in db.Person select new { ID = p3.ID + 1, p3.FirstName } on p1.ID equals p2.ID - 1 + where p1.ID == 1 + select new Person { ID = p1.ID, FirstName = p2.FirstName }); + } + + [Test] + public void InnerJoin7() + { + var expected = + from t in + from ch in Child + join p in Parent on ch.ParentID equals p.ParentID + select ch.ParentID + p.ParentID + where t > 2 + select t; + + ForEachProvider(db => AreEqual(expected, + from t in + from ch in db.Child + join p in db.Parent on ch.ParentID equals p.ParentID + select ch.ParentID + p.ParentID + where t > 2 + select t)); + } + + [Test] + public void InnerJoin8() + { + ForEachProvider(db => AreEqual( + from t in + from ch in Child + join p in Parent on ch.ParentID equals p.ParentID + select new { ID = ch.ParentID + p.ParentID } + where t.ID > 2 + select t, + from t in + from ch in db.Child + join p in db.Parent on ch.ParentID equals p.ParentID + select new { ID = ch.ParentID + p.ParentID } + where t.ID > 2 + select t)); + } + + [Test] + public void InnerJoin9() + { + ForEachProvider(new[] { ProviderName.Access }, db => AreEqual( + from g in GrandChild + join p in Parent4 on g.Child.ParentID equals p.ParentID + where g.ParentID < 10 && p.Value1 == TypeValue.Value3 + select g, + from g in db.GrandChild + join p in db.Parent4 on g.Child.ParentID equals p.ParentID + where g.ParentID < 10 && p.Value1 == TypeValue.Value3 + select g)); + } + + [Test] + public void InnerJoin10() + { + ForEachProvider(db => AreEqual( + from p in Parent + join g in GrandChild on p.ParentID equals g.ParentID into q + from q1 in q + select new { p.ParentID, q1.GrandChildID }, + from p in db.Parent + join g in db.GrandChild on p.ParentID equals g.ParentID into q + from q1 in q + select new { p.ParentID, q1.GrandChildID })); + } + + [Test] + public void GroupJoin1() + { + ForEachProvider(db => AreEqual( + from p in Parent + join ch in Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select p, + from p in db.Parent + join ch in db.Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select p)); + } + + [Test] + public void GroupJoin2() + { + ForEachProvider(db => + { + var q = + from p in db.Parent + join c in db.Child on p.ParentID equals c.ParentID into lj + where p.ParentID == 1 + select new { p, lj }; + + var list = q.ToList(); + + Assert.AreEqual(1, list.Count); + Assert.AreEqual(1, list[0].p.ParentID); + Assert.AreEqual(1, list[0].lj.Count()); + + var ch = list[0].lj.ToList(); + + Assert.AreEqual( 1, ch[0].ParentID); + Assert.AreEqual(11, ch[0].ChildID); + }); + } + + [Test] + public void GroupJoin3() + { + var q1 = Parent + .GroupJoin( + Child, + p => p.ParentID, + ch => ch.ParentID, + (p, lj1) => new { p, lj1 = new { lj1 } } + ) + .Where (t => t.p.ParentID == 2) + .Select(t => new { t.p, t.lj1 }); + + var list1 = q1.ToList(); + + ForEachProvider(db => + { + var q2 = db.Parent + .GroupJoin( + db.Child, + p => p.ParentID, + ch => ch.ParentID, + (p, lj1) => new { p, lj1 = new { lj1 } } + ) + .Where (t => t.p.ParentID == 2) + .Select(t => new { t.p, t.lj1 }); + + var list2 = q2.ToList(); + + Assert.AreEqual(list1.Count, list2.Count); + Assert.AreEqual(list1[0].p.ParentID, list2[0].p.ParentID); + Assert.AreEqual(list1[0].lj1.lj1.Count(), list2[0].lj1.lj1.Count()); + }); + } + + [Test] + public void GroupJoin4() + { + var q1 = + from p in Parent + join ch in + from c in Child select new { c.ParentID, c.ChildID } + on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 3 + select new { p, lj1 }; + + var list1 = q1.ToList(); + + ForEachProvider(db => + { + var q2 = + from p in db.Parent + join ch in + from c in db.Child select new { c.ParentID, c.ChildID } + on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 3 + select new { p, lj1 }; + + var list2 = q2.ToList(); + + Assert.AreEqual(list1.Count, list2.Count); + Assert.AreEqual(list1[0].p.ParentID, list2[0].p.ParentID); + Assert.AreEqual(list1[0].lj1.Count(), list2[0].lj1.Count()); + }); + } + + [Test] + public void GroupJoin5() + { + ForEachProvider(db => AreEqual( + from p in Parent + join ch in Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select lj1.First(), + from p in db.Parent + join ch in db.Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select lj1.First())); + } + + [Test] + public void GroupJoin51() + { + var expected = + ( + from p in Parent + join ch in Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select new { p1 = lj1, p2 = lj1.First() } + ).ToList(); + + ForEachProvider(db => + { + var result = + ( + from p in db.Parent + join ch in db.Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select new { p1 = lj1, p2 = lj1.First() } + ).ToList(); + + Assert.AreEqual(expected.Count, result.Count); + AreEqual(expected[0].p1, result[0].p1); + }); + } + + [Test] + public void GroupJoin52() + { + ForEachProvider(db => AreEqual( + from p in Parent + join ch in Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select lj1.First().ParentID, + from p in db.Parent + join ch in db.Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select lj1.First().ParentID)); + } + + [Test] + public void GroupJoin53() + { + ForEachProvider(db => AreEqual( + from p in Parent + join ch in Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select lj1.Select(_ => _.ParentID).First(), + from p in db.Parent + join ch in db.Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select lj1.Select(_ => _.ParentID).First())); + } + + [Test] + public void GroupJoin54() + { + ForEachProvider(db => AreEqual( + from p in Parent + join ch in Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select new { p1 = lj1.Count(), p2 = lj1.First() }, + from p in db.Parent + join ch in db.Child on p.ParentID equals ch.ParentID into lj1 + where p.ParentID == 1 + select new { p1 = lj1.Count(), p2 = lj1.First() })); + } + + [Test] + public void GroupJoin6() + { + var n = 1; + + var q1 = + from p in Parent + join c in Child on p.ParentID + n equals c.ParentID into lj + where p.ParentID == 1 + select new { p, lj }; + + var list1 = q1.ToList(); + var ch1 = list1[0].lj.ToList(); + + ForEachProvider(db => + { + var q2 = + from p in db.Parent + join c in db.Child on p.ParentID + n equals c.ParentID into lj + where p.ParentID == 1 + select new { p, lj }; + + var list2 = q2.ToList(); + + Assert.AreEqual(list1.Count, list2.Count); + Assert.AreEqual(list1[0].p.ParentID, list2[0].p.ParentID); + Assert.AreEqual(list1[0].lj.Count(), list2[0].lj.Count()); + + var ch2 = list2[0].lj.ToList(); + + Assert.AreEqual(ch1[0].ParentID, ch2[0].ParentID); + Assert.AreEqual(ch1[0].ChildID, ch2[0].ChildID); + }); + } + + [Test] + public void GroupJoin7() + { + var n = 1; + + var q1 = + from p in Parent + join c in Child on new { id = p.ParentID } equals new { id = c.ParentID - n } into j + where p.ParentID == 1 + select new { p, j }; + + var list1 = q1.ToList(); + var ch1 = list1[0].j.ToList(); + + ForEachProvider( + new[] { ProviderName.Firebird }, + db => + { + var q2 = + from p in db.Parent + join c in db.Child on new { id = p.ParentID } equals new { id = c.ParentID - n } into j + where p.ParentID == 1 + select new { p, j }; + + var list2 = q2.ToList(); + + Assert.AreEqual(list1.Count, list2.Count); + Assert.AreEqual(list1[0].p.ParentID, list2[0].p.ParentID); + Assert.AreEqual(list1[0].j.Count(), list2[0].j.Count()); + + var ch2 = list2[0].j.ToList(); + + Assert.AreEqual(ch1[0].ParentID, ch2[0].ParentID); + Assert.AreEqual(ch1[0].ChildID, ch2[0].ChildID); + }); + } + + [Test] + public void GroupJoin8() + { + ForEachProvider(db => AreEqual( + from p in Parent + join c in Child on p.ParentID equals c.ParentID into g + select new + { + Child = g.FirstOrDefault() + }, + from p in db.Parent + join c in db.Child on p.ParentID equals c.ParentID into g + select new + { + Child = g.FirstOrDefault() + } + )); + } + + [Test] + public void GroupJoin9() + { + ForEachProvider(db => AreEqual( + Parent + .GroupJoin( + Parent, + x => new { Id = x.ParentID }, + y => new { Id = y.ParentID }, + (xid, yid) => new { xid, yid } + ) + .SelectMany( + y => y.yid.DefaultIfEmpty(), + (x1, y) => new { x1.xid, y } + ) + .GroupJoin( + Parent, + x => new { Id = x.xid.ParentID }, + y => new { Id = y.ParentID }, + (x2, y) => new { x2.xid, x2.y, h = y } + ) + .SelectMany( + a => a.h.DefaultIfEmpty(), + (x3, a) => new { x3.xid, x3.y, a } + ) + .GroupJoin( + Parent, + x => new { Id = x.xid.ParentID }, + y => new { Id = y.ParentID }, + (x4, y) => new { x4.xid, x4.y, x4.a, p = y } + ) + .SelectMany( + z => z.p.DefaultIfEmpty(), + (x5, z) => new { x5.xid, z, x5.y, x5.a } + ) + .GroupJoin( + Parent, + x => new { Id = x.xid.ParentID }, + y => new { Id = y.Value1 ?? 1 }, + (x6, y) => new { x6.xid, xy = x6.y, x6.a, x6.z, y } + ) + .SelectMany( + z => z.y.DefaultIfEmpty(), + (x7, z) => new { x7.xid, z, x7.xy, x7.a, xz = x7.z } + ) + .GroupJoin( + Parent, + x => new { Id = x.xid.ParentID }, + y => new { Id = y.ParentID }, + (x8, y) => new { x8.xid, x8.z, x8.xy, x8.a, x8.xz, y } + ) + .SelectMany( + a => a.y.DefaultIfEmpty(), + (x9, a) => new { x9.xid, x9.z, x9.xy, xa = x9.a, x9.xz, a } + ), + db.Parent + .GroupJoin( + db.Parent, + x => new { Id = x.ParentID }, + y => new { Id = y.ParentID }, + (xid, yid) => new { xid, yid } + ) + .SelectMany( + y => y.yid.DefaultIfEmpty(), + (x1, y) => new { x1.xid, y } + ) + .GroupJoin( + db.Parent, + x => new { Id = x.xid.ParentID }, + y => new { Id = y.ParentID }, + (x2, y) => new { x2.xid, x2.y, h = y } + ) + .SelectMany( + a => a.h.DefaultIfEmpty(), + (x3, a) => new { x3.xid, x3.y, a } + ) + .GroupJoin( + db.Parent, + x => new { Id = x.xid.ParentID }, + y => new { Id = y.ParentID }, + (x4, y) => new { x4.xid, x4.y, x4.a, p = y } + ) + .SelectMany( + z => z.p.DefaultIfEmpty(), + (x5, z) => new { x5.xid, z, x5.y, x5.a } + ) + .GroupJoin( + db.Parent, + x => new { Id = x.xid.ParentID }, + y => new { Id = y.Value1 ?? 1 }, + (x6, y) => new { x6.xid, xy = x6.y, x6.a, x6.z, y } + ) + .SelectMany( + z => z.y.DefaultIfEmpty(), + (x7, z) => new { x7.xid, z, x7.xy, x7.a, xz = x7.z } + ) + .GroupJoin( + db.Parent, + x => new { Id = x.xid.ParentID }, + y => new { Id = y.ParentID }, + (x8, y) => new { x8.xid, x8.z, x8.xy, x8.a, x8.xz, y } + ) + .SelectMany( + a => a.y.DefaultIfEmpty(), + (x9, a) => new { x9.xid, x9.z, x9.xy, xa = x9.a, x9.xz, a } + ))); + } + + [Test] + public void LeftJoin1() + { + var expected = + from p in Parent + join ch in Child on p.ParentID equals ch.ParentID into lj1 + from ch in lj1.DefaultIfEmpty() + where p.ParentID >= 4 + select new { p, ch }; + + ForEachProvider(db => AreEqual(expected, + from p in db.Parent + join ch in db.Child on p.ParentID equals ch.ParentID into lj1 + from ch in lj1.DefaultIfEmpty() + where p.ParentID >= 4 + select new { p, ch })); + } + + [Test] + public void LeftJoin2() + { + ForEachProvider(db => AreEqual( + from p in Parent + join ch in Child on p.ParentID equals ch.ParentID into lj1 + from ch in lj1.DefaultIfEmpty() + select new { p, ch }, + from p in db.Parent + join ch in db.Child on p.ParentID equals ch.ParentID into lj1 + from ch in lj1.DefaultIfEmpty() + select new { p, ch })); + } + + [Test] + public void LeftJoin3() + { + ForEachProvider(db => AreEqual( + from c in Child select c.Parent, + from c in db.Child select c.Parent)); + } + + [Test] + public void LeftJoin4() + { + ForEachProvider(db => AreEqual( + Parent + .GroupJoin(Child, + x => new { x.ParentID, x.Value1 }, + y => new { y.ParentID, Value1 = (int?)y.ParentID }, + (x, y) => new { Parent = x, Child = y }) + .SelectMany( + y => y.Child.DefaultIfEmpty(), + (x, y) => new { x.Parent, Child = x.Child.FirstOrDefault() }) + .Where(x => x.Parent.ParentID == 1 && x.Parent.Value1 != null) + .OrderBy(x => x.Parent.ParentID), + db.Parent + .GroupJoin(db.Child, + x => new { x.ParentID, x.Value1 }, + y => new { y.ParentID, Value1 = (int?)y.ParentID }, + (x, y) => new { Parent = x, Child = y }) + .SelectMany( + y => y.Child.DefaultIfEmpty(), + (x, y) => new { x.Parent, Child = x.Child.FirstOrDefault() }) + .Where(x => x.Parent.ParentID == 1 && x.Parent.Value1 != null) + .OrderBy(x => x.Parent.ParentID))); + } + + public enum EnumInt + { + [MapValue(1)] One + } + + [TableName("Child")] + public class EnumChild + { + public int ParentID; + public EnumInt ChildID; + } + + [Test] + public void LeftJoin5() + { + ForEachProvider(db => + { + var q = + from p in db.Parent + join ch in new Table<EnumChild>(db) on p.ParentID equals ch.ParentID into lj1 + from ch in lj1.DefaultIfEmpty() + where ch == null + select new { p, ch }; + + var list = q.ToList(); + list.ToString(); + }); + } + + [Test] + public void SubQueryJoin() + { + var expected = + from p in Parent + join ch in + from c in Child + where c.ParentID > 0 + select new { c.ParentID, c.ChildID } + on p.ParentID equals ch.ParentID into lj1 + from ch in lj1.DefaultIfEmpty() + select p; + + ForEachProvider(db => AreEqual(expected, + from p in db.Parent + join ch in + from c in db.Child + where c.ParentID > 0 + select new { c.ParentID, c.ChildID } + on p.ParentID equals ch.ParentID into lj1 + from ch in lj1.DefaultIfEmpty() + select p)); + } + + [Test] + public void ReferenceJoin1() + { + ForEachProvider(new[] { ProviderName.Access }, db => AreEqual( + from c in Child join g in GrandChild on c equals g.Child select new { c.ParentID, g.GrandChildID }, + from c in db.Child join g in db.GrandChild on c equals g.Child select new { c.ParentID, g.GrandChildID })); + } + + [Test] + public void ReferenceJoin2() + { + ForEachProvider(new[] { ProviderName.Access }, db => AreEqual( + from g in GrandChild + join c in Child on g.Child equals c + select new { c.ParentID, g.GrandChildID }, + from g in db.GrandChild + join c in db.Child on g.Child equals c + select new { c.ParentID, g.GrandChildID })); + } + + [Test] + public void JoinByAnonymousTest() + { + ForEachProvider(new[] { ProviderName.Access }, db => AreEqual( + from p in Parent + join c in Child on new { Parent = p, p.ParentID } equals new { c.Parent, c.ParentID } + select new { p.ParentID, c.ChildID }, + from p in db.Parent + join c in db.Child on new { Parent = p, p.ParentID } equals new { c.Parent, c.ParentID } + select new { p.ParentID, c.ChildID })); + } + + [Test] + public void FourTableJoin() + { + ForEachProvider(db => AreEqual( + from p in Parent + join c1 in Child on p.ParentID equals c1.ParentID + join c2 in GrandChild on c1.ParentID equals c2.ParentID + join c3 in GrandChild on c2.ParentID equals c3.ParentID + select new { p, c1Key = c1.ChildID, c2Key = c2.GrandChildID, c3Key = c3.GrandChildID }, + from p in db.Parent + join c1 in db.Child on p.ParentID equals c1.ParentID + join c2 in db.GrandChild on c1.ParentID equals c2.ParentID + join c3 in db.GrandChild on c2.ParentID equals c3.ParentID + select new { p, c1Key = c1.ChildID, c2Key = c2.GrandChildID, c3Key = c3.GrandChildID })); + } + + [Test] + public void ProjectionTest1() + { + ForEachProvider(db => AreEqual( + from p1 in Person + join p2 in Person on p1.ID equals p2.ID + select new { ID1 = new { Value = p1.ID }, FirstName2 = p2.FirstName, } into p1 + select p1.ID1.Value, + from p1 in db.Person + join p2 in db.Person on p1.ID equals p2.ID + select new { ID1 = new { Value = p1.ID }, FirstName2 = p2.FirstName, } into p1 + select p1.ID1.Value)); + } + + [Test] + public void LeftJoinTest() + { + // Reproduces the problem described here: http://rsdn.ru/forum/prj.rfd/4221837.flat.aspx + ForEachProvider( + //Providers.Select(p => p.Name).Except(new[] { ProviderName.SQLite }).ToArray(), + db => + { + var q = + from p1 in db.Person + join p2 in db.Person on p1.ID equals p2.ID into g + from p2 in g.DefaultIfEmpty() // yes I know the join will always succeed and it'll never be null, but just for test's sake :) + select new { p1, p2 }; + + var list = q.ToList(); // NotImplementedException? :( + Assert.That(list, Is.Not.Empty); + }); + } + + [Test] + public void LeftJoinTest2() + { + // THIS TEST MUST BE RUN IN RELEASE CONFIGURATION (BECAUSE IT PASSES UNDER DEBUG CONFIGURATION) + // Reproduces the problem described here: http://rsdn.ru/forum/prj.rfd/4221837.flat.aspx + + ForEachProvider( + Providers.Select(p => p.Name).Except(new[] { ProviderName.SQLite }).ToArray(), + db => + { + var q = + from p1 in db.Patient + join p2 in db.Patient on p1.Diagnosis equals p2.Diagnosis into g + from p2 in g.DefaultIfEmpty() // yes I know the join will always succeed and it'll never be null, but just for test's sake :) + join p3 in db.Person on p2.PersonID equals p3.ID + select new { p1, p2, p3 }; + + var arr = q.ToArray(); // NotImplementedException? :( + Assert.That(arr, Is.Not.Empty); + }); + } + + [Test] + public void StackOverflow([IncludeDataContexts("Sql2008", "Sql2012")] string context) + { + using (var db = new TestDbManager(context)) + { + var q = + from c in db.Child + join p in db.Parent on c.ParentID equals p.ParentID + select new { p, c }; + + for (var i = 0; i < 100; i++) + { + q = + from c in q + join p in db.Parent on c.p.ParentID equals p.ParentID + select new { p, c.c }; + } + + var list = q.ToList(); + } + } + + [Test] + public void ApplyJoin([IncludeDataContexts("Sql2008")] string context) + { + using (var db = new TestDbManager(context)) + { + var q = + from ch in db.Child + from p in new Model.Functions(db).GetParentByID(ch.Parent.ParentID) + select p; + + q.ToList(); + } + } + + [Test] + public void Issue257([DataContexts] string context) + { + using (var db = GetDataContext(context)) + { + var q = + from m in db.Types + join p in db.Parent on m.ID equals p.ParentID + group m by new + { + m.DateTimeValue.Date + } + into b + select new + { + QualiStatusByDate = b.Key, + Count = b.Count() + }; + + q.ToList(); + } + } + } +}