Mercurial > pub > bltoolkit
view UnitTests/Linq/JoinTest.cs @ 5:f7d63a092920
Исправлено условие Where в тех случаях, когда репозитарий не является генериком
author | cin |
---|---|
date | Tue, 10 Mar 2015 16:02:11 +0300 |
parents | f990fcb411a9 |
children |
line wrap: on
line source
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(); } } } }