Fluent Nhibernate之旅(五)--利用AutoMapping进行简单开发
Fluent Nhibernate(以下简称FN)发展到如今,已经相当成熟了,在Nhibernate的书中也相应的推荐了使用FN来进行映射配置,之前写的FN之旅至今还有很多人会来私信我问题,说来惭愧,从FN之旅四至今已经4年多,至今还未更新过此系列,原因有很多,最大的就是懒惰,哈。
安装
现在在项目中使用FN很方便,使用Nuget管理就可以了,但我还是建议大家,可以下载源代码,自己可以详细了解下。

当然,您也可以用命令台来进行安装。说个题外话,NuGet真心不错,至少已经做新项目的时候不用到处去整理lib包了,从NuGet进行下载、更新、卸载都很方便,而且还能自搭建自己公司的服务器,不过目前还是有些问题,有时候在下载最新包无法使用的情况下,无法自动降低版本,还得自己去手动控制台下载,非常不便。
在NuGet下载FluentNhibernate后,会自动下载安装Nhibernate及Iesi。
配置
准备工作完成,今天我们要说下FN的AutoMapping,之前呢我们都是用了FluentMapping进行手动的Map映射,如果可以的话,请大家还是使用之前的映射方式,因为AutoMapping有很多契约,您需要按照一定的规范编写您的对象。
我们先看下ISessionFactory中的Mapping配置:
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005
.ConnectionString(s => s.Server(".")
.Database("MyNHibernate")
.TrustedConnection()))
.Mappings(m => m.FluentMappings.Add<Store>())
.BuildSessionFactory();
}
这是我们手动映射,Mapping()中指定了用FluentMappings进行映射,我们只要把它改成AutoMapping:
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005
.ConnectionString(s => s.Server(".")
.Database("MyNHibernate")
.TrustedConnection()))
.Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Store>()))
.BuildSessionFactory();
}
红色字体为不同之处,Store是我们需要映射的实体类,可能您会用为何不能像FluentMapping一样Add<T>()呢?因为这里考虑到一些契约的问题,它的Add参数为AutoPersistenceModel类型,接下来会说的。
数据库结构
接下来,我们设计一个数据库结构,简单点:

员工,仓库,产品,对应关系也全部到位了
实体类代码
我们来编写对应的Model代码:
public class Store
{
public Store()
{
Products = new List<Product>();
} public virtual int Id { get; set; } public virtual string Name { get; set; } public virtual IEnumerable<Product> Products { get; set; }
} public class UserName
{
public string FirstName { get; set; } public virtual string LastName { get; set; }
} public class Employee
{
public virtual int Id { get; set; } public virtual UserName Name { get; set; } public virtual Store Store { get; set; }
} public class Product
{
public Product()
{
Stores = new List<Store>();
} public virtual int Id { get; set; } public virtual float Price { get; set; } public virtual string Name { get; set; } public virtual IEnumerable<Store> Stores { get; set; }
}
好了,代码编写完毕,接下来是映射吗???No,无需映射了,因为我们用了AutoMapping,一切交给FN吧,我们接下来只要编写测试代码即可。
测试
我们先配置ISessionFactory:
private static string dbfile = ConfigurationManager.AppSettings["dbfile"];
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(SQLiteConfiguration.Standard.UsingFile(dbfile))
.Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Store>()))
.ExposeConfiguration(BuildSchema) //利用Nhibernate的SchemaExport创建数据库及其架构
.BuildSessionFactory();
} private static void BuildSchema(NHibernate.Cfg.Configuration obj)
{
//delete the existing db on each run
if (File.Exists(dbfile))
File.Delete(dbfile); new SchemaExport(obj).Create(false, true);
}
在这里,我用了Sqlite做为我们的数据库,ORM最大的好处就是我们可以随意的变更我们的数据库类型,不需要考虑其类型,这是我选择Nhibernate的原因,EF虽然通过扩展能够支持其他数据库,但我相信用EF使用其他数据库的人很少吧。用ExposeConfiguration方法委托Nhibernate的SchemaExport来创建数据库架构,相信很多NH玩家都会用吧。不过不建议把它用在稍大的项目里,我们的项目数据库会随着项目需求的增加和改变会经常修改的,建议用专业的数据库管理,比如Migrator,有兴趣下次可以开篇介绍下,用下来还是不错的。
[Fact]
public void DemoTest()
{
using (var session = CreateSessionFactory().OpenSession())
{
new PersistenceSpecification<Employee>(session)
.CheckProperty(c => c.Id, 1)
.CheckProperty(c => c.Name.FirstName, "James")
.CheckProperty(c => c.Name.LastName, "YinG")
.CheckReference(c => c.Store, new Store() { Name = "MyStore" })
.VerifyTheMappings();
}
}
我们利用XUnit进行测试下,您会发现报错:

这是为什么呢?这个其实就是AutoMapping在处理映射的时候,都是按照一定的规则去映射的,细心的朋友可能发现,我们的索引字段的字段名都是Id,这就是AutoMapping的约定,我们也可以自己来进行配置。
刚我们的测试报错,是因为Employee中的Name是个UserName类,Nhibernate的Component,我在FN之旅四(上)中有介绍到,默认情况下映射根据字段映射到数据库的,所以上面的测试会报错,接下来我们自己配置下:
编写一个类,继承DefaultAutomappingConfiguration:
public class CustomConfiguration : DefaultAutomappingConfiguration
{
public override bool IsComponent(Type type)
{
return type == typeof(UserName);
}
}
重写IsComponent方法,简单吧,核对下类型即可,写完自己的规则后,我们需要在建立SessionFactory的时候引入此配置:
.Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Store>(new CustomConfiguration())))
现在您还无法测试通过,因为我用了PersistenceSpecification进行测试的,在进行常规的测试时是没有问题的,但遇到Component或者Reference之类的,都需要我们自己来写一个IEqualityComparer的实现:
public class UserNameComparer : IEqualityComparer
{
public new bool Equals(object x, object y)
{
var username_x = x as UserName;
if (username_x == null) return false;
var username_y = y as UserName;
if (username_y == null) return false; return username_x.FirstName.Equals(username_y.FirstName) &&
username_x.LastName.Equals(username_y.LastName);
} public int GetHashCode(object obj)
{
throw new NotImplementedException();
}
} public class StoreComparer : IEqualityComparer
{
public new bool Equals(object x, object y)
{
var Store_x = x as Store;
if (Store_x == null) return false;
var Store_y = y as Store;
if (Store_y == null) return false; return Store_x.Id == Store_y.Id;
} public int GetHashCode(object obj)
{
throw new NotImplementedException();
}
}
好,修改下我们的测试代码:
[Fact]
public void DemoTest()
{
using (var session = CreateSessionFactory().OpenSession())
{
new PersistenceSpecification<Employee>(session)
.CheckProperty(c => c.Id, 1)
.CheckProperty(c => c.UserName, new UserName{
FirstName = "James", LastName = "YinG"
}, new UserNameComparer())
.CheckReference(c => c.Store, new Store() { Name = "MyStore" }, new StoreComparer())
.VerifyTheMappings();
}
}
在进行下测试,这下我们通过了:

这里我只测试了Employee和Store两个实体,对于多对多还未测试,时间有限,等有时间下篇继续下。今天介绍了AutoMapping简单的介绍,但在使用中您要时刻注意,AutoMapping是有很多限制的,比如Id,比如Component等,当然我们可以通过重写DefaultAutomappingConfiguration的一些方法来进行合适的一些配置,如果您要对持久类有一些要求,不对一对多的LazyLoad或者Cascade之类的,您需要通过实现IReferenceConvention,IHasManyConvention,IHasManyToManyConvention进行配置,今天就不多讲了,下次吧。
Fluent Nhibernate确实是个好东西,让我在开发上省去了很多时间,今天虽然介绍了AutoMapping,但我不推荐您在您的项目中使用,用起来没手感(个人感觉),需要约定的东西太多了,对于数据库结构也得按照他的契约来,否则就得自己重写一些方法,实现一些类,有点累人。但在开发一些小工具时,又要用到小型存储数据的话,不妨可以试试这种方式。
PS:今天本来心情不错,没想到有客人来拉横幅,一直在公司吵闹,害的我无法集中精力,估计在文章中会有错的地方,大家见谅了。
Fluent Nhibernate之旅(五)--利用AutoMapping进行简单开发的更多相关文章
- Fluent NHibernate之旅
Fluent NHibernate 之旅 导航篇: [原创]Fluent NHibernate之旅开篇: [原创]Fluent NHibernate之旅二--Entity Mapping: [原创]F ...
- 【翻译】Fluent NHibernate介绍和入门指南
英文原文地址:https://github.com/jagregory/fluent-nhibernate/wiki/Getting-started 翻译原文地址:http://www.cnblogs ...
- [Fluent NHibernate]一对多关系处理
目录 写在前面 系列文章 一对多关系 总结 写在前面 上篇文章简单介绍了,Fluent Nhibernate使用代码的方式生成Nhibernate的配置文件,以及如何生成持久化类的映射文件.通过上篇的 ...
- Fluent NHibernate AutoMapping Conventions
前言 使用nhibernate在项目中不管是代码或者xml文件映射方式,如果项目较大编写映射也应该算一笔大的工作量了,使用Fluent Nhibernate自己编写映射规则,将从conventions ...
- Fluent NHibernate and Spring.net
http://blog.bennymichielsen.be/2009/01/04/using-fluent-nhibernate-in-spring-net/ http://comments.gma ...
- NHibernate之旅系列文章导航
NHibernate之旅系列文章导航 宣传语 NHibernate.NHibernate教程.NHibernate入门.NHibernate下载.NHibernate教程中文版.NHibernate实 ...
- NHibernate之旅(18):初探代码生成工具使用
本节内容 引入 代码生成工具 结语 引入 我们花了大量的篇幅介绍了相关NHibernate的知识.一直都是带着大家手动编写代码,首先创建数据库架构.然后编写持久化类和映射文件,最后编写数据操作方法.測 ...
- 全自动迁移数据库的实现 (Fluent NHibernate, Entity Framework Core)
在开发涉及到数据库的程序时,常会遇到一开始设计的结构不能满足需求需要再添加新字段或新表的情况,这时就需要进行数据库迁移. 实现数据库迁移有很多种办法,从手动管理各个版本的ddl脚本,到实现自己的mig ...
- [Fluent NHibernate]第一个程序
目录 写在前面 Fluent Nhibernate简介 基本配置 总结 写在前面 在耗时两月,NHibernate系列出炉这篇文章中,很多园友说了Fluent Nhibernate的东东,也激起我的兴 ...
随机推荐
- 【HTML5&CSS3进阶学习01】气泡组件的实现
前言 气泡组件在实际工作中非常普遍,无论是网页中还是app中,比如: 我们这里所谓气泡组件是指列表型气泡组件,这里就其dom实现,css实现,js实现做一个讨论,最后对一些细节点做一些说明,希望对各位 ...
- javascript 函数初探 (四)--- 回调函数
回调函数 既然函数与任何被赋值给变量的数据是相同的,那么她当然可以像其他数据那样被定义.删除.拷贝,以及当成参数传递给其它函数. 我们定义一个函数,这个函数有两个函数类型的参数,然后他会分别执行这两个 ...
- Android刷机教程之LG Nexus 5X线刷官方Nexus系列教程
镜像下载地址:https://developers.google.com/android/nexus/images 1.打开手机 设置-关于手机-点击版本号7次,以打开“开发者选项” 2.返回上一步, ...
- CoreData的一些简单运用
1.首先创建一个新的工程 记得勾选下面的 Use Core Data 万恶分割线———————————————————————— 然后点击Add Entity 创建一个类似于表名. 万恶分割线———— ...
- windows下安装nginx
说起开发,自己感到非常惭愧,由于公司让我给<绿电侠>项目写整体架构解决方案,才开始接触nginx这个东东,突然觉得它是一把非常好的利器. 本文主要记录在windows下安装nginx,另参 ...
- ORACLE应用调优:请避免SQL做大量循环逻辑处理
前阵子遇到一个案例:一个同事说以前一个运行很正常的包,突然间比以前慢了很多,执行时间非常长,晚上的作业调用这个包跑了几个小时也没有跑出数据.于是我在跟踪.优化过程中定位到包中一个存储过程的一段SQL, ...
- Linux make: g++: Command not found
Linux使用make命令时遇到"make: g++: Command not found",这个主要是没有安装gcc-c++.x86_64,如下所示 [root@localh ...
- SQL SERVER Transactional Replication中添加新表如何不初始化整个快照
在SQL SERVER的复制(Replication)中,有可能出现由于业务需求变更,需要新增一张表或一些表到已有的复制(发布订阅)当中,这种需求应该是很正常,也很常见的.但是在已有的复制(发布订阅) ...
- Linux查看关机时间
在Linux系统中,如何查看系统什么时候执行了shutdown命令关闭服务器了呢? 方法1:使用 last -x|grep shutdown 查看shutdown的历史记录 [root@mylnx20 ...
- 从零自学Hadoop(16):Hive数据导入导出,集群数据迁移上
阅读目录 序 导入文件到Hive 将其他表的查询结果导入表 动态分区插入 将SQL语句的值插入到表中 模拟数据文件下载 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并 ...