Development With A Dot

Blog on development in general, and specifically on .NET

Sponsors

News

My Friends

My Links

Permanent Posts

Portuguese Communities

Soft Deletes With NHibernate, Part II

After my previous post, Adam Bar suggested that setting an SQL Delete command might be a better idea, I actually agree with him, so I decided to post an alternative solution.

For those not familiar with the concept, NHibernate lets us specify SQL commands for all of the basic CRUD operations: loading, inserting, updating and deleting. The SQL can even be a stored procedure call. In this case, it’s the deleting that we’re after, and it is quite easy to configure:

   1: public class RecordMapping : ClassMapping<Record>
   2: {
   3:     public RecordMapping()
   4:     {
   5:         this.Table("record");
   6:         this.Lazy(true);
   7:         this.Where("deleted = 0");
   8:         this.SqlDelete("UPDATE record SET deleted = 0 WHERE record_id = ?");
   9:  
  10:         this.Id(x => x.RecordId, x =>
  11:         {
  12:             x.Column("record_id");
  13:             x.Generator(Generators.HighLow);
  14:         });
  15:  
  16:         this.Version(x => x.UpdatedAt, x =>
  17:         {
  18:             x.Column(y =>
  19:             {
  20:                 y.NotNullable(true);
  21:                 y.Name("updated_at");
  22:             });
  23:             x.Generated(VersionGeneration.Never);
  24:             x.Type(NHibernateUtil.UtcDateTime as IVersionType);
  25:         });
  26:         
  27:         this.Property(x => x.CreatedAt, x =>
  28:         {
  29:             x.Column("created_at");
  30:             x.NotNullable(true);
  31:             x.Update(false);
  32:             x.Insert(true);
  33:         });
  34:  
  35:         this.Property(x => x.CreatedBy, x =>
  36:         {
  37:             x.Column("created_by");
  38:             x.NotNullable(true);
  39:             x.Update(false);
  40:             x.Insert(true);
  41:         });
  42:  
  43:         this.Property(x => x.UpdatedBy, x =>
  44:         {
  45:             x.Column("updated_by");
  46:             x.NotNullable(true);
  47:         });
  48:  
  49:         this.Property(x => x.Name, x =>
  50:         {
  51:             x.Column("name");
  52:             x.Length(50);
  53:             x.NotNullable(true);
  54:         });
  55:  
  56:         this.Property(x => x.Deleted, x =>
  57:         {
  58:             x.Column("deleted");
  59:             x.NotNullable(true);
  60:         });
  61:  
  62:         this.ManyToOne(x => x.Parent, x =>
  63:         {
  64:             x.Column("parent_record_id");
  65:             x.NotNullable(false);
  66:             x.Lazy(LazyRelation.NoProxy);
  67:             x.Cascade(Cascade.All);
  68:         });
  69:  
  70:         this.Bag(x => x.Children, x =>
  71:         {
  72:             x.Inverse(true);
  73:             x.Cascade(Cascade.All | Cascade.DeleteOrphans);
  74:             x.SqlDelete("UPDATE record SET deleted = 1 WHERE record_id = ?");
  75:             x.Where("deleted = 0");
  76:             x.Key(y =>
  77:             {
  78:                 y.Column("parent_record_id");
  79:                 y.NotNullable(false);
  80:             });
  81:         }, x =>
  82:         {
  83:             x.OneToMany();
  84:         });
  85:     }
  86: }

Notice the two calls to SqlDelete, one for the class itself, and the other for the Children collection. The former takes care of soft deleting the record itself, and the later, it’s children.

It is a more contained and straightforward solution, no need for registering listeners.

Comments

No Comments