简体   繁体   中英

Nhibernate class mapping and cascade property

We have an Address entity, which has a foreign key that references a City table. An Address only references one City , but a City should be able to be referenced by many Address es.

public class Address : Entity
{
    public virtual string AddressLine1 { get; set; }

    public virtual string AddressLine2 { get; set; }

    public virtual City City { get; set; }
}

public class City : Entity
{       
    public virtual string CityName { get; set; }
}

This is the Address class mapping.

public class AddressClassMapping : ClassMapping<Address>
{
    public AddressClassMapping()
    {
        this.Schema("dbo");
        this.Table("addresses");
        this.Cache(e => e.Usage(CacheUsage.ReadWrite));
        this.Id(e => e.Id, 
                m => { m.Column("id_address"); m.Generator(Generators.Native);});
        this.Property(e => e.AddressLine1, 
                      m => { m.Column("address_line_1"); m.NotNullable(true); });
        this.Property(e => e.AddressLine2, 
                      m => { .Column("address_line_2"); 
                      m.NotNullable(true); });
        this.ManyToOne(
            e => e.City,
            m =>
            {
                m.Column("id_city");
                m.Cascade(Cascade.All);
            });
    }
}

How should I change the class mappings so that:

  1. When I delete a City, all the Addresses with that City are deleted?
  2. When I delete an Address, the City is NOT touched?
  3. I can update an Address's City property by updating the foreign key?

So far, I have played with the Cascade property and have faced issues in which an update to an address's city caused updates to the City table, or I couldn't delete an address without violating a foreign key constraint.

The many-to-one part, shown above (and discussed also here NHibernate Many-to-one cascade ) could be set to these values

// xml
cascade="all|none|save-update|delete" 
// maping by code
Cascade.All | Cascade.None | Cascade.Persist | Cascade.Remove
// fluent 
Cascade.All() | Cascade.SaveUpdate() | Cascade.None() | Cascade.Delete() 

(read more here Mapping-by-Code - ManyToOne )

This will cover point number... well none of the above. Becuase none of the requirements is asking for cascading from Address to city.

The point 3:

  1. I can update an Address's City property by updating the foreign key?

is not about cascading. This is standard behviour, working even without cascading, because it changes the value in the Address table. Not touching the City at all.

To cover the point 2:

  1. When I delete an Address, the City is NOT touched?

Well, we should remove cascading at all, because ... it is not needed in this direction. But, this setting will fit to point 2

this.ManyToOne(
    e => e.City,
    m =>
    {
        m.Column("id_city");
        m.Cascade(Cascade.Persist);

To cover first point:

  1. When I delete a City, all the Addresses with that City are deleted?

we have to do a lot. We need to extend the POCO relations and introduce the one-to-many mapping. That will do what needed:

public class City : Entity
{       
    public virtual IList<Address> Addresses { get; set; }
}

mapping

mapping by code:

Set(x => x.Addresses, c =>
{
   ...
   c.Cascade(Cascade.All.Include(Cascade.DeleteOrphans));

fluent version

HasMany(x => x.Addresses)
    ...
    Cascade.AllDeleteOrphan();

(read more here Mapping-by-Code - Set and Bag )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM