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()); + } + } +}