Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/NHibernate.DomainModel/Northwind/Entities/Animal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ public class Animal
public virtual Animal FatherOrMother => Father ?? Mother;
}

public abstract class Reptile : Animal
public interface IReptile
{
EnumStoredAsString Enum1 { get; }
}

public abstract class Reptile : Animal, IReptile
{
public virtual double BodyTemperature { get; set; }

Expand Down
187 changes: 187 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/GH2858/FixtureByCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using System;
using System.Collections.Generic;
using System.Linq;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Mapping.ByCode;
using NUnit.Framework;
using NHibernate.Linq;

namespace NHibernate.Test.NHSpecificTest.GH2858
{
using System.Threading.Tasks;
[TestFixture]
public class ByCodeFixtureAsync : TestCaseMappingByCode
{
protected override HbmMapping GetMappings()
{
var mapper = new ModelMapper();

mapper.Class<Department>(
rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name);
});
mapper.Class<Project>(
rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name);
rc.ManyToOne(x => x.Department, m => m.Column("DepartmentId"));
});
mapper.Class<Issue>(
rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name);
rc.IdBag(
x => x.Departments,
m => m.Table("IssuesToDepartments"),
r => r.ManyToMany());
rc.ManyToOne(x => x.Project, m => m.Column("ProjectId"));
});
mapper.Class<TimeChunk>(
rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.ManyToOne(x => x.Issue, m => m.Column("IssueId"));
rc.Property(x => x.Seconds);
});

return mapper.CompileMappingForAllExplicitlyAddedEntities();
}

protected override void OnSetUp()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var deptA = new Department {Name = "A"};
session.Save(deptA);
var deptB = new Department {Name = "B"};
session.Save(deptB);
var deptC = new Department {Name = "C"};
session.Save(deptC);
var deptD = new Department {Name = "D"};
session.Save(deptD);
var deptE = new Department {Name = "E"};
session.Save(deptE);

var projectX = new Project {Name = "X", Department = deptA};
session.Save(projectX);
var projectY = new Project {Name = "Y", Department = deptC};
session.Save(projectY);
var projectZ = new Project {Name = "Z", Department = deptE};
session.Save(projectZ);

var issue1 = new Issue {Name = "TEST-1", Project = projectX,};
session.Save(issue1);
var issue2 = new Issue {Name = "TEST-2", Project = projectX, Departments = {deptA},};
session.Save(issue2);
var issue3 = new Issue {Name = "TEST-3", Project = projectX, Departments = {deptA, deptB},};
session.Save(issue3);
var issue4 = new Issue {Name = "TEST-4", Project = projectY,};
session.Save(issue4);
var issue5 = new Issue {Name = "TEST-5", Project = projectY, Departments = {deptD}};
session.Save(issue5);

session.Save(new TimeChunk {Issue = issue1});
session.Save(new TimeChunk {Issue = issue1});
session.Save(new TimeChunk {Issue = issue2});
session.Save(new TimeChunk {Issue = issue2});
session.Save(new TimeChunk {Issue = issue3});
session.Save(new TimeChunk {Issue = issue3});
session.Save(new TimeChunk {Issue = issue4});
session.Save(new TimeChunk {Issue = issue4});
session.Save(new TimeChunk {Issue = issue5});
session.Save(new TimeChunk {Issue = issue5});

transaction.Commit();
}
}

protected override void OnTearDown()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
session.Delete("from System.Object");
transaction.Commit();
}
}

[Test(Description = "GH-2857")]
public async Task GroupLevelQueryAsync()
{
using (var session = OpenSession())
{
var query = session.Query<ITimeChunk>()
.Select(x => new object[] {(object) x})
.GroupBy(g => new object[] {(Guid?) (((ITimeChunk) g[0]).Issue.Project.Id)}, v => (ITimeChunk) v[0])
.Select(r => new object[] {r.Key, r.Sum(t => (int?) t.Seconds)});

var results = await (query.ToListAsync());
Assert.That(results, Has.Count.EqualTo(2));
}
}

[Test(Description = "GH-2857")]
public async Task GroupLevelQuery_SimplifiedAsync()
{
using (var session = OpenSession())
{
var query = session.Query<ITimeChunk>()
.Select(x => new object[] {x})
.GroupBy(g => new object[] {((ITimeChunk) g[0]).Issue.Project.Id}, v => (ITimeChunk) v[0])
.Select(r => new object[] {r.Key, r.Sum(t => (int?) t.Seconds)});

var results = await (query.ToListAsync());
Assert.That(results, Has.Count.EqualTo(2));
}
}

[Test]
public async Task SelectManySubQueryWithCoalesceAsync()
{
using (var session = OpenSession())
{
var usedDepartments = session.Query<ITimeChunk>()
.SelectMany(x => ((IEnumerable<object>) x.Issue.Departments).DefaultIfEmpty().Select(d => (object) ((Guid?) ((Guid?) (((IDepartment) d).Id) ?? x.Issue.Project.Department.Id))))
.Where(id => id != null)
.Select(id => (Guid?) id);

var result = session.Query<IDepartment>()
.Where(d => usedDepartments.Contains(d.Id))
.Select(d => new {d.Id, d.Name});

Assert.That(await (result.ToListAsync()), Has.Count.EqualTo(4));
}
}

[Test]
public async Task SelectManySubQueryWithCoalesce_SimplifiedAsync()
{
using (var session = OpenSession())
{
var usedDepartments = session.Query<ITimeChunk>()
.SelectMany(x => ((IEnumerable<object>) x.Issue.Departments).DefaultIfEmpty().Select(d => (Guid?) ((IDepartment) d).Id ?? x.Issue.Project.Department.Id));

var result = session.Query<IDepartment>()
.Where(d => usedDepartments.Contains(d.Id))
.Select(d => new {d.Id, d.Name});

Assert.That(await (result.ToListAsync()), Has.Count.EqualTo(4));
}
}
}
}
10 changes: 10 additions & 0 deletions src/NHibernate.Test/Linq/ParameterTypeLocatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ public void SubClassStringEnumTest()
);
}

[Test]
public void SubClassAsUnamppedInterfaceStringEnumTest()
{
AssertResults(
new Dictionary<string, Predicate<IType>> {{"0", o => o is EnumStoredAsStringType}},
db.Animals.Where(o => o.Children.OfType<IReptile>().Any(r => r.Enum1 == EnumStoredAsString.Unspecified)),
db.Animals.Where(o => o.Children.OfType<IReptile>().Any(r => EnumStoredAsString.Unspecified == r.Enum1))
);
}

[Test]
public void EqualsMethodStringTest()
{
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate.Test/Linq/TryGetMappedTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public void SelfCastNotMappedTest()
false,
typeof(A).FullName,
null,
o => o is SerializableType serializableType && serializableType.ReturnedClass == typeof(object));
o => o is EntityType entityType && entityType.ReturnedClass == typeof(A));
}

[Test]
Expand Down
61 changes: 61 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH2858/Entity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;

namespace NHibernate.Test.NHSpecificTest.GH2858
{
public interface IDepartment
{
Guid Id { get; set; }
string Name { get; set; }
}

public class Department : IDepartment
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
}

public interface IProject
{
Guid Id { get; set; }
string Name { get; set; }
Department Department { get; set; }
}

public class Project : IProject
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual Department Department { get; set; }
}

public interface IIssue
{
Guid Id { get; set; }
string Name { get; set; }
Project Project { get; set; }
IList<Department> Departments { get; set; }
}

public class Issue : IIssue
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Department> Departments { get; set; } = new List<Department>();
public virtual Project Project { get; set; }
}

public interface ITimeChunk
{
Guid Id { get; set; }
Issue Issue { get; set; }
int Seconds { get; set; }
}

public class TimeChunk : ITimeChunk
{
public virtual Guid Id { get; set; }
public virtual Issue Issue { get; set; }
public virtual int Seconds { get; set; }
}
}
Loading