views:

76

answers:

2

In my application I have a situation where we need to capture the when a record was created and modified and what user performed those actions. So I might have an object something like:

public class Product
{ 
  int Id;
  int Name;
  DateTime CreatedOn;
  int CreatedByUserId;
  DateTime LastModifiedOn;
  int LastModifiedByUserId;
}

What's the best practice for handling these in NHibernate? Via using an interceptor something like what's described here?

+1  A: 

I don't think there's a "best" practice, but the use of event listeners is more common for this. There's a good example at http://ayende.com/Blog/archive/2009/04/29/nhibernate-ipreupdateeventlistener-amp-ipreinserteventlistener.aspx

One thing you'll need to consider is that you need to store that userId somewhere. I'm currently doing that by assigning a static property on the listener on startup. It's not pretty, but it gets the job done.

Diego Mijelshon
Somehow I figured that would be the answer :) I guess I wasn't really looking for "best" but "recommended"
Mark Boltuc
A: 

I agree with Diego that I don't think there's a best practice. It depends on your application context. In Diego's link, and to use event listeners at the persistence (nHibernate) level, it needs to know how to lookup the current user. This may not make sense depending on your application. For example, if you're writing an ASP.NET MVC app, do you really want your persistence layer to depend on HttpContext to know the user? Yes, you could pass in some type of strategy, but this doesn't seem like it's always going to be the right thing to do.

I think it's perfectly valid to have your service layer construct the object and add the creator itself. Then pass the whole object, with the creator already hydrated, down to nHibernate to persist. The creator would be saved to the database the same way as any other property.

manu08
My app (ASP.NET MVC) is structured using repositories and such so passing the user information is going to be interesting. I definitely don't want the repos to have direct reference to HttpContext so I'm going to need to find a way to pass that information to the repositories elegantly.
Mark Boltuc
You can strategize it; create some kind of ICurrentUserProvider and pass that down from the controller/service layer. ICurrentUserProvier will have a delegate pointing to a method that uses HttpContext to resolve the current user. That said, this is still a violation of DIP and should be avoided if possible.
manu08
I use IoC to inject the user where needed, something like this in autofac: builder.Register(c => HttpContext.Current.User).HttpRequestScoped();
UpTheCreek