Skip to content

Commit d4d4173

Browse files
committed
Separate parameter type detection for Linq queries
1 parent 4b5f71d commit d4d4173

File tree

107 files changed

+5583
-788
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+5583
-788
lines changed

src/NHibernate.DomainModel/Northwind/Entities/Animal.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public class Animal
1414
public virtual string SerialNumber { get; set; }
1515
public virtual string FatherSerialNumber => Father?.SerialNumber;
1616
public virtual bool HasFather => Father != null;
17+
public virtual Animal FatherOrMother => Father ?? Mother;
1718
}
1819

1920
public abstract class Reptile : Animal

src/NHibernate.DomainModel/Northwind/Entities/Role.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ public class Role
88
public virtual bool IsActive { get; set; }
99
public virtual AnotherEntity Entity { get; set; }
1010
public virtual Role ParentRole { get; set; }
11+
public virtual User CreatedBy { get; set; } // Not mapped
1112
}
1213
}

src/NHibernate.DomainModel/Northwind/Entities/User.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,18 @@ public class User : IUser, IEntity
4444

4545
public virtual Role Role { get; set; }
4646

47-
public virtual FeatureSet Features { get; set; }
47+
public virtual User NotMappedUser => this;
48+
49+
public virtual FeatureSet Features { get; set; }
4850

4951
public virtual EnumStoredAsString Enum1 { get; set; }
5052

53+
public virtual EnumStoredAsString? NullableEnum1 { get; set; }
54+
5155
public virtual EnumStoredAsInt32 Enum2 { get; set; }
5256

57+
public virtual EnumStoredAsInt32? NullableEnum2 { get; set; }
58+
5359
public virtual int NotMapped { get; set; }
5460

5561
public virtual Role NotMappedRole { get; set; }

src/NHibernate.DomainModel/Northwind/Entities/UserComponent.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ public class UserComponent2
1313
{
1414
public string OtherProperty1 { get; set; }
1515

16-
public string OtherProperty2 { get; set; }
17-
18-
public string OtherProperty3 => OtherProperty1;
16+
public string OtherProperty2 => OtherProperty1;
1917
}
2018
}

src/NHibernate.DomainModel/Northwind/Entities/UserDto.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23

34
namespace NHibernate.DomainModel.Northwind.Entities
45
{
@@ -9,11 +10,13 @@ public class UserDto
910
public virtual int InvalidLoginAttempts { get; set; }
1011
public virtual string RoleName { get; set; }
1112
public virtual UserDto2 Dto2 { get; set; }
13+
public virtual List<UserDto2> Dto2List { get; set; } = new List<UserDto2>();
1214

1315
public UserDto(int id, string name)
1416
{
1517
Id = id;
1618
Name = name;
19+
Dto2 = new UserDto2();
1720
}
1821
}
1922

src/NHibernate.DomainModel/Northwind/Mappings/User.hbm.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@
1616
<column name="Enum1" length="12" />
1717
</property>
1818

19+
<property name="NullableEnum1" type="NHibernate.DomainModel.Northwind.Entities.EnumStoredAsStringType, NHibernate.DomainModel"
20+
formula="(case when Enum1 = 'Unspecified' then null else Enum1 end)" insert="false" update="false">
21+
</property>
22+
1923
<property name="Enum2" not-null="true" />
2024

25+
<property name="NullableEnum2" formula="(case when Enum2 = 0 then null else Enum2 end)" insert="false" update="false" />
26+
2127
<property name="Features" not-null="true" />
2228

2329
<many-to-one name="Role" class="Role">
@@ -30,7 +36,6 @@
3036

3137
<component name="OtherComponent" class="UserComponent2">
3238
<property name="OtherProperty1" type="AnsiString" />
33-
<property name="OtherProperty2" type="AnsiString" formula="OtherProperty1"/>
3439
</component>
3540
</component>
3641
</class>

src/NHibernate.Test/Async/Linq/ByMethod/AverageTests.cs

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,32 +22,10 @@ public class AverageTestsAsync : LinqTestCase
2222
[Test]
2323
public async Task CanGetAverageOfIntegersAsDoubleAsync()
2424
{
25-
if (Dialect is Oracle8iDialect)
26-
{
27-
// The point of this test is to verify that LINQ's Average over an
28-
// integer columns yields a non-integer result, even on databases
29-
// where the corresponding avg() will yield a return type equal to
30-
// the input type. This means the LINQ provider must generate HQL
31-
// that cast the input to double inside the call to avg(). This works
32-
// fine on most databases, but Oracle causes trouble.
33-
//
34-
// The dialect maps double to "DOUBLE PRECISION" on Oracle, which
35-
// on Oracle has larger precision than C#'s double. When such
36-
// values are returned, ODP.NET will convert it to .Net decimal, which
37-
// has lower precision and thus causes an overflow exception.
38-
//
39-
// Some argue that this is a flaw in ODP.NET, others have created
40-
// local dialects that use e.g. BINARY_DOUBLE instead, which more
41-
// closely matches C#'s IEEE 745 double, see e.g. HHH-1961 and
42-
// serveral blogs.
43-
44-
Assert.Ignore("Not supported on Oracle due to casting/overflow issues.");
45-
}
46-
4725
//NH-2429
4826
var average = await (db.Products.AverageAsync(x => x.UnitsOnOrder));
4927

5028
Assert.AreEqual(average, 10.129870d, 0.000001d);
5129
}
5230
}
53-
}
31+
}

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010

1111
using System.Linq;
12+
using System.Linq.Expressions;
1213
using NHibernate.DomainModel.Northwind.Entities;
1314
using NUnit.Framework;
1415
using NHibernate.Linq;
@@ -64,5 +65,43 @@ public async Task CanQueryOnEnumStoredAsString_Small_1Async()
6465

6566
Assert.AreEqual(expectedCount, query.Count);
6667
}
68+
69+
[Test]
70+
public async Task ConditionalNavigationPropertyAsync()
71+
{
72+
EnumStoredAsString? type = null;
73+
await (db.Users.Where(o => o.Enum1 == EnumStoredAsString.Large).ToListAsync());
74+
await (db.Users.Where(o => EnumStoredAsString.Large != o.Enum1).ToListAsync());
75+
await (db.Users.Where(o => (o.NullableEnum1 ?? EnumStoredAsString.Large) == EnumStoredAsString.Medium).ToListAsync());
76+
await (db.Users.Where(o => ((o.NullableEnum1 ?? type) ?? o.Enum1) == EnumStoredAsString.Medium).ToListAsync());
77+
78+
await (db.Users.Where(o => (o.NullableEnum1.HasValue ? o.Enum1 : EnumStoredAsString.Unspecified) == EnumStoredAsString.Medium).ToListAsync());
79+
await (db.Users.Where(o => (o.Enum1 != EnumStoredAsString.Large
80+
? (o.NullableEnum1.HasValue ? o.Enum1 : EnumStoredAsString.Unspecified)
81+
: EnumStoredAsString.Small) == EnumStoredAsString.Medium).ToListAsync());
82+
83+
84+
await (db.Users.Where(o => (o.Enum1 == EnumStoredAsString.Large ? o.Role : o.Role).Name == "test").ToListAsync());
85+
}
86+
87+
[Test]
88+
public async Task CanQueryComplexExpressionOnEnumStoredAsStringAsync()
89+
{
90+
var type = EnumStoredAsString.Unspecified;
91+
var query = await ((from user in db.Users
92+
where (user.NullableEnum1 == EnumStoredAsString.Large
93+
? EnumStoredAsString.Medium
94+
: user.NullableEnum1 ?? user.Enum1
95+
) == type
96+
select new
97+
{
98+
user,
99+
simple = user.Enum1,
100+
condition = user.Enum1 == EnumStoredAsString.Large ? EnumStoredAsString.Medium : user.Enum1,
101+
coalesce = user.NullableEnum1 ?? EnumStoredAsString.Medium
102+
}).ToListAsync());
103+
104+
Assert.That(query.Count, Is.EqualTo(0));
105+
}
67106
}
68107
}

0 commit comments

Comments
 (0)