使用Fluent NHibernate自动映射
使用Fluent NHibernate自动映射,首先要将映射的实体放到一个命名空间中,这使得通知AutoMapper哪些实体和值对象包含在映射中更容易。建议在你的项目中创建一个Domain文件夹,将需要映射的实体和值对象放到这个文件夹中。
因为隐式映射实体和值对象,需要为AutoMapping定义约定和例外。我们通过实现一个继承自DefaultAutomappingConfiguration的配置类实现。
假设我们已经将所有的实体和值对象放在了相同的命名空间中,这个命名空间只包含domain类,我们就可以如下面的代码定义配置类:
public class OrderingSystemConfiguration : DefaultAutomappingConfiguration { public override bool ShouldMap(Type type) { return type.Namespace == typeof(Customer).Namespace; } }
上面的代码告诉AutoMapping只映射那些和Customer实体有相同命名空间的类。
在AutoMapper工作之前,我们还需要告诉它更多的事情。我们必须告诉它在系统中谁是值对象。这可以在配置类中重写IsComponent方法实现,如下面代码所示:
public override bool IsComponent(Type type) { var componentTypes = new[] { typeof(Name), typeof(Address) }; return componentTypes.Contains(type); }
配置系统使用自动映射,我们利用下面的代码:
var cfg = new OrderingSystemConfiguration(); var configuration = Fluently.Configure() .Database(/* database config */) .Mappings(m =>m.AutoMappings.Add( AutoMap.AssemblyOf<Employee>(cfg))) .BuildConfiguration();
实战时间–使用自动映射
在这个例子中,我们想定义一个基本的领域模型,使用Fluent NHibernate提供的自动映射来映射我们的模型,然后让NHibernate根据映射为我们生成数据库架构:
1. 在VS中创建一个Console Application,名字为:AutoMappingSample。
2. 添加NHibernate.dll和FluentNHibernate两个程序集到项目中。
3. 在项目中新建一个Domain文件夹。
4. 分别添加以下类到Domain文件夹中:
Customer类
namespace AutoMappingSample.Domain { public class Customer { public virtual int Id { get; set; } public virtual string CustomerName { get; set; } } }
LineItem类
namespace AutoMappingSample.Domain { public class LineItem { public virtual int Id { get; set; } public virtual int Quantity { get; set; } public virtual decimal UnitPrice { get; set; } public virtual string ProductCode { get; set; } } }
Order类
namespace AutoMappingSample.Domain { public class Order { public virtual int Id { get; set; } public virtual DateTime OrderDate { get; set; } public virtual Customer Customer { get; set; } public virtual IList<LineItem> LineItems { get; set; } } }
5. 在项目中添加一个OrderingSystemConfiguration类,继承自DefaultAutomappingConfiguration。
6. 重写ShouldMap方法,如下面的代码:
namespace AutoMappingSample { public class OrderingSystemConfiguration : DefaultAutomappingConfiguration { public override bool ShouldMap(Type type) { return type.Namespace == typeof(Customer).Namespace; } } }
7. 在Program类中添加如下using语句:
using FluentNHibernate.Cfg; using FluentNHibernate.Cfg.Db; using FluentNHibernate.Automapping; using AutoMappingSample.Domain; using NHibernate.Tool.hbm2ddl;
8. 添加下面的代码到Program类的Main方法创建NHibernate配置。配置对象使用Fluent NHibernate的配置API创建用于自动映射。
var cfg = new OrderingSystemConfiguration(); var configuration = Fluently.Configure().Database(MsSqlConfiguration.MsSql2008) .Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Customer>(cfg))).BuildConfiguration();
注意为这个操作定义数据库字符串没有必要,因为我们不访问数据库,只是告诉NHibernate哪种类型的数据库。
9. 添加下面的代码创建并在控制台上显示SQL脚本:
var exporter = new SchemaExport(configuration); exporter.Execute(true, false, false);
10. 添加下面的代码避免程序不经确认就退出:
Console.WriteLine("按回车退出:"); Console.ReadLine();
11. 运行程序,控制台输出如下:
使用ConfORM自动映射
ConfORM是NHibernate contributions的一部分,可从http://code.google.com/p/codeconform/downloads/list下载。确保下载的版本兼容你使用的NHibernate版本。
和Fluent NHibernate的AutoMapper一样,ConfORM使用约定隐式定义领域模型的映射。这些约定可以重写,也可以定义我们自己的约定。
实战时间–使用ConfORM映射模型
在这个例子中,我们再一次创建一个简单的领域模型并使用ConfORM为我们创建一个隐式的映射。然后我们使用NHiernate的schema exporter创建SQL脚本来创建兼容我们模型的数据库架构。
1. 打开VS,创建一个Console Application项目,名字为:ConfORMSample。
2. 添加对NHibernate.dll和ConfORM.dll程序集的引用到项目中。我使用的NHibernate版本是3.1的,所以ConfORM也是兼容3.1的ConfORM 1.0.1.5。
3. 在项目中创建一个Domain文件夹。
4. 添加上一个例子中的Customer,Order和LineItem类到Domain文件夹。
Customer类
namespace ConfORMSample.Domain { public class Customer { public virtual int Id { get; set; } public virtual string CustomerName { get; set; } } }
Order类
namespace ConfORMSample.Domain { public class Order { public virtual int Id { get; set; } public virtual DateTime OrderDate { get; set; } public virtual Customer Customer { get; set; } public virtual IList<LineItem> LineItems { get; set; } } }
LineItem类
namespace ConfORMSample.Domain { public class LineItem { public virtual int Id { get; set; } public virtual int Quantity { get; set; } public virtual decimal UnitPrice { get; set; } public virtual string ProductCode { get; set; } } }
5. 在Program类中添加如下using语句:
using ConfORMSample.Domain; using ConfOrm; using ConfOrm.NH; using NHibernate.Cfg; using NHibernate.Cfg.Loquacious; using NHibernate.Dialect; using NHibernate.Driver; using NHibernate.Tool.hbm2ddl;
6. 在Program类的Main方法中,使用NHibernate提供的fluent配置API创建一个NHibernate配置对象:
var configuration = new Configuration(); configuration.DataBaseIntegration(db => { db.Dialect<MsSql2008Dialect>(); db.Driver<SqlClientDriver>(); });
7. 添加如下代码,确定要映射的类型:
var types = typeof(Customer).Assembly.GetTypes() .Where(t => t.Namespace == typeof(Customer).Namespace);
8. 创建一个类型为ObjectRelationalMapper的实例,如下面的代码所示:
var orm = new ObjectRelationalMapper();
9. 告诉映射器,应该为每一个类型创建一个表,如下所示:
orm.TablePerClass(types);
10. 创建映射,并将它们添加到配置对象,如下面的代码所示:
var mapper = new Mapper(orm); var hbmMappings = mapper.CompileMappingFor(types); configuration.AddDeserializedMapping(hbmMappings, "MyDomain");
11. 创建schema生成脚本,如下面的代码所示:
var exporter = new SchemaExport(configuration); exporter.Execute(true, false, false);
12. 同样,添加下面的代码为避免程序未经确认就退出:
Console.Write("按回车退出:"); Console.ReadLine();
13. 运行程序,如下图所示:
没用编码和少量的配置,我们就使系统为我们的领域模型创建了一个隐式的映射,并导出为可以创建数据库架构的脚本。生成的脚本基于定义在ConfORM中的约定。所有的这些约定都可以重写,也可以根据需要添加自己的约定。
自动映射到此为止,下一篇介绍XML映射。