NHibernate 3.2 Mapping by Code – Enforce Referential Integrity

28 Sep 2011 by

In the previous post, I show an example of a simple parent/child mapping by code in NHibernate 3.2. In this article, I will show how to enforce referential integrity in way the that deleting a parent record will yield to child record deletion as well.

The data model is exactly the same as previous post. The different is mapping technique.

ProvinceMap.cs

  public class ProvinceMap : ClassMapping
  {
    public ProvinceMap()
    {
      Id(p=>p.Id, map=>map.Generator(Generators.Assigned));
      Property(p => p.Code, map =>
                              {
                                map.Length(3);
                                map.NotNullable(true);
                              });
      Property(p=>p.Name);

      Bag(p => p.Districts, map =>
                              {
                                map.Key(k =>
                                          {
                                            k.Column("ProvinceId");
                                            k.OnDelete(OnDeleteAction.Cascade);
                                          });
                                map.Cascade(Cascade.All);
                                map.Inverse(true);
                              }, ce => ce.OneToMany());
    }
  }

DistrictMap.cs

  public class DistrictMap : ClassMapping
  {
    public DistrictMap()
    {
      Id(p=>p.Id, map=>map.Generator(Generators.Assigned));
      Property(p=>p.Name);
      ManyToOne(p=>p.Province, map=>map.Column("ProvinceId"));
    }
  }

NUnit Test

    [Test]
    public void Referential_integrity_should_work()
    {
      var province = new Province() {Id = 1, Code = "BMC", Name = "Banteay Meanchey"};
      var districtA = new District() {Id = 101, Name = "AA", Province = province};
      var districtB = new District() {Id = 102, Name = "BB", Province = province};

      province.Districts.Add(districtA);
      province.Districts.Add(districtB);

      using(var tx=NhSession.BeginTransaction())
      {
        NhSession.Save(province);
        tx.Commit();
      }

      var provinceBMC = NhSession.Get(province.Id);
      Assert.AreEqual("BMC", provinceBMC.Code);
      Assert.AreEqual(2, provinceBMC.Districts.Count);

      using(var tx = NhSession.BeginTransaction())
      {
        NhSession.Delete(provinceBMC);
        tx.Commit();
      }

      var queryDistrictA = NhSession.Get(districtA.Id);
      Assert.IsNull(queryDistrictA);
    }

 

5 responses so far

  • Hi,

    Doing this way, the cascading delete action is in the database.

    How do I get Nhibernate do the delete instead of database?

  • NHibernate is just an abstract layer over pure SQL statement. So I don’t thing there is a configuration in NHibernate to perform cascade delete rather than enforce integrity in the database.

    Moreover, it’s advisable to consider constraint and integrity in the database level rather than programming level.

  • Diogo Menezes says:

    Hi, i think it is possible because if i dont set cascade in nhibernate and neather in database, nhibernate fires 2  sqls.

    Update child set parentId = null where parentId = ‘x’

    Delete from parent where parentId = ‘x’

    I only want change updqte to delete.

    Idea?

  • Diogo Menezes says:

    I prefer the programing level because i put the nhibenate query log in a file and ists important to me.

  • Anyway, still 2 SQL require (Update and then Delete). Otherwise, I think no choice.

Leave a Reply