views:

33

answers:

2

I try to map NHibernate to an existing database structure. Unfortunately I can not change the existing structure.

First I'll give some background and then explain the problem itself

Relational analysis is quite simple: alt text

Log is the main Entity. he has one-to-one relationship with Form. the foreign key is FormID.

Buyer & Seller are collection of the form entity. The application should save the form entity together with the buyers and the sellers.

The problem is the primary key consisting of the Buyer & Seller entity. The key composite from ForegineKey- FormID and an intenal ordering int number- tdNum

This is reflected in the following form FNH mapping

public class FormLogMap : ClassMap<FormLog>
{
    public FormLogMap()
    {
        Table("BillOfSaleLog");

        Id(x => x.FormId).Column("FormID").GeneratedBy.Native();
        ....
        ....
        References<Form>(x => x.Form, "FormID").LazyLoad().ReadOnly();
    }
}

public class FormMap : ClassMap<Form>
{
    public FormMap()
    {

    Table("BillOfSaleForm");

        Id(x => x.Id).Column("FormID").GeneratedBy.Foreign("Log");
        ...
        ...

        HasOne<FormLog>(x => x.Log).Cascade.All();

        HasMany(x => x.Buyers).KeyColumn("FormID").Inverse().Cascade.All();

        HasMany(x => x.Sellers).KeyColumn("FormID").Inverse().Cascade.All();
    }
}


public class BuyerMap : ClassMap<Buyer>
{
    public BuyerMap()
    {

        Table("BillOfSaleBuyer");

        CompositeId()
                    .KeyReference(x => x.Form, "FormID")
                    .KeyProperty(x => x.InnerOrderId, "tdNum1");

         ....
         ....
    }
}

Seller is exectly the same

The problem occurs when I try to save the entity by the Edit Action I'm using MVC to get the user data and make it an object. The binding works fine and makes the object along with the collections.

But when I save an entity receive the following error: alt text

I expect NHibernate be smart enough to set the Buyer & Seller foreign keys. But in fact they remain without value.

The problem can be solved by setting foreign keys manually as the following code:

        //i have to set the form proerty in the childs
        //without of the lines NH will try to save the childs it with FormID = null
        foreach (var buyer in form.Buyers) { buyer.Form = form; }
        foreach (var seller in form.Sellers) { seller.Form = form; }

But I'm looking for an elegant and correct solution

Thank you for reading

A: 

According to this related question, HHibernate does not support cascade working with a composite key (as you have in BuyerMap). One of the answers does contain a hack to workaround this, but you will end up with a redundant column.

Cocowalla
@Cocowalla Thank you for the replay. I understand the suggested solution but it requires a change in tabular schem.I'll take my proposed solution above.It is understandable that the ability to map clumsy relational structure is problematic
ari
+1  A: 

You don't show the code for adding a Buyer or Seller to a Form but it should look like this:

form.Buyers.Add(buyer);
buyer.Form = form;

Because Form is the inverse side of the relationships, you have to set the reference to Form on the many side. You should do this anyway so that the in-memory objects are correct. If the Buyer and Seller objects are already persistent in the same ISession than that should work.

Jamie Ide
I mentioned above that the form object I get through databinding from an edit view. I do not create the form object instance by code that referance between the objects its little problem. Another option is in addition to information of the seller / buyer in the view also include the foreign key of the form parent. It's simple to get around the problem. Too bad ..
ari