Skip to content

Commit 1f5ca0d

Browse files
committed
GH-1879 - Allow Coalesce and Conditional logic on entity properties and collections (LINQ)
1 parent baee90e commit 1f5ca0d

10 files changed

+994
-3
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using NUnit.Framework;
5+
6+
namespace NHibernate.Test.NHSpecificTest.GH1879
7+
{
8+
[TestFixture]
9+
public class CoalesceChildThenAccessMember : GH1879BaseFixture<Issue>
10+
{
11+
protected override void OnSetUp()
12+
{
13+
using (var session = OpenSession())
14+
using (var transaction = session.BeginTransaction())
15+
{
16+
var clientA = new Client { Name = "Albert" };
17+
var clientB = new Client { Name = "Bob" };
18+
var corpA = new CorporateClient { Name = "Alpha", CorporateId = "1234" };
19+
var corpB = new CorporateClient { Name = "Beta", CorporateId = "5647" };
20+
var clientZ = new Client { Name = null }; // A null value should propagate if the entity is non-null
21+
session.Save(clientA);
22+
session.Save(clientB);
23+
session.Save(corpA);
24+
session.Save(corpB);
25+
session.Save(clientZ);
26+
27+
var projectA = new Project { Name = "A", BillingClient = null, Client = clientA };
28+
var projectB = new Project { Name = "B", BillingClient = corpB, Client = clientA };
29+
var projectC = new Project { Name = "C", BillingClient = null, Client = clientB };
30+
var projectD = new Project { Name = "D", BillingClient = corpA, Client = clientB };
31+
var projectE = new Project { Name = "E", BillingClient = clientZ, Client = clientA };
32+
var projectZ = new Project { Name = "Z", BillingClient = null, Client = null };
33+
session.Save(projectA);
34+
session.Save(projectB);
35+
session.Save(projectC);
36+
session.Save(projectD);
37+
session.Save(projectE);
38+
session.Save(projectZ);
39+
40+
session.Save(new Issue { Key = "01", Project = null, Client = null });
41+
session.Save(new Issue { Key = "02", Project = null, Client = clientA });
42+
session.Save(new Issue { Key = "03", Project = null, Client = clientB });
43+
session.Save(new Issue { Key = "04", Project = projectC, Client = clientA });
44+
session.Save(new Issue { Key = "05", Project = projectA, Client = clientB });
45+
session.Save(new Issue { Key = "06", Project = projectB, Client = clientA });
46+
session.Save(new Issue { Key = "07", Project = projectD, Client = clientB });
47+
session.Save(new Issue { Key = "08", Project = projectZ, Client = corpA });
48+
session.Save(new Issue { Key = "09", Project = projectZ, Client = corpB });
49+
session.Save(new Issue { Key = "10", Project = projectE, Client = clientA });
50+
51+
session.Flush();
52+
transaction.Commit();
53+
}
54+
}
55+
56+
[Test]
57+
public void WhereClause()
58+
{
59+
AreEqual(
60+
// Actual
61+
q => q.Where(i => (i.Project.BillingClient ?? i.Project.Client ?? i.Client).Name.StartsWith("A")),
62+
// Expected
63+
q => q.Where(i => (i.Project.BillingClient != null ? i.Project.BillingClient.Name : i.Project.Client != null ? i.Project.Client.Name : i.Client.Name).StartsWith("A"))
64+
);
65+
}
66+
67+
[Test]
68+
public void SelectClause()
69+
{
70+
AreEqual(
71+
// Actual
72+
q => q.OrderBy(i => i.Key)
73+
.Select(i => (i.Project.BillingClient ?? i.Project.Client ?? i.Client).Name),
74+
// Expected
75+
q => q.OrderBy(i => i.Key)
76+
.Select(i => i.Project.BillingClient != null ? i.Project.BillingClient.Name : i.Project.Client != null ? i.Project.Client.Name : i.Client.Name)
77+
);
78+
}
79+
80+
[Test]
81+
public void SelectClauseToAnon()
82+
{
83+
AreEqual(
84+
// Actual
85+
q => q.OrderBy(i => i.Key)
86+
.Select(i => new { i.Key, Client = (i.Project.BillingClient ?? i.Project.Client ?? i.Client).Name }),
87+
// Expected
88+
q => q.OrderBy(i => i.Key)
89+
.Select(i => new { i.Key, Client = i.Project.BillingClient != null ? i.Project.BillingClient.Name : i.Project.Client != null ? i.Project.Client.Name : i.Client.Name })
90+
);
91+
}
92+
93+
[Test]
94+
public void OrderByClause()
95+
{
96+
AreEqual(
97+
// Actual
98+
q => q.OrderBy(i => (i.Project.BillingClient ?? i.Project.Client ?? i.Client).Name ?? "ZZZ")
99+
.ThenBy(i => i.Key)
100+
.Select(i => i.Key),
101+
// Expected
102+
q => q.OrderBy(i => (i.Project.BillingClient != null ? i.Project.BillingClient.Name : i.Project.Client != null ? i.Project.Client.Name : i.Client.Name) ?? "ZZZ")
103+
.ThenBy(i => i.Key)
104+
.Select(i => i.Key)
105+
);
106+
}
107+
108+
[Test]
109+
public void GroupByClause()
110+
{
111+
AreEqual(
112+
// Actual
113+
q => q.GroupBy(i => (i.Project.BillingClient ?? i.Project.Client ?? i.Client).Name)
114+
.OrderBy(x => x.Key ?? "ZZZ")
115+
.Select(grp => new { grp.Key, Count = grp.Count() }),
116+
// Expected
117+
q => q.GroupBy(i => i.Project.BillingClient != null ? i.Project.BillingClient.Name : i.Project.Client != null ? i.Project.Client.Name : i.Client.Name)
118+
.OrderBy(x => x.Key ?? "ZZZ")
119+
.Select(grp => new { grp.Key, Count = grp.Count() })
120+
);
121+
}
122+
}
123+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
using System;
2+
using System.Linq;
3+
using System.Linq.Expressions;
4+
using NUnit.Framework;
5+
6+
namespace NHibernate.Test.NHSpecificTest.GH1879
7+
{
8+
[TestFixture]
9+
public class CoalesceSiblingsThenAccessMember : GH1879BaseFixture<Project>
10+
{
11+
protected override void OnSetUp()
12+
{
13+
using (var session = OpenSession())
14+
using (var transaction = session.BeginTransaction())
15+
{
16+
var clientA = new Client { Name = "Albert" };
17+
var clientB = new Client { Name = "Bob" };
18+
var corpA = new CorporateClient { Name = "Alpha", CorporateId = "1234" };
19+
var corpB = new CorporateClient { Name = "Beta", CorporateId = "5647" };
20+
var clientZ = new Client { Name = null }; // A null value should propagate if the entity is non-null
21+
session.Save(clientA);
22+
session.Save(clientB);
23+
session.Save(corpA);
24+
session.Save(corpB);
25+
session.Save(clientZ);
26+
27+
session.Save(new Project { Name = "A", BillingClient = null, CorporateClient = null, Client = clientA });
28+
session.Save(new Project { Name = "B", BillingClient = null, CorporateClient = null, Client = clientB });
29+
session.Save(new Project { Name = "C", BillingClient = null, CorporateClient = corpA, Client = clientA });
30+
session.Save(new Project { Name = "D", BillingClient = null, CorporateClient = corpB, Client = clientA });
31+
session.Save(new Project { Name = "E", BillingClient = corpA, CorporateClient = null, Client = clientA });
32+
session.Save(new Project { Name = "F", BillingClient = clientB, CorporateClient = null, Client = clientA });
33+
session.Save(new Project { Name = "G", BillingClient = clientZ, CorporateClient = null, Client = clientA });
34+
session.Save(new Project { Name = "Z", BillingClient = null, CorporateClient = null, Client = null });
35+
36+
session.Flush();
37+
transaction.Commit();
38+
}
39+
}
40+
41+
[Test]
42+
public void WhereClause()
43+
{
44+
AreEqual(
45+
// Actual
46+
q => q.Where(p => (p.BillingClient ?? p.CorporateClient ?? p.Client).Name.StartsWith("A")),
47+
// Expected
48+
q => q.Where(p => (p.BillingClient != null ? p.BillingClient.Name : p.CorporateClient != null ? p.CorporateClient.Name : p.Client.Name).StartsWith("A"))
49+
);
50+
}
51+
52+
[Test]
53+
public void SelectClause()
54+
{
55+
AreEqual(
56+
// Actual
57+
q => q.OrderBy(p => p.Name)
58+
.Select(p => (p.BillingClient ?? p.CorporateClient ?? p.Client).Name),
59+
// Expected
60+
q => q.OrderBy(p => p.Name)
61+
.Select(p => p.BillingClient != null ? p.BillingClient.Name : p.CorporateClient != null ? p.CorporateClient.Name : p.Client.Name)
62+
);
63+
}
64+
65+
[Test]
66+
public void SelectClauseToAnon()
67+
{
68+
AreEqual(
69+
// Actual
70+
q => q.OrderBy(p => p.Name)
71+
.Select(p => new { Project = p.Name, Client = (p.BillingClient ?? p.CorporateClient ?? p.Client).Name }),
72+
// Expected
73+
q => q.OrderBy(p => p.Name)
74+
.Select(p => new { Project = p.Name, Client = p.BillingClient != null ? p.BillingClient.Name : p.CorporateClient != null ? p.CorporateClient.Name : p.Client.Name })
75+
);
76+
}
77+
78+
[Test]
79+
public void OrderByClause()
80+
{
81+
AreEqual(
82+
// Actual
83+
q => q.OrderBy(p => (p.BillingClient ?? p.CorporateClient ?? p.Client).Name ?? "ZZZ")
84+
.ThenBy(p => p.Name)
85+
.Select(p => p.Name),
86+
// Expected
87+
q => q.OrderBy(p => (p.BillingClient != null ? p.BillingClient.Name : p.CorporateClient != null ? p.CorporateClient.Name : p.Client.Name) ?? "ZZZ")
88+
.ThenBy(p => p.Name)
89+
.Select(p => p.Name)
90+
);
91+
}
92+
93+
[Test]
94+
public void GroupByClause()
95+
{
96+
AreEqual(
97+
// Actual
98+
q => q.GroupBy(p => (p.BillingClient ?? p.CorporateClient ?? p.Client).Name)
99+
.OrderBy(x => x.Key ?? "ZZZ")
100+
.Select(grp => new { grp.Key, Count = grp.Count() }),
101+
// Expected
102+
q => q.GroupBy(p => p.BillingClient != null ? p.BillingClient.Name : p.CorporateClient != null ? p.CorporateClient.Name : p.Client.Name)
103+
.OrderBy(x => x.Key ?? "ZZZ")
104+
.Select(grp => new { grp.Key, Count = grp.Count() })
105+
);
106+
}
107+
}
108+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using NUnit.Framework;
7+
8+
namespace NHibernate.Test.NHSpecificTest.GH1879
9+
{
10+
[TestFixture]
11+
public class ConditionalThenAccessMember : GH1879BaseFixture<Project>
12+
{
13+
protected override void OnSetUp()
14+
{
15+
using (var session = OpenSession())
16+
using (var transaction = session.BeginTransaction())
17+
{
18+
var clientA = new Client { Name = "Albert" };
19+
var clientB = new Client { Name = "Bob" };
20+
var clientC = new CorporateClient { Name = "Charlie", CorporateId = "1234" };
21+
session.Save(clientA);
22+
session.Save(clientB);
23+
session.Save(clientC);
24+
25+
session.Save(new Project { Name = "A", EmailPref = EmailPref.Primary, Client = clientA, BillingClient = clientB, CorporateClient = clientC, });
26+
session.Save(new Project { Name = "B", EmailPref = EmailPref.Billing, Client = clientA, BillingClient = clientB, CorporateClient = clientC, });
27+
session.Save(new Project { Name = "C", EmailPref = EmailPref.Corp, Client = clientA, BillingClient = clientB, CorporateClient = clientC, });
28+
29+
session.Save(new Project { Name = "D", EmailPref = EmailPref.Primary, Client = null, BillingClient = clientB, CorporateClient = clientC, });
30+
session.Save(new Project { Name = "E", EmailPref = EmailPref.Billing, Client = clientA, BillingClient = null, CorporateClient = clientC, });
31+
session.Save(new Project { Name = "F", EmailPref = EmailPref.Corp, Client = clientA, BillingClient = clientB, CorporateClient = null, });
32+
33+
session.Flush();
34+
transaction.Commit();
35+
}
36+
}
37+
38+
[Test]
39+
public void WhereClause()
40+
{
41+
AreEqual(
42+
// Actual
43+
q => q.Where(p => (p.EmailPref == EmailPref.Primary
44+
? p.Client
45+
: p.EmailPref == EmailPref.Corp
46+
? p.CorporateClient
47+
: p.BillingClient).Name.Length > 3),
48+
// Expected
49+
q => q.Where(p => (p.EmailPref == EmailPref.Primary
50+
? p.Client.Name
51+
: p.EmailPref == EmailPref.Corp
52+
? p.CorporateClient.Name
53+
: p.BillingClient.Name).Length > 3)
54+
);
55+
}
56+
57+
[Test]
58+
public void SelectClause()
59+
{
60+
AreEqual(
61+
// Actual
62+
q => q.OrderBy(p => p.Name)
63+
.Select(p => (p.EmailPref == EmailPref.Primary
64+
? p.Client
65+
: p.EmailPref == EmailPref.Corp
66+
? p.CorporateClient
67+
: p.BillingClient).Name),
68+
// Expected
69+
q => q.OrderBy(p => p.Name)
70+
.Select(p => p.EmailPref == EmailPref.Primary
71+
? p.Client.Name
72+
: p.EmailPref == EmailPref.Corp
73+
? p.CorporateClient.Name
74+
: p.BillingClient.Name)
75+
);
76+
}
77+
78+
[Test]
79+
public void SelectClauseToAnon()
80+
{
81+
AreEqual(
82+
// Actual
83+
q => q.OrderBy(p => p.Name)
84+
.Select(p => new { p.Name, Client = (p.EmailPref == EmailPref.Primary
85+
? p.Client
86+
: p.EmailPref == EmailPref.Corp
87+
? p.CorporateClient
88+
: p.BillingClient).Name }),
89+
// Expected
90+
q => q.OrderBy(p => p.Name)
91+
.Select(p => new { p.Name, Client = p.EmailPref == EmailPref.Primary
92+
? p.Client.Name
93+
: p.EmailPref == EmailPref.Corp
94+
? p.CorporateClient.Name
95+
: p.BillingClient.Name })
96+
);
97+
}
98+
99+
[Test]
100+
public void OrderByClause()
101+
{
102+
AreEqual(
103+
// Actual
104+
q => q.OrderBy(p => (p.EmailPref == EmailPref.Primary
105+
? p.Client
106+
: p.EmailPref == EmailPref.Corp
107+
? p.CorporateClient
108+
: p.BillingClient).Name ?? "ZZZ")
109+
.ThenBy(p => p.Name)
110+
.Select(p => p.Name),
111+
// Expected
112+
q => q.OrderBy(p => (p.EmailPref == EmailPref.Primary
113+
? p.Client.Name
114+
: p.EmailPref == EmailPref.Corp
115+
? p.CorporateClient.Name
116+
: p.BillingClient.Name) ?? "ZZZ")
117+
.ThenBy(p => p.Name)
118+
.Select(p => p.Name)
119+
);
120+
}
121+
122+
[Test]
123+
public void GroupByClause()
124+
{
125+
AreEqual(
126+
// Actual
127+
q => q.GroupBy(p => (p.EmailPref == EmailPref.Primary
128+
? p.Client
129+
: p.EmailPref == EmailPref.Corp
130+
? p.CorporateClient
131+
: p.BillingClient).Name)
132+
.OrderBy(x => x.Key ?? "ZZZ")
133+
.Select(grp => new { grp.Key, Count = grp.Count() }),
134+
// Expected
135+
q => q.GroupBy(p => p.EmailPref == EmailPref.Primary
136+
? p.Client.Name
137+
: p.EmailPref == EmailPref.Corp
138+
? p.CorporateClient.Name
139+
: p.BillingClient.Name)
140+
.OrderBy(x => x.Key ?? "ZZZ")
141+
.Select(grp => new { grp.Key, Count = grp.Count() })
142+
);
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)