Reputation: 17506
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:
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.
Upvotes: 2
Views: 2050
Reputation: 123901
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:
- 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:
- 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:
- 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)
Upvotes: 2