From 133b26dbe73c299d3c089fc86d12bb4db87d47e2 Mon Sep 17 00:00:00 2001 From: Vasily Kabanov Date: Tue, 26 Nov 2019 17:55:29 +1100 Subject: [PATCH] Added test case LinqExpressionOnParameterEvaluated for issue originally described under https://github.com/nhibernate/nhibernate-core/issues/2244 --- src/NHibernate.DomainModel/ProductMaterial.cs | 94 +++++++++++++++++++ .../ProductMaterial.hbm.xml | 35 +++++++ .../Linq/LinqQueriesReadWrite.cs | 76 +++++++++++++++ src/NHibernate.Test/Linq/LinqTestCase.cs | 5 +- src/NHibernate.Test/TestCase.cs | 8 ++ 5 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 src/NHibernate.DomainModel/ProductMaterial.cs create mode 100644 src/NHibernate.DomainModel/ProductMaterial.hbm.xml create mode 100644 src/NHibernate.Test/Linq/LinqQueriesReadWrite.cs diff --git a/src/NHibernate.DomainModel/ProductMaterial.cs b/src/NHibernate.DomainModel/ProductMaterial.cs new file mode 100644 index 00000000000..9b2d08d56e6 --- /dev/null +++ b/src/NHibernate.DomainModel/ProductMaterial.cs @@ -0,0 +1,94 @@ + +using System; +using System.Collections.Generic; + +namespace NHibernate.DomainModel +{ + public class EntityVersioned + where TKey: struct, IComparable + { + public static IEqualityComparer KeyComparer { get; protected internal set; } = EqualityComparer.Default; + + public virtual TKey Id { get; set; } + + public virtual int IntegrityVersion { get; set; } + + /// + /// No business key, any 2 instances with same Ids considered equal + /// + public override bool Equals(object obj) + { + if (ReferenceEquals(this, obj)) + return true; + + if (!(obj is EntityVersioned thatEntity)) + return false; + + var thisType = GetTypeUnproxied(); + var thatType = thatEntity.GetTypeUnproxied(); + + if (thisType != thatType) + return false; + + return KeyComparer.Equals(Id, thatEntity.Id); + } + + public override int GetHashCode() + { + return Id.GetHashCode(); + } + + public virtual bool IsTransient => IntegrityVersion <= 0; + + protected virtual System.Type GetTypeUnproxied() + { + return GetTypeUnproxied(this); + } + + protected virtual bool IsPersistentWithSameIdAs(EntityVersioned compareTo) + { + if (compareTo == null) throw new ArgumentNullException(nameof(compareTo)); + + return !IsTransient && !compareTo.IsTransient && KeyComparer.Equals(Id, compareTo.Id); + } + + public static System.Type GetTypeUnproxied(EntityVersioned obj) + { + if (obj == null) throw new ArgumentNullException(nameof(obj)); + + var result = obj.GetType(); + + while (IsProxyOrAccessor(result)) + result = result.BaseType; + + return result; + } + + public static bool IsProxyOrAccessor(System.Type type) => type.Assembly.IsDynamic + || typeof(Intercept.IFieldInterceptorAccessor).IsAssignableFrom(type) + || typeof(Proxy.INHibernateProxy).IsAssignableFrom(type); + } + + public class EntityVersionedWithName : EntityVersioned + where TKey: struct, IComparable + { + public virtual string Name { get; set; } + } + + public class Material : EntityVersionedWithName + { + + public virtual MaterialDefinition MaterialDefinition { get; set; } + + public virtual ProductDefinition ProductDefinition { get; set; } + } + + public class MaterialDefinition : EntityVersionedWithName + { + } + + public class ProductDefinition : EntityVersionedWithName + { + public virtual MaterialDefinition MaterialDefinition { get; set; } + } +} diff --git a/src/NHibernate.DomainModel/ProductMaterial.hbm.xml b/src/NHibernate.DomainModel/ProductMaterial.hbm.xml new file mode 100644 index 00000000000..ee6443b3b49 --- /dev/null +++ b/src/NHibernate.DomainModel/ProductMaterial.hbm.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/NHibernate.Test/Linq/LinqQueriesReadWrite.cs b/src/NHibernate.Test/Linq/LinqQueriesReadWrite.cs new file mode 100644 index 00000000000..00a28af237c --- /dev/null +++ b/src/NHibernate.Test/Linq/LinqQueriesReadWrite.cs @@ -0,0 +1,76 @@ +using System.Linq; +using NHibernate.DomainModel; +using NUnit.Framework; + +namespace NHibernate.Test.Linq +{ + /// + /// Self-contained setup + /// + [TestFixture] + public class LinqQueriesReadWrite : TestCase + { + private static readonly ProductDefinition productDefinition1 = new ProductDefinition() { Id = 1000, MaterialDefinition = new MaterialDefinition { Id = 1 } }; + private static readonly ProductDefinition productDefinition2 = new ProductDefinition() { Id = 1001, MaterialDefinition = new MaterialDefinition { Id = 2 } }; + private static readonly Material material1 = new Material {Id = 1, MaterialDefinition = productDefinition1.MaterialDefinition, ProductDefinition = productDefinition1}; + private static readonly Material material2 = new Material {Id = 2, MaterialDefinition = productDefinition2.MaterialDefinition, ProductDefinition = productDefinition2}; + + protected override string[] Mappings + { + get { return new[] {"ProductMaterial.hbm.xml"}; } + } + + protected override void OnSetUp() + { + using (var session = OpenSession(true)) + { + session.Save(productDefinition1); + session.Save(productDefinition2); + session.Save(material1); + session.Save(material2); + + session.Transaction.Commit(); + } + base.OnSetUp(); + } + + protected override void OnTearDown() + { + using (var session = OpenSession(true)) + { + session.Delete(productDefinition1); + session.Delete(productDefinition2); + session.Delete(material1); + session.Delete(material2); + + session.Transaction.Commit(); + } + + base.OnTearDown(); + } + + [Test(Description = "#2244")] + public void LinqExpressionOnParameterEvaluated() + { + using (var session = OpenSession()) + { + var selectedProducts = new[] { productDefinition1 }; + + var query = session.Query() + .Where(x => selectedProducts.Contains(x.ProductDefinition) && selectedProducts.Select(y => y.MaterialDefinition).Contains(x.MaterialDefinition)); + + //var sessionImpl = session.GetSessionImplementation(); + //var factoryImplementor = sessionImpl.Factory; + + //var nhLinqExpression = new NhLinqExpression(query.Expression, factoryImplementor); + //var translatorFactory = new ASTQueryTranslatorFactory(); + //var translator = translatorFactory.CreateQueryTranslators(nhLinqExpression, null, false, sessionImpl.EnabledFilters, factoryImplementor).First(); + + var result = query.ToList(); + + Assert.AreEqual(1, result.Count); + Assert.AreEqual(material1, result.Single()); + } + } + } +} diff --git a/src/NHibernate.Test/Linq/LinqTestCase.cs b/src/NHibernate.Test/Linq/LinqTestCase.cs index 26503786bb0..c624f968fbe 100755 --- a/src/NHibernate.Test/Linq/LinqTestCase.cs +++ b/src/NHibernate.Test/Linq/LinqTestCase.cs @@ -33,7 +33,8 @@ protected override string[] Mappings "Northwind.Mappings.User.hbm.xml", "Northwind.Mappings.TimeSheet.hbm.xml", "Northwind.Mappings.Animal.hbm.xml", - "Northwind.Mappings.Patient.hbm.xml" + "Northwind.Mappings.Patient.hbm.xml", + "ProductMaterial.hbm.xml" }; } } @@ -69,4 +70,4 @@ protected override void OnTearDown() Assert.That(entities.Select(x => entityIdGetter(x)), Is.EquivalentTo(expectedIds)); } } -} \ No newline at end of file +} diff --git a/src/NHibernate.Test/TestCase.cs b/src/NHibernate.Test/TestCase.cs index 4c9ea610c6d..275a2f23b4c 100644 --- a/src/NHibernate.Test/TestCase.cs +++ b/src/NHibernate.Test/TestCase.cs @@ -372,6 +372,14 @@ protected virtual ISession OpenSession() return Sfi.OpenSession(); } + protected virtual ISession OpenSession(bool beginTransaction) + { + var result = Sfi.OpenSession(); + if (beginTransaction) + result.BeginTransaction(); + return result; + } + protected virtual ISession OpenSession(IInterceptor sessionLocalInterceptor) { return Sfi.WithOptions().Interceptor(sessionLocalInterceptor).OpenSession();