Skip to content

Commit 12fbe7b

Browse files
kevinchaletfredericDelaporte
authored andcommitted
Support IEquatable<T> in the LINQ provider (#1714)
1 parent bced0cd commit 12fbe7b

File tree

7 files changed

+269
-2
lines changed

7 files changed

+269
-2
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,5 +501,15 @@ where item.Discount.Equals(-1)
501501

502502
await (ObjectDumper.WriteAsync(query));
503503
}
504+
505+
[Test]
506+
public async Task WhereEquatableEqualAsync()
507+
{
508+
var query = from item in db.Shippers
509+
where ((IEquatable<Guid>) item.Reference).Equals(Guid.Empty)
510+
select item;
511+
512+
await (ObjectDumper.WriteAsync(query));
513+
}
504514
}
505515
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using System;
12+
using System.Linq;
13+
using NUnit.Framework;
14+
using NHibernate.Linq;
15+
16+
namespace NHibernate.Test.NHSpecificTest.GH1712
17+
{
18+
using System.Threading.Tasks;
19+
using System.Threading;
20+
[TestFixture]
21+
public class FixtureAsync : BugTestCase
22+
{
23+
protected override void OnSetUp()
24+
{
25+
using (var session = OpenSession())
26+
using (var tx = session.BeginTransaction())
27+
{
28+
session.Save(
29+
"GenericEntityWithGuid",
30+
new GenericEntity<Guid>(),
31+
Guid.Parse("093D2C0D-C1A4-42CB-95FC-1039CD0C00B6"));
32+
session.Save("GenericEntityWithLong", new GenericEntity<long>(), 42L);
33+
session.Save("GenericEntityWithString", new GenericEntity<string>(), "Bob l'éponge");
34+
session.Save("GenericEntityWithTimeSpan", new GenericEntity<TimeSpan>(), TimeSpan.FromDays(1));
35+
tx.Commit();
36+
}
37+
}
38+
39+
protected override void OnTearDown()
40+
{
41+
base.OnTearDown();
42+
using (var session = OpenSession())
43+
using (var tx = session.BeginTransaction())
44+
{
45+
session.CreateQuery("delete from System.Object").ExecuteUpdate();
46+
tx.Commit();
47+
}
48+
}
49+
50+
[Test]
51+
public async Task QueryWithIEquatableEqualsShouldNotThrowAsync()
52+
{
53+
using (var session = Sfi.OpenSession())
54+
{
55+
Assert.That(
56+
await (QueryIdAsync("GenericEntityWithGuid", Guid.Parse("093D2C0D-C1A4-42CB-95FC-1039CD0C00B6"), session)),
57+
Is.InstanceOf<GenericEntity<Guid>>());
58+
Assert.That(
59+
await (QueryIdAsync("GenericEntityWithLong", 42L, session)),
60+
Is.InstanceOf<GenericEntity<long>>());
61+
Assert.That(
62+
await (QueryIdAsync("GenericEntityWithString", "Bob l'éponge", session)),
63+
Is.InstanceOf<GenericEntity<string>>());
64+
Assert.That(
65+
await (QueryIdAsync("GenericEntityWithTimeSpan", TimeSpan.FromDays(1), session)),
66+
Is.InstanceOf<GenericEntity<TimeSpan>>());
67+
}
68+
}
69+
70+
private Task<GenericEntity<TId>> QueryIdAsync<TId>(string name, TId id, ISession session, CancellationToken cancellationToken = default(CancellationToken)) where TId : IEquatable<TId>
71+
=> (from e in session.Query<GenericEntity<TId>>(name)
72+
where e.Id.Equals(id)
73+
select e).FirstOrDefaultAsync(cancellationToken);
74+
75+
[Test]
76+
public async Task QueryWithDefaultEqualsShouldNotThrowAsync()
77+
{
78+
using (var session = Sfi.OpenSession())
79+
{
80+
Assert.That(
81+
await ((from e in session.Query<GenericEntity<Guid>>("GenericEntityWithGuid")
82+
where e.Id.Equals(Guid.Parse("093D2C0D-C1A4-42CB-95FC-1039CD0C00B6"))
83+
select e).FirstOrDefaultAsync()),
84+
Is.InstanceOf<GenericEntity<Guid>>());
85+
Assert.That(
86+
await ((from e in session.Query<GenericEntity<long>>("GenericEntityWithLong")
87+
where e.Id.Equals(42L)
88+
select e).FirstOrDefaultAsync()),
89+
Is.InstanceOf<GenericEntity<long>>());
90+
Assert.That(
91+
await ((from e in session.Query<GenericEntity<string>>("GenericEntityWithString")
92+
where e.Id.Equals("Bob l'éponge")
93+
select e).FirstOrDefaultAsync()),
94+
Is.InstanceOf<GenericEntity<string>>());
95+
Assert.That(
96+
await ((from e in session.Query<GenericEntity<TimeSpan>>("GenericEntityWithTimeSpan")
97+
where e.Id.Equals(TimeSpan.FromDays(1))
98+
select e).FirstOrDefaultAsync()),
99+
Is.InstanceOf<GenericEntity<TimeSpan>>());
100+
}
101+
}
102+
}
103+
}

src/NHibernate.Test/Linq/FunctionTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,5 +490,15 @@ where item.Discount.Equals(-1)
490490

491491
ObjectDumper.Write(query);
492492
}
493+
494+
[Test]
495+
public void WhereEquatableEqual()
496+
{
497+
var query = from item in db.Shippers
498+
where ((IEquatable<Guid>) item.Reference).Equals(Guid.Empty)
499+
select item;
500+
501+
ObjectDumper.Write(query);
502+
}
493503
}
494504
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System;
2+
3+
namespace NHibernate.Test.NHSpecificTest.GH1712
4+
{
5+
class GenericEntity<TId> where TId : IEquatable<TId>
6+
{
7+
public virtual TId Id { get; set; }
8+
}
9+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using System.Linq;
3+
using NUnit.Framework;
4+
5+
namespace NHibernate.Test.NHSpecificTest.GH1712
6+
{
7+
[TestFixture]
8+
public class Fixture : BugTestCase
9+
{
10+
protected override void OnSetUp()
11+
{
12+
using (var session = OpenSession())
13+
using (var tx = session.BeginTransaction())
14+
{
15+
session.Save(
16+
"GenericEntityWithGuid",
17+
new GenericEntity<Guid>(),
18+
Guid.Parse("093D2C0D-C1A4-42CB-95FC-1039CD0C00B6"));
19+
session.Save("GenericEntityWithLong", new GenericEntity<long>(), 42L);
20+
session.Save("GenericEntityWithString", new GenericEntity<string>(), "Bob l'éponge");
21+
session.Save("GenericEntityWithTimeSpan", new GenericEntity<TimeSpan>(), TimeSpan.FromDays(1));
22+
tx.Commit();
23+
}
24+
}
25+
26+
protected override void OnTearDown()
27+
{
28+
base.OnTearDown();
29+
using (var session = OpenSession())
30+
using (var tx = session.BeginTransaction())
31+
{
32+
session.CreateQuery("delete from System.Object").ExecuteUpdate();
33+
tx.Commit();
34+
}
35+
}
36+
37+
[Test]
38+
public void QueryWithIEquatableEqualsShouldNotThrow()
39+
{
40+
using (var session = Sfi.OpenSession())
41+
{
42+
Assert.That(
43+
QueryId("GenericEntityWithGuid", Guid.Parse("093D2C0D-C1A4-42CB-95FC-1039CD0C00B6"), session),
44+
Is.InstanceOf<GenericEntity<Guid>>());
45+
Assert.That(
46+
QueryId("GenericEntityWithLong", 42L, session),
47+
Is.InstanceOf<GenericEntity<long>>());
48+
Assert.That(
49+
QueryId("GenericEntityWithString", "Bob l'éponge", session),
50+
Is.InstanceOf<GenericEntity<string>>());
51+
Assert.That(
52+
QueryId("GenericEntityWithTimeSpan", TimeSpan.FromDays(1), session),
53+
Is.InstanceOf<GenericEntity<TimeSpan>>());
54+
}
55+
}
56+
57+
private GenericEntity<TId> QueryId<TId>(string name, TId id, ISession session) where TId : IEquatable<TId>
58+
=> (from e in session.Query<GenericEntity<TId>>(name)
59+
where e.Id.Equals(id)
60+
select e).FirstOrDefault();
61+
62+
[Test]
63+
public void QueryWithDefaultEqualsShouldNotThrow()
64+
{
65+
using (var session = Sfi.OpenSession())
66+
{
67+
Assert.That(
68+
(from e in session.Query<GenericEntity<Guid>>("GenericEntityWithGuid")
69+
where e.Id.Equals(Guid.Parse("093D2C0D-C1A4-42CB-95FC-1039CD0C00B6"))
70+
select e).FirstOrDefault(),
71+
Is.InstanceOf<GenericEntity<Guid>>());
72+
Assert.That(
73+
(from e in session.Query<GenericEntity<long>>("GenericEntityWithLong")
74+
where e.Id.Equals(42L)
75+
select e).FirstOrDefault(),
76+
Is.InstanceOf<GenericEntity<long>>());
77+
Assert.That(
78+
(from e in session.Query<GenericEntity<string>>("GenericEntityWithString")
79+
where e.Id.Equals("Bob l'éponge")
80+
select e).FirstOrDefault(),
81+
Is.InstanceOf<GenericEntity<string>>());
82+
Assert.That(
83+
(from e in session.Query<GenericEntity<TimeSpan>>("GenericEntityWithTimeSpan")
84+
where e.Id.Equals(TimeSpan.FromDays(1))
85+
select e).FirstOrDefault(),
86+
Is.InstanceOf<GenericEntity<TimeSpan>>());
87+
}
88+
}
89+
}
90+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
3+
namespace="NHibernate.Test.NHSpecificTest.GH1712"
4+
assembly="NHibernate.Test">
5+
<class name="GenericEntity`1[[System.Guid]]" entity-name="GenericEntityWithGuid" table="GenericEntityWithGuid">
6+
<id name="Id">
7+
<generator class="assigned" />
8+
</id>
9+
</class>
10+
<class name="GenericEntity`1[[System.Int64]]" entity-name="GenericEntityWithLong" table="GenericEntityWithLong">
11+
<id name="Id">
12+
<generator class="assigned" />
13+
</id>
14+
</class>
15+
<class name="GenericEntity`1[[System.String]]" entity-name="GenericEntityWithString" table="GenericEntityWithString">
16+
<id name="Id">
17+
<generator class="assigned" />
18+
</id>
19+
</class>
20+
<class name="GenericEntity`1[[System.TimeSpan]]" entity-name="GenericEntityWithTimeSpan" table="GenericEntityWithTimeSpan">
21+
<id name="Id">
22+
<generator class="assigned" />
23+
</id>
24+
</class>
25+
</hibernate-mapping>

src/NHibernate/Linq/Functions/EqualsGenerator.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,27 @@ public EqualsGenerator()
3939
ReflectHelper.GetMethodDefinition<Guid>(x => x.Equals(x)),
4040
ReflectHelper.GetMethodDefinition<DateTime>(x => x.Equals(x)),
4141
ReflectHelper.GetMethodDefinition<DateTimeOffset>(x => x.Equals(x)),
42-
ReflectHelper.GetMethodDefinition<bool>(x => x.Equals(default(bool)))
42+
ReflectHelper.GetMethodDefinition<TimeSpan>(x => x.Equals(x)),
43+
ReflectHelper.GetMethodDefinition<bool>(x => x.Equals(default(bool))),
44+
45+
ReflectHelper.GetMethodDefinition<IEquatable<string>>(x => x.Equals(default(string))),
46+
ReflectHelper.GetMethodDefinition<IEquatable<char>>(x => x.Equals(default(char))),
47+
ReflectHelper.GetMethodDefinition<IEquatable<sbyte>>(x => x.Equals(default(sbyte))),
48+
ReflectHelper.GetMethodDefinition<IEquatable<byte>>(x => x.Equals(default(byte))),
49+
ReflectHelper.GetMethodDefinition<IEquatable<short>>(x => x.Equals(default(short))),
50+
ReflectHelper.GetMethodDefinition<IEquatable<ushort>>(x => x.Equals(default(ushort))),
51+
ReflectHelper.GetMethodDefinition<IEquatable<int>>(x => x.Equals(default(int))),
52+
ReflectHelper.GetMethodDefinition<IEquatable<uint>>(x => x.Equals(default(uint))),
53+
ReflectHelper.GetMethodDefinition<IEquatable<long>>(x => x.Equals(default(long))),
54+
ReflectHelper.GetMethodDefinition<IEquatable<ulong>>(x => x.Equals(default(ulong))),
55+
ReflectHelper.GetMethodDefinition<IEquatable<float>>(x => x.Equals(default(float))),
56+
ReflectHelper.GetMethodDefinition<IEquatable<double>>(x => x.Equals(default(double))),
57+
ReflectHelper.GetMethodDefinition<IEquatable<decimal>>(x => x.Equals(default(decimal))),
58+
ReflectHelper.GetMethodDefinition<IEquatable<Guid>>(x => x.Equals(default(Guid))),
59+
ReflectHelper.GetMethodDefinition<IEquatable<DateTime>>(x => x.Equals(default(DateTime))),
60+
ReflectHelper.GetMethodDefinition<IEquatable<DateTimeOffset>>(x => x.Equals(default(DateTimeOffset))),
61+
ReflectHelper.GetMethodDefinition<IEquatable<TimeSpan>>(x => x.Equals(default(TimeSpan))),
62+
ReflectHelper.GetMethodDefinition<IEquatable<bool>>(x => x.Equals(default(bool)))
4363
};
4464
}
4565

@@ -53,4 +73,4 @@ public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject,
5373
visitor.Visit(rhs).ToArithmeticExpression());
5474
}
5575
}
56-
}
76+
}

0 commit comments

Comments
 (0)