Browse by Tags

All Tags » nHibernate (RSS)

ActiveRecord: Loading Records by Primary Key

I was reviewing some code today for a project that uses ActiveRecord .  One of the things that stood out for me was the use of a query to find objects by their primary key.  There's two reasons this raised a red flag for me: ActiveRecord already contains a built-in method for locating objects by their primary key: Find(). Ayende just made a post about a month ago about why you shouldn't use queries to find objects by their primary key in NHibernate (which ActiveRecord uses under the hood).  You loose some optimizations that are built-in to NHibernate.  Read Ayende's post for more details. So if you're an ActiveRecord user, how can you control which Session method to use – Get() or Load()?  Easy: ActiveRecordBase.Find() uses Session.Load to load objects by primary key. ActiveRecordBase.TryFind() uses Session.Get to load objects by primary key. And if you're ever wondering how ActiveRecord works under the hood (or how some NHibernate concepts are used), grab the source and look around! Technorati Tags: .NET , ActiveRecord , Nhibernate

NHibernate Queries: HQL vs. Criteria API

As someone who did a lot of SQL a few years ago, I was immediately more comfortable using HQL for my ActiveRecord queries than the Criteria API.  But from a documentation/samples standpoint, I see a much higher percentage of the Criteria API being used vs. HQL.  I still use HQL most of the time. This morning, Ayende had a post that answered the question I've always wondered: Which should I use? Technorati Tags: .NET , ActiveRecord , HQL , nHibernate

OutputDebugStringAppender in a web app?

I spent a couple of hours yesterday trying to get log4net to log to an OutputDebugStringAppender with no success.  At first, I thought I had a configuration error in log4net so I added a file appender and that works fine.  It's a Monorail application that uses ActiveRecord for database access.  There's a couple of spots where I wanted to check out the SQL being generated by ActiveRecord (NHibernate).  I did all my set up for log4net and even got it logging to a FileAppender.  But I wanted to log the SQL to an OutputDebugStringAppender. Here's my logging set up: 1: < log4net > 2: <!-- Define some output appenders --> 3: < appender name ="logfile" type ="log4net.Appender.FileAppender, log4net" > 4: < file value ="log-file.txt" /> 5: < appendToFile value ="true" /> 6: < layout type ="log4net.Layout.PatternLayout" > 7: < conversionPattern value ="%d [%t] %-5p %c - %m%n" /> 8: </ layout > 9: </ appender > 10: < appender name ="ods" type ="log4net.Appender.OutputDebugStringAppender, log4net" > 11: < layout type ="log4net.Layout.PatternLayout,log4net" > 12: < conversionPattern value ="%d [%t] %-5p %c - %m%n" /> 13: </ layout > 14: </ appender > 15: < logger name ="NHibernate.SQL" > 16: < level value ="ALL" /> 17: < appender-ref ref ="logfile" /> 18: < appender-ref ref ="ods" /> 19: </ logger > 20: < root > 21: <!-- priority value can be set to ALL|INFO|WARN|ERROR --> 22: < priority value ="ALL" /> 23: < appender-ref ref ="ods" /> 24: </ root > 25: </ log4net > The log-file.txt gets all the logging I want, but I really just wanted to be able to view these statements in DebugView (gives me a bit more control in clearing out past queries, setting filters/highlight colors, etc…) I'm positive I had something like this working before but I get NOTHING in DebugView.  Anyone have any ideas as to what I'm doing wrong?  Is there a permission issue that makes this not possible? Technorati Tags: Log4Net , MonoRail , ActiveRecord , NHibernate

ActiveRecord and a Custom NHibernate PrimitiveType

I was intrigued by Steve Smith 's blog post yesterday about reducing SQL Lookup tables in nHibernate . He gave an example of a WorkOrderStatus class the exposed the actual status as a POCO object that wasn't stored in the database. What really piqued my interest was the following comment: NHibernate can map this status directly if you create a WorkOrderStatusType class that inherits from NHibernate.Type.PrimitiveType and overrides its methods. I never knew nHibernate supported this type of feature (never needed it or thought about it). As I'm an avid ActiveRecord user, I decided to see how I would implement a custom nHibernate PrimitiveType and utilize it via ActiveRecord. Turns out it was pretty easy! The full source is available from my GoogleCode page either through SVN or simply a ZIP download. A quick note before we begin: I didn't find a whole lot of documentation on extending PrimitiveType and implementing your own. I reviewed some nHibernate code and I think I got the general implementation right, but can't be sure it'll work 100% of the time. It was a proof-of-concept project. ActiveRecord Setup I decided I'd use SQLite for this sample since it's perfect for this type of job -- small, compact and no install required. I can poke around the database to check schema and data using the SQLite addon for Firefox . Instead of stealing Steve's WorkOrderStatus, I decided to go with a schema that has a simple Company object, and that Company object has a CompanyType defined. Instead of defining a lookup table just for company types, I'll create a CompanyType class that derives from NHibernate.Type.PrimitiveType and let nHibernate do the loading/saving. First, the CompanyType. For this demo, it's a simple object with a Description (string) and a Value (integer). The Value is what is actually saved to the database (note: this isn't the entire class -- just the basics): public class CompanyType : NHibernate.Type.PrimitiveType { public static readonly CompanyType Software = new CompanyType() { Description = "Software" , Value = 1 }; public static readonly CompanyType Manufacturing = new CompanyType() { Description = "Manufacturing" , Value = 2 }; public static readonly CompanyType Insurance = new CompanyType() { Description = "Insurance" , Value = 3 }; private static readonly CompanyType[] AllTypes = new CompanyType[] { Software, Manufacturing, Insurance }; public string Description { get; set; } public int Value { get; set; } public override string ToString() { return this .Description; } public CompanyType() : base (SqlTypeFactory.Int32) { } } I've defined an AllTypes[] that I'll use to find the matching CompanyType when nHibernate reads the integer from the database. The ctor calls the base class ctor and tells nHibernate what data type this new PrimitiveType is based on (the schema in the database will be an integer). I also overrode ToString() to return the Description property to make debugging easier. The Company record is pretty simple too. When we get to the CompanyType, we tell ActiveRecord (which works through nHibernate) the column type for the column (our custom PrimitiveType): [ActiveRecord] public class Company : ActiveRecordBase<Company> { [PrimaryKey(Generator = PrimaryKeyType.Identity)] public int Id { get; set; } [Property] public string Name { get; set; } [Property] public DateTime InceptionDate { get; set; } [Property(ColumnType = "ARPrimitiveType.Model.CompanyType, ARPrimitiveType" )] public CompanyType CompanyType { get; set; } public override string ToString() { return this .Name; } } Implementing the required methods in CompanyType was pretty easy. I'm not sure when DefaultValue is used, so I just return a CompanyType of Software: public override object DefaultValue { get { return CompanyType.Software; } } ObjectToSQLString seems to want to convert your PrimitiveType (CompanyType) to a string value that can be used by the database. So we'll convert our Value property to a string: public override string ObjectToSQLString( object value , NHibernate.Dialect.Dialect dialect) { CompanyType type = value as CompanyType; return type.Value.ToString(); } The PrimitiveType class indicated the actual type of data stored in the database (a 32-bit integer for our CompanyType): public override Type PrimitiveClass { get { return typeof (Int32); } } The FromStringValue and two Get overloads both need to do the same thing: Take a representation of the database value and convert it to our PrimitiveType (a CompanyType). For this I created a single method that converts the database integer back to a CompanyType instance using a LINQ query on the AllTypes array: public override object FromStringValue( string xml) { return GetCompanyType(xml); } public override object Get(System.Data.IDataReader rs, string name) { return GetCompanyType(rs[name]); } public override object Get(System.Data.IDataReader rs,...