The reason why I avoided automapping in Fluent NHibernate before is I got the wrong impression that one need to put the models in a separate assembly for him/her to have a hassle-free Fluent NHibernate awesome automapping; though putting the models in separate assembly is a good discipline, there are times you just don't want to create a separate project for models, so this decision naturally led me to always map objects and properties manually (via ClassMap<>, Map(),Id(),etc). Oh well, Entity Framework's minimalist and whitelist approach(via DbSet<>, no need to put the models in a separate project) pumped me up to find the same thing in Fluent NHibernate.
That's a big wrong impression there on part of me. Fluent NHibernate also has a whitelist capability for automapping objects to tables; it also has a mechanism to *blacklist* the properties you specified. There's no whitelist mechanism for properties, if there is, things will not be so auto anymore ;-)
Boilerplate code for automapping in Fluent NHibernate:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using NHibernate; using NHibernate.Dialect; using FluentNHibernate.Cfg; using FluentNHibernate.Cfg.Db; using FluentNHibernate.Automapping; using FluentNHibernate.Conventions; using FluentNHibernate.Conventions.Instances; using FluentNHibernate.Conventions.Helpers; using TestFluentAutomapping.Model; namespace TestFluentAutomapping { public static class Mapper { static ISessionFactory _sf = null; public static ISessionFactory GetSessionFactory() { if (_sf != null) return _sf; var fc = Fluently.Configure() .Database(MsSqlConfiguration.MsSql2008.ConnectionString(@"Data Source=localhost;Initial Catalog=TestDbx;User id=sa;Password=P@$$w0rd")) .Mappings ( m => m.AutoMappings.Add ( AutoMap.AssemblyOf<Program>(new CustomConfiguration()) .Conventions.Add(ForeignKey.EndsWith("Id")) .Override<Band>(n => { n.HasMany(x => x.Fans).Inverse().KeyColumn("FavoriteBandId"); } ) ) // .ExportTo(@"C:\_Misc\NH") ); // Console.WriteLine( "{0}", string.Join( ";\n", fc.BuildConfiguration().GenerateSchemaCreationScript(new MsSql2008Dialect() ) ) ); // Console.ReadLine(); _sf = fc.BuildSessionFactory(); return _sf; } class CustomConfiguration : DefaultAutomappingConfiguration { IList<Type> _objectsToMap = new List<Type>() { // whitelisted objects to map typeof(Person), typeof(Country), typeof(Band) }; public override bool ShouldMap(Type type) { return _objectsToMap.Any(x => x == type); } public override bool IsId(FluentNHibernate.Member member) { return member.Name == member.DeclaringType.Name + "Id"; } } } }
Objects:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestFluentAutomapping.Model { public class Country { public virtual int CountryId { get; set; } public virtual string CountryName { get; set; } public virtual int Population { get; set; } public virtual IList<Person> People { get; set; } } public class Band { public virtual int BandId { get; set; } public virtual string BandName { get; set; } public virtual IList<Person> Fans { get; set; } } public class Person { public virtual int PersonId { get; set; } public virtual string PersonName { get; set; } public virtual Country Country { get; set; } public virtual Band FavoriteBand { get; set; } } }
Using the objects that was mapped by means of automapping:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using NHibernate.Linq; using TestFluentAutomapping.Model; namespace TestFluentAutomapping { class Program { static void Main(string[] args) { var s = Mapper.GetSessionFactory().OpenSession(); foreach (var c in s.Query<Country>()) { Console.WriteLine("\n{0}'s people", c.CountryName); foreach(var p in c.People) Console.WriteLine("* {0}", p.PersonName); } foreach (var b in s.Query<Band>()) { Console.WriteLine("\n{0}'s fans", b.BandName); foreach (var p in b.Fans) Console.WriteLine("* {0}", p.PersonName); } Console.WriteLine("\nAll people:"); foreach (var p in s.Query<Person>()) { Console.WriteLine("* {0}", p.PersonName); } Console.ReadLine(); } } }
Output:
Philippines's people * Michael * Yeyet China's people * Jolin * Atong Backstreet Boys's fans * Jolin * Yeyet Beatles's fans * Michael * Atong All people: * Michael * Jolin * Atong * Yeyet
DDL:
create table Country ( CountryId int identity(1,1) not null primary key, CountryName nvarchar(100) not null unique, Population int not null ); create table Band ( BandId int identity(1,1) not null primary key, BandName nvarchar(100) not null unique, YearStarted int not null ); create table Person ( PersonId int identity(1,1) not null primary key, PersonName nvarchar(100) not null unique, CountryId int not null references Country(CountryId), FavoriteBandId int null references Band(BandId) ); insert into Band(BandName,YearStarted) values('Beatles', 1957); insert into Band(BandName,YearStarted) values('Backstreet Boys', 1900); insert into Country(CountryName, Population) values('Philippines',9); insert into Country(CountryName, Population) values('China',2); insert into Person(PersonName,CountryId,FavoriteBandId) values('Michael',1,1) insert into Person(PersonName,CountryId,FavoriteBandId) values('Yeyet',1,2) insert into Person(PersonName,CountryId,FavoriteBandId) values('Jolin',2,2) insert into Person(PersonName,CountryId,FavoriteBandId) values('Atong',2,1)
No comments:
Post a Comment