0
votes

I have problems understanding proper mapping (mapping by code) for updating my data. Here it is (simplified for the sake of clarity).

  • [Persons] table is just a dictionary and is immutable.
  • [Objects] can be:
    • created,
    • modified with [persons]:
      1. added to object or
      2. removed from object or
      3. only modified metadata (status and dates).

I can't figured it out how to properly map my classes. No matter what kind of cascade I set I can't get nhibernate to: - NOT modify person records, - properly delete or modify records from objectperson table - it mostly just try to add new ones. I suspect my mappings are completely wrong but cant figure it out.

I also tried to make composite key for objectperson table (makes more sense) but found out it is for some reason discouraged in nhibernate. That's why I added separate autoid column.

I managed to make selecting records work (sample below) but SaveOrUpdate never works as expected... where I gone wrong?

My classes:

t_object
{
    public virtual int ID { get; set; }
    public virtual string Number { get; set; }
    public virtual IEnumerable<t_objectperson> Persons { get; set; }
}
t_person
{
    public virtual int ID { get; set; }
    public virtual string Name { get; set; }
    public virtual string Surename { get; set; }
    public virtual IEnumerable<t_objectperson> Objects { get; set; }
}
t_objectperson
{
    public virtual int ID { get; set; }
    public virtual t_object Object { get; set; }
    public virtual t_person Person { get; set; }
    public virtual int Status { get; set; }
    public virtual DateTime Added { get; set; }
    public virtual DateTime? Expired { get; set; }
}

My mappings:

    public t_object_map()
    {
        this.Table("rs_object");

        this.Id(c => c.ID, m =>
        {
            m.Column("Id");
            m.Generator(Generators.Identity);
        });
        this.Property(c => c.Number);
        Set(x => x.Persons 
            , c => {
                c.Key(k => k.Column("IdObject"));
                c.Cascade(Cascade.All);
            }
            , map => map.OneToMany(p => p.Class(typeof(t_objectperson)))                   
        );
    }

    public t_objectperson_map()
    {
        this.Table("rs_objectperson");
        this.Id(c => c.ID, m =>
        {
            m.Column("Id");
            m.Generator(Generators.Identity);
        });
        this.Property(c => c.ID);
        this.ManyToOne(p => p.Object, m =>
        {
            m.Column("IdObject");
            m.Cascade(Cascade.All);
            //m.NotNullable(true);
            m.Unique(false);
        });
        this.ManyToOne(p => p.Person, m =>
        {
            m.Column("IdPerson");
            //m.Cascade(Cascade.All);
            //m.NotNullable(true);
            m.Unique(false);
        });
    }
    public t_person_map()
    {
        this.Table("rs_person");
        this.Id(c => c.ID, m =>
        {
            m.Column("Id");
            m.Generator(Generators.Identity);
        });   
        this.Property(c => c.Name);
        this.Property(c => c.Surename);     
    }

How I get data:

var query = session
                  .QueryOver<t_object>()
                  .Where(c => c.ID == ID)
                  .Fetch(c => c.Persons).Eager
                  .Fetch(x => x.Persons.First().Object).Eager
                  .OrderBy(c => c.Number).Asc
                  .List<t_object>();
1

1 Answers

0
votes

Are you missing the collection mapping on t_person_map?

You need to set Inverse(true) Set collection.

Here's a quick explanation of when to set inverse:

one-to-many -> many-to-one

right side should be active (left with inverse="true"), to save on UPDATEs (unless left side is explicitly ordered)

i.e. one side has to take control of relationship and you need to be consistent in the way you do this.

from: http://notherdev.blogspot.com/2012/04/nhibernates-inverse-what-does-it-really.html