If all I get from my ORM is to save me from the need to maintain stored procedures then that is good enough for me.
However there's much more in that an ORM allows us be free of the hostage-like grip database schemas impose on the design of our code. Things are much simpler when I can model my code exactly like the real world, and I can still do this with a (good) ORM which helps (and hides) the mapping of a potential unsightly legacy db with terrible naming conventions into a structure that means something and not care about redundant code like this everywhere:
using (SqlWrapper sql = SqlWrapper.Create(WrapperConnectionType.ShopNet, "sStore_InsertUpdate_v4"))
{
sql.AddParameter("StoreId", StoreId);
sql.AddParameter("StoreName", StoreName);
sql.AddParameter("Region", Region);
sql.AddParameter("PostCode", PostCode);
sql.AddParameter("Tel", Tel);
sql.AddParameter("Email", Email);
sql.AddParameter("RegionId", RegionId);
sql.AddParameter("MapImage", MapImage);
sql.AddParameter("ShopImage", ShopImage);
sql.AddParameter("Visible", Visible ? 'Y' : 'N');
sql.AddParameter("TazEnabled", TasEnabled ? 'Y' : 'N');
sql.AddParameter("Latitude", Latitude);
sql.AddParameter("Longitude", Longitude);
sql.AddParameter("StoreOpeningDate", OpeningDate);
sql.AddParameter("CustomerNo", CustomerNo);
sql.AddParameter("ReserveAtStoreEnabled", RasEnabled);
sql.AddParameter("OpeningHoursId", OpeningHours.Id);
sql.AddParameter("AddressLine1", AddressLine1);
sql.AddParameter("AddressLine2", AddressLine2);
sql.AddParameter("City", City);
sql.AddParameter("District", District);
sql.AddParameter("County", County);
sql.AddParameter("CountryCode", CountryCode);
sql.AddParameter("GoogleCategories", GoogleCategories);
sql.AddParameter("GooglePlacesEnabled", GooglePlacesEnabled);
sql.AddParameter("ManagerName", ManagerName);
sql.AddParameter("MapZoomLevel", MapZoomLevel);
sql.AddParameter("IpAddress", IpAddress);
sql.AddParameter("FlibbleEnabled", FlibbleEnabled);
sql.AddParameter("RegionalManager", RegionalManagerId);
sql.AddParameter("ShutlLogin", ShutlLogin);
sql.AddParameter("ShutlPassword", ShutlPassword);
sql.Execute();
}
and lets eradicate (but not forget) these type of battles:
System.IndexOutOfRangeException
at System.Data.SqlClient.SqlDataReader.GetOrdinal(String name)
The argument for me doesn't have to be any more complicated than that, I get a couple of nice things and something awful is taken away. Nuff said, Next!
No one is arguing that an ORM is a 100% replacement for everything traditional. It won't be a great tool for writing complex reports, for that use SPs and views, and use NHibernate to call them natively and map them automatically to your c# entities. Great, still all the power of SQL and no crappy mapping code.
Be gone into the darkness ye storer of 0s & 1s and come hither ye light of wholesome c# weltanschauung.