From 8d11eca9a837135fc16086b6267d14f6e2bab43f Mon Sep 17 00:00:00 2001 From: mazhar Date: Mon, 16 Oct 2017 01:09:22 +0500 Subject: [PATCH 1/3] Added unit test for #750 - AliasToBean failure --- .../Async/NHSpecificTest/GH0750/Fixture.cs | 115 ++++++++++++++++++ .../NHSpecificTest/GH0750/Fixture.cs | 113 +++++++++++++++++ .../NHSpecificTest/GH0750/Mappings.hbm.xml | 47 +++++++ .../NHSpecificTest/GH0750/Order.cs | 52 ++++++++ .../NHSpecificTest/GH0750/OrderLine.cs | 51 ++++++++ .../NHSpecificTest/GH0750/Product.cs | 41 +++++++ 6 files changed, 419 insertions(+) create mode 100644 src/NHibernate.Test/Async/NHSpecificTest/GH0750/Fixture.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH0750/Fixture.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH0750/Mappings.hbm.xml create mode 100644 src/NHibernate.Test/NHSpecificTest/GH0750/Order.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH0750/OrderLine.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH0750/Product.cs diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH0750/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH0750/Fixture.cs new file mode 100644 index 00000000000..3b8e7798643 --- /dev/null +++ b/src/NHibernate.Test/Async/NHSpecificTest/GH0750/Fixture.cs @@ -0,0 +1,115 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by AsyncGenerator. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + +using System.Collections.Generic; +using NHibernate.Criterion; +using NHibernate.Transform; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH0750 +{ + using System.Threading.Tasks; + using System.Threading; + + [TestFixture] + public class FixtureAsync : BugTestCase + { + protected override void OnSetUp() + { + using (ISession session = OpenSession()) + using (ITransaction tx = session.BeginTransaction()) + { + var greenTea = new Product() + { + ProductId = 1, + Name = "Green Tea", + UnitPrice = 5 + }; + + session.Save(greenTea); + + var blackTea = new Product() + { + ProductId = 2, + Name = "Black Tea", + UnitPrice = 10 + }; + + session.Save(blackTea); + + var greenTeaOrder = new Order() + { + OrderId = 1, + OrderDate = System.DateTime.Now + }; + + session.Save(greenTeaOrder); + + greenTeaOrder.OrderLines.Add(new OrderLine() { Order = greenTeaOrder, Product = greenTea, Quantity = 2, UnitPrice = greenTea.UnitPrice ?? 0 }); + + session.Save(greenTeaOrder); + + var blackTeaOrder = new Order() + { + OrderId = 2, + OrderDate = System.DateTime.Now + }; + + session.Save(blackTeaOrder); + + blackTeaOrder.OrderLines.Add(new OrderLine() { Order = blackTeaOrder, Product = blackTea, Quantity = 5, UnitPrice = blackTea.UnitPrice ?? 0 }); + + session.Save(blackTeaOrder); + tx.Commit(); + } + } + + protected override void OnTearDown() + { + using (var s = OpenSession()) + using (var tx = s.BeginTransaction()) + { + s.CreateQuery("delete from OrderLine").ExecuteUpdate(); + s.CreateQuery("delete from System.Object").ExecuteUpdate(); + tx.Commit(); + } + } + + [Test] + public void MapQueryResultWithAliasToBeanTransformerAsync() + { + Assert.DoesNotThrowAsync(() => GetSaleSummariesAsync()); + } + + public async Task> GetSaleSummariesAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + using (var session = OpenSession()) + using (var tx = session.BeginTransaction()) + { + var criteria = session + .CreateCriteria("O") + .CreateCriteria("O.OrderLines", "OI", SqlCommand.JoinType.InnerJoin) + .CreateCriteria("OI.Product", "P", SqlCommand.JoinType.InnerJoin); + + var summaeries = await (criteria + .SetProjection(Projections.ProjectionList().Add(Projections.Property("P.ProductId"), "ProductId") + .Add(Projections.Property("P.Name"), "Name") + .Add(Projections.Sum(Projections.Cast(NHibernateUtil.Int32, Projections.Property("OI.Quantity"))), "TotalQuantity") + .Add(Projections.Sum("OI.UnitPrice"), "TotalPrice") + .Add(Projections.GroupProperty("P.ProductId")) + .Add(Projections.GroupProperty("P.Name"))) + .SetResultTransformer(Transformers.AliasToBean(typeof(ProductSummary))) + .ListAsync(cancellationToken)); + await (tx.CommitAsync(cancellationToken)); + return summaeries; + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH0750/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH0750/Fixture.cs new file mode 100644 index 00000000000..1a1e32beb88 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH0750/Fixture.cs @@ -0,0 +1,113 @@ +using System.Collections.Generic; +using NHibernate.Criterion; +using NHibernate.Transform; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH0750 +{ + public class ProductSummary + { + public int ProductId { get; set; } + + public string Name { get; set; } + + public int TotalQuantity { get; set; } + + public decimal TotalPrice { get; set; } + } + + [TestFixture] + public class Fixture : BugTestCase + { + protected override void OnSetUp() + { + using (ISession session = OpenSession()) + using (ITransaction tx = session.BeginTransaction()) + { + var greenTea = new Product() + { + ProductId = 1, + Name = "Green Tea", + UnitPrice = 5 + }; + + session.Save(greenTea); + + var blackTea = new Product() + { + ProductId = 2, + Name = "Black Tea", + UnitPrice = 10 + }; + + session.Save(blackTea); + + var greenTeaOrder = new Order() + { + OrderId = 1, + OrderDate = System.DateTime.Now + }; + + session.Save(greenTeaOrder); + + greenTeaOrder.OrderLines.Add(new OrderLine() { Order = greenTeaOrder, Product = greenTea, Quantity = 2, UnitPrice = greenTea.UnitPrice ?? 0 }); + + session.Save(greenTeaOrder); + + var blackTeaOrder = new Order() + { + OrderId = 2, + OrderDate = System.DateTime.Now + }; + + session.Save(blackTeaOrder); + + blackTeaOrder.OrderLines.Add(new OrderLine() { Order = blackTeaOrder, Product = blackTea, Quantity = 5, UnitPrice = blackTea.UnitPrice ?? 0 }); + + session.Save(blackTeaOrder); + tx.Commit(); + } + } + + protected override void OnTearDown() + { + using (var s = OpenSession()) + using (var tx = s.BeginTransaction()) + { + s.CreateQuery("delete from OrderLine").ExecuteUpdate(); + s.CreateQuery("delete from System.Object").ExecuteUpdate(); + tx.Commit(); + } + } + + [Test] + public void MapQueryResultWithAliasToBeanTransformer() + { + Assert.DoesNotThrow(() => GetSaleSummaries()); + } + + public IList GetSaleSummaries() + { + using (var session = OpenSession()) + using (var tx = session.BeginTransaction()) + { + var criteria = session + .CreateCriteria("O") + .CreateCriteria("O.OrderLines", "OI", SqlCommand.JoinType.InnerJoin) + .CreateCriteria("OI.Product", "P", SqlCommand.JoinType.InnerJoin); + + var summaeries = criteria + .SetProjection(Projections.ProjectionList().Add(Projections.Property("P.ProductId"), "ProductId") + .Add(Projections.Property("P.Name"), "Name") + .Add(Projections.Sum(Projections.Cast(NHibernateUtil.Int32, Projections.Property("OI.Quantity"))), "TotalQuantity") + .Add(Projections.Sum("OI.UnitPrice"), "TotalPrice") + .Add(Projections.GroupProperty("P.ProductId")) + .Add(Projections.GroupProperty("P.Name"))) + .SetResultTransformer(Transformers.AliasToBean(typeof(ProductSummary))) + .List(); + tx.Commit(); + return summaeries; + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH0750/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/GH0750/Mappings.hbm.xml new file mode 100644 index 00000000000..1f03d82f675 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH0750/Mappings.hbm.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/NHibernate.Test/NHSpecificTest/GH0750/Order.cs b/src/NHibernate.Test/NHSpecificTest/GH0750/Order.cs new file mode 100644 index 00000000000..58cfd3ab86f --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH0750/Order.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; + +namespace NHibernate.Test.NHSpecificTest.GH0750 +{ + public class Order + { + private readonly ISet _orderLines; + private DateTime? _orderDate; + private int _orderId; + + public Order() + { + _orderLines = new HashSet(); + } + + public virtual int OrderId + { + get { return _orderId; } + set { _orderId = value; } + } + + public virtual DateTime? OrderDate + { + get { return _orderDate; } + set { _orderDate = value; } + } + + public virtual ISet OrderLines + { + get { return _orderLines; } + } + + public virtual void AddOrderLine(OrderLine orderLine) + { + if (!_orderLines.Contains(orderLine)) + { + orderLine.Order = this; + _orderLines.Add(orderLine); + } + } + + public virtual void RemoveOrderLine(OrderLine orderLine) + { + if (_orderLines.Contains(orderLine)) + { + _orderLines.Remove(orderLine); + orderLine.Order = null; + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH0750/OrderLine.cs b/src/NHibernate.Test/NHSpecificTest/GH0750/OrderLine.cs new file mode 100644 index 00000000000..c7bbe8a4aac --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH0750/OrderLine.cs @@ -0,0 +1,51 @@ +namespace NHibernate.Test.NHSpecificTest.GH0750 +{ + public class OrderLine + { + private int _orderLineId; + private Order _order; + private Product _product; + private int _quantity; + private decimal _unitPrice; + + public OrderLine() : this(null, null) + { + } + + public OrderLine(Order order, Product product) + { + _order = order; + _product = product; + } + + public virtual int OrderLineId + { + get { return _orderLineId; } + set { _orderLineId = value; } + } + + public virtual Order Order + { + get { return _order; } + set { _order = value; } + } + + public virtual Product Product + { + get { return _product; } + set { _product = value; } + } + + public virtual decimal UnitPrice + { + get { return _unitPrice; } + set { _unitPrice = value; } + } + + public virtual int Quantity + { + get { return _quantity; } + set { _quantity = value; } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH0750/Product.cs b/src/NHibernate.Test/NHSpecificTest/GH0750/Product.cs new file mode 100644 index 00000000000..40eb22e0dcd --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH0750/Product.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace NHibernate.Test.NHSpecificTest.GH0750 +{ + public class Product + { + private readonly IList _orderLines; + private decimal? _unitPrice; + private int _productId; + private string _name; + + public Product() + { + _orderLines = new List(); + } + + public virtual int ProductId + { + get { return _productId; } + set { _productId = value; } + } + + public virtual string Name + { + get { return _name; } + set { _name = value; } + } + + public virtual decimal? UnitPrice + { + get { return _unitPrice; } + set { _unitPrice = value; } + } + + public virtual ReadOnlyCollection OrderLines + { + get { return new ReadOnlyCollection(_orderLines); } + } + } +} From 0068255a8b6d993dd8bd61594ce9a31af1158302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Delaporte?= Date: Mon, 16 Oct 2017 18:28:36 +0200 Subject: [PATCH 2/3] Fix #750 - AliasToBean failure with criteria grouping --- src/NHibernate/Transform/AliasToBeanResultTransformer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/NHibernate/Transform/AliasToBeanResultTransformer.cs b/src/NHibernate/Transform/AliasToBeanResultTransformer.cs index 0caabc5696c..96a0677f256 100644 --- a/src/NHibernate/Transform/AliasToBeanResultTransformer.cs +++ b/src/NHibernate/Transform/AliasToBeanResultTransformer.cs @@ -121,6 +121,10 @@ public override IList TransformList(IList collection) /// same visibility and inheritance depth. private void SetProperty(string alias, object value, object resultObj) { + if (alias == null) + // Grouping properties in criteria are selected without alias, just ignore them. + return; + if (TrySet(alias, value, resultObj, _propertiesByNameCaseSensitive)) return; if (TrySet(alias, value, resultObj, _fieldsByNameCaseSensitive)) @@ -299,4 +303,4 @@ public override int GetHashCode() #endregion } -} \ No newline at end of file +} From 22f1c19386f91d040b6708073fd7e843cb9ae353 Mon Sep 17 00:00:00 2001 From: mazharqayyum <569356+mazharqayyum@users.noreply.github.com> Date: Thu, 25 Feb 2021 21:31:03 +0500 Subject: [PATCH 3/3] HQL for delete fails to parse --- .../NHSpecificTest/GH2688/BasketItem.cs | 41 +++++++++ .../NHSpecificTest/GH2688/FixtureByCode.cs | 90 +++++++++++++++++++ .../NHSpecificTest/GH2688/Product.cs | 47 ++++++++++ 3 files changed, 178 insertions(+) create mode 100644 src/NHibernate.Test/NHSpecificTest/GH2688/BasketItem.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH2688/FixtureByCode.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH2688/Product.cs diff --git a/src/NHibernate.Test/NHSpecificTest/GH2688/BasketItem.cs b/src/NHibernate.Test/NHSpecificTest/GH2688/BasketItem.cs new file mode 100644 index 00000000000..c5e8a0a4fc9 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2688/BasketItem.cs @@ -0,0 +1,41 @@ +using NHibernate.Mapping.ByCode; +using NHibernate.Mapping.ByCode.Conformist; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NHibernate.Test.NHSpecificTest.GH2688 +{ + public class BasketItem + { + public virtual int Id { get; set; } + + public virtual string Name { get; set; } + + public virtual decimal Price { get; set; } + + public virtual Product Product { get; set; } + + public virtual int OrderBy { get; set; } + } + + public class BasketItemMap : ClassMapping + { + public BasketItemMap() + { + Id(x => x.Id, m => { + m.Generator(Generators.Identity); + m.Column("BasketItemId"); + }); + Property(x => x.Name); + Property(x => x.Price); + Property(x => x.OrderBy); + ManyToOne(x => x.Product, m => { + m.NotFound(NotFoundMode.Ignore); + m.Column("ProductId"); + }); + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2688/FixtureByCode.cs b/src/NHibernate.Test/NHSpecificTest/GH2688/FixtureByCode.cs new file mode 100644 index 00000000000..dfb1f1382db --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2688/FixtureByCode.cs @@ -0,0 +1,90 @@ +using System.Linq; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH2688 +{ + /// + /// Fixture using 'by code' mappings + /// + /// + /// This fixture is identical to except the mapping is performed + /// by code in the GetMappings method, and does not require the Mappings.hbm.xml file. Use this approach + /// if you prefer. + /// + [TestFixture] + public class ByCodeFixture : TestCaseMappingByCode + { + protected override HbmMapping GetMappings() + { + var mapper = new ModelMapper(); + mapper.AddMapping(); + mapper.AddMapping(); + return mapper.CompileMappingForAllExplicitlyAddedEntities(); + } + + protected override void OnSetUp() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + var e1 = new Product { Name = "Printer Paper", Price = 10 }; + session.Save(e1); + + var e2 = new BasketItem { Name = "Printer Paper", Price = 10, Product = e1, OrderBy = 1 }; + session.Save(e2); + + var e3 = new BasketItem { Name = "Cable", Price = 10, Product = null, OrderBy = 2 }; + session.Save(e3); + + transaction.Commit(); + } + } + + protected override void OnTearDown() + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + // The HQL delete does all the job inside the database without loading the entities, but it does + // not handle delete order for avoiding violating constraints if any. Use + // session.Delete("from System.Object"); + // instead if in need of having NHbernate ordering the deletes, but this will cause + // loading the entities in the session. + session.CreateQuery("delete from System.Object").ExecuteUpdate(); + + transaction.Commit(); + } + } + + [Test] + public void YourTestName() + { + int productId = 0; + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + var product = session.QueryOver() + .Where(p => p.Name == "Printer Paper") + .SingleOrDefault(); + productId = product.Id; + session.Delete(product); + transaction.Commit(); + } + + Assert.DoesNotThrow(() => { DeleteBasketItems(productId); }); + } + + private void DeleteBasketItems(int productId) + { + using (var session = OpenSession()) + using (var transaction = session.BeginTransaction()) + { + session.CreateQuery("delete from BasketItem where Product.Id = " + productId) + .ExecuteUpdate(); + transaction.Commit(); + } + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH2688/Product.cs b/src/NHibernate.Test/NHSpecificTest/GH2688/Product.cs new file mode 100644 index 00000000000..c60e296283e --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH2688/Product.cs @@ -0,0 +1,47 @@ +using NHibernate; +using NHibernate.Mapping; +using NHibernate.Mapping.ByCode; +using NHibernate.Mapping.ByCode.Conformist; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NHibernate.Test.NHSpecificTest.GH2688 +{ + public class Product + { + public virtual int Id { get; set; } + + public virtual string Name { get; set; } + + public virtual decimal Price { get; set; } + + public virtual IList BasketItems { get; set; } + } + + public class ProductMap : ClassMapping + { + public ProductMap() + { + Id(x => x.Id, m => { + m.Generator(Generators.Identity); + m.Column("ProductId"); + }); + Property(x => x.Name); + Property(x => x.Price); + Bag(x => x.BasketItems, bag => { + bag.Inverse(true); + bag.Lazy(CollectionLazy.Lazy); + bag.Cascade(Mapping.ByCode.Cascade.Persist); + bag.OrderBy("OrderBy asc"); + bag.Key(km => + { + km.Column("ProductId"); + km.ForeignKey("none"); + }); + }, a => a.OneToMany()); + } + } +}