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