views:

168

answers:

1

Say I want to create a class called EntityWithCreatedAt:

class Entity<T> : ActiveRecordBase<T>
{
  [PrimaryKey]
  public int Id { get; set; }
}

class EntityWithCreatedAt<T> : Entity<T>
{
  [Property]
  public DateTime CreatedAt { get; set; }
}

What is the best way to populate the CreatedAt field? Do I just do it in EntityWithCreatedAt's constructors, or is there some other way?

What about an UpdatedAt property?

Thanks,

+2  A: 

In Rails' implementation of AR, CreatedAt and UpdatedAt are automatic timestamps created in migrations (although you can created them manually, too). Assuming you want the same behaviour, you'll need to override Create and Update.

   public override void Update() 
   {
         UpdatedAt = DateTime.Now;                      
         base.Update(); 
   }

   public override void Create()
   {
         CreatedAt = DateTime.Now;
         base.Create();
   }

If you're not using an assigned primary key, and the DB is generating it for you (with auto increment, for example), then you may be using the Save method to decide whether to call Create or Update. Using Save will still work perfectly for you, as a call to the base class' Save() method will trigger a call to your Create (if the ID hasn't been set) or your Update (if the ID has been set and the record has previously been saved).

The only downside to this method is that your CreatedAt and UpdatedAt properties should always reflect what's saved in the DB, but in your case you're setting the properties before you know the commit to the DB succeeded. This is unavoidable, but with some try/catch code in your Update override, you should be able to record the previous value and assign it back should anything go wrong:

   public override void Update() 
   {
         DateTime originalUpdatedAt = UpdatedAt;
         try 
         {
            UpdatedAt = DateTime.UtcNow;  // Assuming you're using UTC timestamps (which I'd recommend)                     
            base.Update(); 
         }
         catch  // Don't worry, you're rethrowing so nothing will get swallowed here.
         {
            UpdatedAt = originalUpdatedAt;
            throw;
         }
   }
Matthew Brindley