Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Dynamic BatchFetchStyle #2959

Merged
merged 13 commits into from
Aug 16, 2022
194 changes: 194 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/NH3530/Fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
//------------------------------------------------------------------------------
// <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;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Loader;
using NUnit.Framework;
using Environment = NHibernate.Cfg.Environment;

namespace NHibernate.Test.NHSpecificTest.NH3530
{
using System.Threading.Tasks;
using System.Threading;
//NH-3530 (GH-1316)
[TestFixture]
public class DynamicBatchFetchStyleFixtureAsync : TestCaseMappingByCode
{
private readonly List<object> _ids = new List<object>();

protected override void Configure(Configuration configuration)
{
base.Configure(configuration);
configuration.SetProperty(Environment.BatchFetchStyle, BatchFetchStyle.Dynamic.ToString());
}

[Test]
public async Task CanLoadEntityAsync()
{
await (PrepareEntitiesAsync(2));

using (var session = OpenSession())
{
var proxy = await (session.LoadAsync<Entity>(_ids[0]));
var result = await (session.GetAsync<Entity>(_ids[1]));

Assert.That(result.Name, Is.Not.Null);

var childrenCount = result.Children.Count;
//Assert.That(NHibernateUtil.IsInitialized(proxy), Is.True);
Assert.That(NHibernateUtil.IsInitialized(proxy.Children), Is.True);
Assert.That(childrenCount, Is.EqualTo(4));
}
}

[KnownBug("GH-2960")]
[Test]
public async Task CanLoadComponentEntityAsync()
{
await (PrepareComponentEntitiesAsync(2));

using (var session = OpenSession())
{
var proxy = await (session.LoadAsync<EntityComponent>(_ids[0]));
var result = await (session.GetAsync<EntityComponent>(_ids[1]));

Assert.That(result.Name, Is.Not.Null);

var childrenCount = result.Children.Count;
Assert.That(NHibernateUtil.IsInitialized(proxy.Children), Is.True);
Assert.That(childrenCount, Is.EqualTo(4));
}
}

[Test]
public async Task CanLoadComponentIdEntityAsync()
{
await (PrepareComponentIdEntitiesAsync(2));

using (var session = OpenSession())
{
var proxy = await (session.LoadAsync<EntityComponentId>(_ids[0]));
var result = await (session.GetAsync<EntityComponentId>(_ids[1]));

Assert.That(result.Name, Is.Not.Null);

var childrenCount = result.Children.Count;
Assert.That(NHibernateUtil.IsInitialized(proxy.Children), Is.True);
Assert.That(childrenCount, Is.EqualTo(4));
}
}

[TestCase(1)]
[TestCase(2)]
[TestCase(3)]
[TestCase(4)]
[TestCase(5)]
public async Task CanLoadBatchAsync(int loadCount)
{
await (PrepareEntitiesAsync(5));

using (var session = OpenSession())
{
foreach (var id in _ids.Take(loadCount))
{
await (session.LoadAsync<Entity>(id));
}

var result = await (session.GetAsync<Entity>(_ids[0]));
var result2 = await (session.GetAsync<Entity>(_ids[1]));
var last = await (session.GetAsync<Entity>(_ids.Last()));

var count = result.Children.Count;
Assert.That(result.Name, Is.Not.Null);
Assert.That(last.Name, Is.Not.Null);
Assert.That(NHibernateUtil.IsInitialized(result2.Children), Is.True);
}
}

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

protected override HbmMapping GetMappings()
{
return EntityMappings.CreateMapping();
}

private async Task PrepareEntitiesAsync(int count, CancellationToken cancellationToken = default(CancellationToken))
{
_ids.Clear();
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
for (int i = 0; i < count; i++)
{
var entity = new Entity { Name = "some name" + 1 };
AddChildren(entity.Children, 4);
_ids.Add((Guid) await (session.SaveAsync(entity, cancellationToken)));
}

await (transaction.CommitAsync(cancellationToken));
}
}

private async Task PrepareComponentEntitiesAsync(int count, CancellationToken cancellationToken = default(CancellationToken))
{
_ids.Clear();
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
for (int i = 0; i < count; i++)
{
var entity = new EntityComponent { Id1 = i, Id2 = i + 1, Name = "some name" + 1 };
AddChildren(entity.Children, 4);

_ids.Add(await (session.SaveAsync(entity, cancellationToken)));
}

await (transaction.CommitAsync(cancellationToken));
}
}

private async Task PrepareComponentIdEntitiesAsync(int count, CancellationToken cancellationToken = default(CancellationToken))
{
_ids.Clear();
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
for (int i = 0; i < count; i++)
{
var entity = new EntityComponentId { Id = new ComponentId { Id1 = i, Id2 = i + 1 }, Name = "some name" + 1 };
AddChildren(entity.Children, 4);
_ids.Add(await (session.SaveAsync(entity, cancellationToken)));
}

await (transaction.CommitAsync(cancellationToken));
}
}

private static void AddChildren<T>(IList<T> list, int count) where T : new()
{
for (int i = 0; i < count; i++)
{
list.Add(new T());
}
}
}
}
91 changes: 91 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/NH3530/Entities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace NHibernate.Test.NHSpecificTest.NH3530
{
public class Entity
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Child> Children { get; set; } = new List<Child>();
}

public class EntityComponent
{
public virtual int Id1 { get; set; }
public virtual int Id2 { get; set; }
public virtual string Name { get; set; }
public virtual IList<ChildForComponent> Children { get; set; } = new List<ChildForComponent>();

public override bool Equals(object obj)
{
return obj == this;
}

public override int GetHashCode()
{
return RuntimeHelpers.GetHashCode(this);
}
}

public class ComponentId
{
public int Id1 { get; set; }
public int Id2 { get; set; }

protected bool Equals(ComponentId other)
{
return Id1 == other.Id1 && Id2 == other.Id2;
}

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ComponentId) obj);
}

public override int GetHashCode()
{
unchecked
{
return (Id1 * 397) ^ Id2;
}
}
}

public class EntityComponentId
{
public virtual ComponentId Id { get; set; }

public virtual string Name { get; set; }
public virtual IList<ChildForComponent> Children { get; set; } = new List<ChildForComponent>();

public override bool Equals(object obj)
{
return obj == this;
}

public override int GetHashCode()
{
return RuntimeHelpers.GetHashCode(this);
}
}

public class Child
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual Guid ParentId { get; set; }
}

public class ChildForComponent
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual int ParentId1 { get; set; }
public virtual int ParentId2 { get; set; }
}
}
108 changes: 108 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/NH3530/EntityMappings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using NHibernate.Cfg.MappingSchema;
using NHibernate.Mapping.ByCode;

namespace NHibernate.Test.NHSpecificTest.NH3530
{
class EntityMappings
{
public static HbmMapping CreateMapping()
{
var mapper = new ModelMapper();
mapper.Class<Entity>(
rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name);
rc.BatchSize(3);
rc.Bag(
x => x.Children,
m =>
{
m.Key(
km =>
{
km.Column("ParentId");
km.ForeignKey("none");
});
m.BatchSize(10);
m.Cascade(Mapping.ByCode.Cascade.All);
},
xr => xr.OneToMany());
});

mapper.Class<EntityComponent>(
rc =>
{
rc.ComposedId(
x =>
{
x.Property(t => t.Id1);
x.Property(e => e.Id2);
});
rc.Property(x => x.Name);
rc.BatchSize(3);
rc.Bag(
x => x.Children,
m =>
{
m.Key(
km =>
{
km.Columns(x => x.Name("ParentId1"), x => x.Name("ParentId2"));
km.ForeignKey("none");
});
m.BatchSize(10);
m.Cascade(Mapping.ByCode.Cascade.All);
},
xr => xr.OneToMany());
});

mapper.Class<EntityComponentId>(
rc =>
{
rc.ComponentAsId(
x => x.Id,
m =>
{
m.Property(t => t.Id1);
m.Property(e => e.Id2);
}
);
rc.Property(x => x.Name);
rc.BatchSize(3);
rc.Bag(
x => x.Children,
m =>
{
m.Key(
km =>
{
km.Columns(x => x.Name("ParentId1"), x => x.Name("ParentId2"));
km.ForeignKey("none");
});
m.BatchSize(10);
m.Cascade(Mapping.ByCode.Cascade.All);
},
xr => xr.OneToMany());
});

mapper.Class<Child>(
rc =>
{
rc.Id(m => m.Id, m => m.Generator(Generators.Guid));
rc.Property(m => m.Name);
rc.Property(m => m.ParentId);
});

mapper.Class<ChildForComponent>(
rc =>
{
rc.Id(m => m.Id, m => m.Generator(Generators.Guid));
rc.Property(m => m.Name);
rc.Property(m => m.ParentId1);
rc.Property(m => m.ParentId2);
});
return mapper.CompileMappingForAllExplicitlyAddedEntities();
}
}
}
Loading