Hi all,

In order to make myself clear, I have created a most basic case to
describe my problem. Let's say I have 3 tables:

    CREATE TABLE [dbo].[Product](
        [ProductID] [int] IDENTITY(1,1) NOT NULL,
        [ProductName] [varchar](50) NOT NULL,
     CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED ( [ProductID] ASC )
    ) ON [PRIMARY]

    CREATE TABLE [dbo].[OrderHeader](
        [HeaderID] [int] IDENTITY(1,1) NOT NULL,
        [Comment] [varchar](100) NULL,
     CONSTRAINT [PK_OrderHeader] PRIMARY KEY CLUSTERED ( [HeaderID]
ASC )
    ) ON [PRIMARY]

    CREATE TABLE [dbo].[OrderDetail](
        [HeaderID] [int] NOT NULL, /* FK to OrderHeader table */
        [ProductID] [int] NOT NULL, /* FK to Product table */
        [CreatedOn] [datetime] NOT NULL,
     CONSTRAINT [PK_OrderDetail] PRIMARY KEY CLUSTERED
    (
        [HeaderID] ASC,
        [ProductID] ASC
    )
    ) ON [PRIMARY]

And I have created correponding entity classes and mapping classes.

        public class Product {
                public virtual int? Id { get; set; }

                public virtual string Name { get; set; }
        }

        public class ProductMap : ClassMap<Product> {
                public ProductMap() {
                        Table("Product");

                        Id(x => x.Id, "ProductID").GeneratedBy.Identity();
                        Map(x => x.Name, "ProductName");
                }
        }

        public class OrderHeader {
                public virtual int? Id { get; set; }

                public virtual string Comment { get; set; }

                public virtual IList<OrderDetail> Details { get; set; }
        }

        public class OrderHeaderMap : ClassMap<OrderHeader> {
                public OrderHeaderMap() {
                        Table("OrderHeader");

                        Id(x => x.Id, "HeaderID").GeneratedBy.Identity();
                        Map(x => x.Comment, "Comment");

                        HasMany<OrderDetail>(x =>
x.Details).KeyColumn("HeaderID").Inverse();
                }
        }

        public class OrderDetail {
                public virtual int? OrderHeaderId { get; set; }

                public virtual int? ProductId { get; set; }

                public virtual OrderHeader OrderHeader { get; set; }

                public virtual Product Product { get; set; }

                public virtual DateTime? CreatedOn { get; set; }

                public override bool Equals(object obj) {
                        OrderDetail other = obj as OrderDetail;
                        if (other == null) {
                                return false;
                        } else {
                                return this.ProductId == other.ProductId && 
this.OrderHeaderId ==
other.OrderHeaderId;
                        }
                }

                public override int GetHashCode() {
                        return (OrderHeaderId.ToString() + "|" +
ProductId.ToString()).GetHashCode();
                }
        }

        public class OrderDetailMap : ClassMap<OrderDetail> {
                public OrderDetailMap() {
                        Table("OrderDetail");

                        CompositeId().KeyProperty(x => x.ProductId,
"ProductID").KeyProperty(x => x.OrderHeaderId, "HeaderID");

                        References<OrderHeader>(x => x.OrderHeader,
"HeaderID").Not.Nullable();
                        References<Product>(x => x.Product, 
"ProductID").Not.Nullable();

                        Version(x => 
x.CreatedOn).Column("CreatedOn").Generated.Always();
                }
        }

I have also created NH Session Provider

        public class NHibernateSessionProvider {
                private static ISessionFactory sessionFactory;

                public static ISessionFactory SessionFactory {
                        get {
                                if (sessionFactory == null) {
                                        sessionFactory = createSessionFactory();
                                }
                                return sessionFactory;
                        }
                }

                private static ISessionFactory createSessionFactory() {
                        return Fluently.Configure()
                                .Database(MsSqlConfiguration.MsSql2008.ShowSql()
                                .ConnectionString(c => 
c.FromConnectionStringWithKey("TestDB")))
                                .Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<OrderHeaderMap>())
                                .BuildSessionFactory();
                }
        }

And a NH repository class is also created

    public class NHibernateRepository<T, TId> {
                protected ISession session = null;
                protected ITransaction transaction = null;

                public NHibernateRepository() {
                        this.session =
NHibernateSessionProvider.SessionFactory.OpenSession();
                }

                public void Save(T entity) {
                        session.SaveOrUpdate(entity);
                }

                public void AddNew(T entity) {
                        session.Save(entity);
                }

                public void BeginTransaction() {
                        transaction = session.BeginTransaction();
                }

                public void CommitTransaction() {
                        transaction.Commit();
                        closeTransaction();
                }

                public void RollbackTransaction() {
                        transaction.Rollback();
                        closeTransaction();
                        closeSession();
                }

                private void closeTransaction() {
                        transaction.Dispose();
                        transaction = null;
                }

                private void closeSession() {
                        session.Close();
                        session.Dispose();
                        session = null;
                }

                public void Dispose() {
                        if (transaction != null) {
                                CommitTransaction();
                        }

                        if (session != null) {
                                session.Flush();
                                closeSession();
                        }
                }
        }

In my code, I have created 2 different ways to save this master/detail
structure with composite-id.

                        private static void method1() {
                        NHibernateRepository<OrderHeader, int?> repo = new
NHibernateRepository<OrderHeader, int?>();
                        OrderHeader oh = new OrderHeader();
                        oh.Comment = "Test Comment " + DateTime.Now.ToString();
                        oh.Details = new List<OrderDetail>();
                        for (int i = 0; i < 2; i++) {
                                OrderDetail od = new OrderDetail
                                {
                                        OrderHeader = oh,
                                        Product = new Product
                                        {
                                                Id = i + 3
                                        }
                                };

                                oh.Details.Add(od);
                        }

                        repo.Save(oh);
                }

                private static void method2() {
                        NHibernateRepository<OrderHeader, int?> repoHeader = new
NHibernateRepository<OrderHeader, int?>();
                        OrderHeader oh = new OrderHeader();
                        oh.Comment = "Test Comment " + DateTime.Now.ToString();
                        repoHeader.Save(oh);

                        NHibernateRepository<OrderDetail, int?> repoDetail = new
NHibernateRepository<OrderDetail, int?>();
                        for (int i = 0; i < 2; i++) {
                                OrderDetail od = new OrderDetail
                                {
                                        OrderHeaderId = oh.Id,
                                        OrderHeader = oh,
                                        ProductId = i + 3,
                                        Product = new Product
                                        {
                                                Id = i + 3
                                        },
                                };

                                repoDetail.AddNew(od);
                        }
                }

But for both methods, the OrderDetail table is never saved. I have
turned on ShowSql() to see SQL statement executed on console, no SQL
generated to save OrderDetail table at all.

I did quite a lot of search everywhere and could not have a clear
conclusion what is wrong.

Anybody has some clue, what exactly do I need to do to save an entity
with composite-id?

Thanks

Hardy

-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en.

Reply via email to