Thursday, May 7, 2009

eventId's 1334, 1089, and 1000

Today, I encountered a problem where my ASP.NET app would not run on my machine. I would get "Server Unavailable" in my browser, and eventId's 1334, 1089, and 1000 in the Application Event Log. The same application ran smoothly on a fellow developer's machine.

Many Web resources suggest using aspnet_regiis.exe enable ASPNET to access the GAC, but that was not my particular problem.

Instead, we have a legacy Visual Studio 2005 Web Application Project (not to be confused with a "Web Site") with unusual configuration requirements: It has to run in a virtual directory located at the root of the Web site. Something tells me this is redundant.

Anywho, steps to make it work included:
  1. Publish to the desired folder (C:\inetpub\wwwroot for example).
  2. Set both the Web site root and the virtual directory root (in IIS) to that folder.
  3. In VS, on the Web section of the WAP's properties, under Servers, select "Use IIS Web server".
  4. In the project URL, put "http://localhost/MyVirtualDirectory".
I hope this helps someone.

Friday, May 1, 2009

First Project with NHibernate 1: Lessons Learned

The ministry where I work recently completed the first revision of our new Money And Marriage Web site, which we built using several new methodologies and tools, one of which was NHibernate. The team put me, the still-green associate developer, in charge of creating a Data Access Layer (DAL) to house the great ORM beast, taming it if you will. One of the interesting requirements of this DAL was that it should completely protect the app-at-large from all persistence concerns, as well as _not_ expose NHibernate in case we decide to use a different ORM instead. Therefore, the app-at-large would not know of NHibernate, but the person writing the app-at-large would have to refer to the *.hbm.xml (NHibernate mapping) files to understand what MyUnitOfWork.Get(id) would do, precisely.

Because we are still new with NHibe, our code is probably not as useful of a solution as you will find elsewhere; thus I will not misguide the reader with such, but will instead share what we learned:
  • For any database, no matter how "legacy" it is, an ORM tool is far better than no ORM tool, even if you still find yourself hand-coding some methods to custom-massage Buisness Objects between the BL and the ORM.
  • For new or (or perfectly kosher old) databases, you can simply use ISession.Get(id), Set(obj), etc. without customizing anything on a per-type basis. Yes, this simplifies your DAL by an order of magnitude! That is, if you have n types in your BL, the number of methods in your DAL goes from O(n) to O(1).
  • NHibe is rather awkward for working with legacy databases. Be prepared to massage data yourself (unless you simply know more NHibernate tricks than I do and can handle insane / exotic situations).
  • Before committing to NHibernate (or any other complex tool for that matter), hold some tech talks / lectures with all techies involved to not only get everyone on board, but also to brief everyone in how to properly use the tool. There are a few instances in our code base where we did certain things like handling relationships between entities the manual way, using ID's of related entities in our BO's rather than using references to those entities and letting NHibernate work its relationships magic. Most of these instances were my doing in working with a legacy database. More knowledge of NHibernate would have helped.
  • Unless you are an uber-brilliant programmer who can simultaneously keep client code from caring about persistence concerns like transactions while still providing a DAL API allowing client code to express persistence requests at the domain level, you should let the app-at-large control transactions. I see no way around it.
  • You can let the app-at-large be blissfully ignorant of connections, and maybe even caches, except that it should keep track of what objects are and are not attached (persisted).
  • Some ORM-related concerns, such as the fact that you cannot attach two different instances representing the same entity to the same session at the same time, will still percalate up to the client code, unless you invent an ingenius scheme to prevent that.