Blog Stats
  • Posts - 18
  • Articles - 0
  • Comments - 14
  • Trackbacks - 82

 

NHibernate Best Practices with ASP.NET, Generics & Unit Tests

I finally got around to it... the whole shebang of NHibernate best practices with ASP.NET and Generics.  The article, along with the related source, can be found at http://www.codeproject.com/useritems/NHibernateBestPractices.asp.  Your review, feedback and suggestions would be much appreciated!


3/3/06 UPDATE

I've updated the article on Code Project to include a unit testing project to show how to simulate the web context and how to create “mock” DAO objects within your unit tests.


Feedback

# re: NHibernate Best Practices with ASP.NET and Generics

Gravatar Great article. Not sure I'll introduce generics into my projects until nHibernate has native support for it though. Also, I'd like to see this example extended through the use of reflection and configuration rather than use inline concrete DAO implementations. Strangely enough, hibernate says "If we use public static nested classes, we can centralize all of them (dao implementations) in one source file." This just doesn't feel right... 3/13/2006 9:52 AM | Jon

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar I don't blame you for waiting; albeit, the sample project I put together will almost seamlessly port once NHibernate supports Generics natively. (I should say "should" instead of "will"...we'll see.)

I like your reflection/configuration idea...if you wanted to extend any of the DAOs, you could then implement a partial class to add methods that are too specialized to be part of the generic DAO. Do you have any suggestions for implementing your idea? Thanks!

3/13/2006 6:13 PM | Billy

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar Billy - I have an abstract factory pattern I use to instantiate my DAO - I use "Repository" instead of "DAO". The code has not been updated yet to extend .NET 2.0 features like generics and partial classes. Ihe .NET 1.1 code uses configuration to load the assemblies. All objects have to be created from the abstract factory. If you are interested, I can email it. Hit me up at cis_jcean@msn.com.nospam 3/14/2006 5:00 AM | Jon

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar Great articl, Billy.
Just wondering if it is a good idea to have another layer between DAOs and ASP.NET Pages, which will talk to DAOs and Domain objects, so that ASP.NET pages can talk to this layer and doesn't have to access DAOs directly?
4/9/2006 10:37 PM | Chris

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar Hi Billy... great article!

I'm just getting in to code OO practices and I've found the article excellent in showing the benefits of "code to an interface".

However, I've noticed that your concrete dao classes(e.g. CustomerDaoNHibernate) implement the IGenericDao interface twice, once via GenericNHibernateDao<Customer, string> and secondly via ICustomerDao. Is this good practice to do this?

Please do not take this as a criticism in any way as I said I'm just trying to learn what is good OO design practice. 5/30/2006 4:02 AM | Gary

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar You could use GenericNHibernateDao without having it implement IGenericDao, but having both GenericNHibernateDao and ICustomerDao implement this interface emphasizes the "contractual relationship" between these classes. So if you modify the signature of IGenericDao, you'll be forced to modify GenericNHibernateDao so that it'll remain in a consistent relationship with ICustomerDao.

Billy 5/30/2006 6:19 AM | Billy

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar Hi Billy, thanks again for your contribution here. I have a question about your HttpModule, especially in regard to second-level caching. When I pull in objects during a session (attached to the HttpRequest via your module), those objects are written back to the Db at the close of every session regardless of whether I SaveOrUpdate the entity. Is that correct behaviour with your module? I want to implement second-level caching and often my use case is to hold off persisting changes until the user approves them...but the HttpModule I use from your example seems to persist them regardless of SaveOrUpdate. What am I missing?

Thanks in advance 6/13/2006 5:29 PM | MIKE

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar That's correct behavior that you're seeing. Whatever items that are retrieved from the DB within an NHibernate session are all saved back to the DB, if there are any changes, when the session's transaction gets committed. As you mentioned, there are times when you'd want to make a change to an object without persisting it back to the DB immediately. An example would be a wizard in which you don't want anything committed until after the last step. What you can do is "Evict" the object(s) that you don't want committed back to the DB when the transaction gets committed. The code to be used is "session.Evict(objectToEvict)." Evict disassociates an object with the session. When you're ready to commit the object that's been evicted, simply call "session.SaveOrUpdate(objectToBeCommitted)."

Billy 6/13/2006 7:40 PM | Billy

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar I've gotten some great mileage out of this post, with some minor modifications to fit my application.

I'd like to make one small improvement, but I can't seem to find a way.

I'd like to hide the IdT from the the declaration of IGenericDao, since the IdT could (theoretically) be determined by T's IdT.

Clearly, my proposed implementation doesn't work.

Any suggestions?

<code>
public interface IDomainObject
{
Type IdType();
}

public abstract class DomainObject<IdT> : IDomainObject
{
// same as before ...

public Type IdType()
{
return typeof(IdT);
}
}

public interface IGenericDao<T> where T : IDomainObject
{
T GetByID(T.IdType() id);
}
</code> 12/27/2006 5:23 PM | Rick

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar That is certainly food-for-thought because if you could simplify this then you could reduce some duplicated ID-data-type declarations. I'm going to give this a try and post another comment if I find a solution...thanks for the idea! 1/3/2007 2:22 PM | Billy

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar After looking at it a bit further, the only solution I can think of is to use reflection to get the object's "ID" property and then to examine what type that property is. The major drawback to this is that then the data layer becomes tied to how the domain model is defined and becomes a bit more fragile. Assume someone changes "ID" to "PersistentID" in the domain object class. The data layer would then have to be altered to adjust to this new naming convention and would not be as reusable. I like the idea of inferring the type of the ID, but I like even more the idea of keeping the data layer completely independent from making assumptions about the domain layer. Let me know your thoughts on this or if you come up with a better solution. 1/3/2007 2:28 PM | Billy

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar The way you could do this is to put the abstract DomainObject (or PersistentObject) base class into the data layer as well. In this way, it wouldn't be problematic having other classes within the data layer making assumptions about this base class. Having the base object anywhere other than the data layer would be a problem as you described. 11/15/2007 10:37 AM | Billy McCafferty

# re: NHibernate Best Practices with ASP.NET, Generics & Unit Tests

Gravatar Hi, I just wanted to look at ur article "http://www.codeproject.com/useritems/NHibernateBestPractices.aspx"

but page is not found . 6/8/2008 4:26 AM | Hi , Page Not found

Post a comment





 

Please add 2 and 4 and type the answer here:

 

 

Copyright © Billy McCafferty