一点一滴之NHibernate
之前介绍了Dapper,速度很快,很轻量,很好用。
但是Dapper其实有自己的弊端,比如在数据关系复杂,数据库表非常多,多数据库支持,数据库结构变动频繁的时候总是很无奈。尽管有代码生成器,但是代码生成器本来就有自身的许多劣根性,比如生成的代码单一,虽然可以用,但是也仅限制在CURD上。把数据库改下了,之前辛苦修改的代码又要重新再改一次,当然这个有方法解决,但是总是带来许多新的问题。
这个也几乎是所有轻量级ORM都会面临的一个问题。
后来实在被这个问题快搞崩溃了,于是写个小工具,希望设计好模型之后,直接生成不同的数据库结构,生成不同的代码表单页面,结果人懒到最后没写完还停在那里,可见这里。
再后来就用上了NHibernate。
NHibernate是一个很强的ORM.尽管让人诟病它的配置项,它的速度,但是亮点也总是很多,甚至超过了java版本。
OK 先来入门。定义几个基础的对象
public class CompanyGroup { public CompanyGroup() : this(string.Empty) { } public CompanyGroup(string name) { this.CompanyGroupName = name; } public virtual long CompanyGroupId { get; set; } public virtual string CompanyGroupName { get; set; } public virtual Company Company { get; set; } public virtual DateTime CreateTime { get; set; } public virtual CompanyGroupExtend CompanyGroupExtend { get; set; } }
/// <summary> /// 公司组扩展信息 /// </summary> public class CompanyGroupExtend { /// <summary> /// 扩展信息编号 /// </summary> public virtual long ExtendId { get; set; } /// <summary> /// 公司组别名 /// </summary> public virtual string CompanyGroupAliases { get; set; } /// <summary> /// 对应公司组 /// </summary> public virtual CompanyGroup CompanyGroup { get; set; } }
public class Company { public Company() : this(null) { } public Company(string name) { this.CompanyName = name; this.CompanyGroups = new List<CompanyGroup>(8); } public virtual long CompanyId { get; set; } public virtual string CompanyName { get; set; } public virtual string CompanyDescription { get; set; } public virtual DateTime CreateTime { get; set; } public virtual ICollection<CompanyGroup> CompanyGroups { get; set; } public virtual void AddCompanyGroup(CompanyGroup group) { if (!this.CompanyGroups.Contains(group)) { this.CompanyGroups.Add(group); } return; } public virtual void RemoveCompanyGroup(CompanyGroup group) { if (this.CompanyGroups.Contains(group)) { this.CompanyGroups.Remove(group); } return; } }
几个基础的实体类也反应了一组基础的关于,分别是1:m,和1:1两种管理。
NHibernate3.x之前,需要配置坑爹的xml,这个是个吐槽点,尽管装了xsd能够智能的感知以及修改,但是都忍不住吐槽,看了被c#惯坏了。
在NHibernate3.x以后可以直接进行手动的代码配置。比如
public class CompanyGroupExtendMap : ClassMapping<CompanyGroupExtend> { public CompanyGroupExtendMap() { base.Id(c => c.ExtendId, map => { map.Generator(Generators.Foreign<CompanyGroup>(c => c.CompanyGroupExtend)); }); base.Property(c => c.CompanyGroupAliases, map => { map.Length(50); map.NotNullable(true); }); base.OneToOne(c => c.CompanyGroup, map => { map.Constrained(true); map.Cascade(Cascade.All); }); } }
public class CompanyGroupMap : ClassMapping<CompanyGroup> { public CompanyGroupMap() { base.Id(c => c.CompanyGroupId, map => { map.Generator(Generators.Native); }); base.Property(c => c.CompanyGroupName, map => { map.Length(50); map.NotNullable(true); }); base.Property(c => c.CreateTime, map => map.NotNullable(true)); base.ManyToOne<Company>(c => c.Company, map => { map.Column("CompanyId"); map.Cascade(Cascade.None); }); base.OneToOne(c => c.CompanyGroupExtend, map => { map.Cascade(Cascade.All); map.Lazy(LazyRelation.Proxy); }); } }
public class CompanyMap : ClassMapping<Company> { public CompanyMap() { base.Id(c => c.CompanyId, map => { map.Generator(Generators.Native); map.Column("CompanyId"); }); base.Property(c => c.CompanyName, map => { map.Length(50); map.NotNullable(true); }); base.Property(c => c.CreateTime, map => { map.NotNullable(true); }); base.Property(c => c.CompanyDescription, map => { map.Length(SqlClientDriver.MaxSizeForLengthLimitedString + 1); }); base.Set(c => c.CompanyGroups, map => { map.Key(r => { r.Column("CompanyId"); }); map.Cascade(Cascade.All); map.Inverse(false); }, action => action.OneToMany()); } }
于是通过派生ModelMapper即可实现数据库的生成策略,以及生成数据库对象。
public class DatabaseGenerationStrategyMapper : ModelMapper { public DatabaseGenerationStrategyMapper() { //base.BeforeMapClass += (mi, propertyPath, map) => map.Table((propertyPath.Name + "Info").ToLower()); //base.BeforeMapProperty += (mi, propertyPath, map) => map.Column(propertyPath.ToColumnName().ToLower()); base.AfterMapManyToOne += (mi, propertyPath, map) => { map.Column((propertyPath.LocalMember.Name + "Id")); map.ForeignKey(string.Format("FK_{0}_{1}_{2}", propertyPath.LocalMember.Name, propertyPath.LocalMember.DeclaringType.Name, Guid.NewGuid().ToString().Substring(0, 8).ToUpper())); }; base.AfterMapOneToOne += (mi, propertyPath, map) => { map.ForeignKey(string.Format("FK_{0}_{1}_{2}", propertyPath.LocalMember.Name, propertyPath.LocalMember.DeclaringType.Name, Guid.NewGuid().ToString().Substring(0, 8).ToUpper())); }; } }
public class DatabaseMapper : DatabaseGenerationStrategyMapper { public DatabaseMapper() { base.AddMapping<CompanyGroupExtendMap>(); base.AddMapping<CompanyGroupMap>(); base.AddMapping<CompanyMap>(); base.AddMapping<UserMap>(); } public override string ToString() { return this.CompileMappingForAllExplicitlyAddedEntities().AsString(); } }
OK 配置搞定。
直接测试下看看。
var configure = new Configuration(); configure.SessionFactoryName("Demo"); configure.DataBaseIntegration(db => { db.Dialect<MsSql2005Dialect>(); db.Driver<SqlClientDriver>(); db.ConnectionString = @"Data Source=*;Initial Catalog=Database;User ID=sa;Password=123456;"; db.LogSqlInConsole = true; }); configure.AddMapping(new DatabaseMapper().CompileMappingForAllExplicitlyAddedEntities()); SchemaMetadataUpdater.QuoteTableAndColumns(configure); new SchemaExport(configure).Create(false, true); using (ISession session = configure.BuildSessionFactory().OpenSession()) { var company = new Company() { CompanyName = "TestCompany", CompanyDescription = "Description", CreateTime = DateTime.Now }; for (int i = 0; i < 100; i++) { var group = new CompanyGroup(Guid.NewGuid().ToString()); group.CreateTime = DateTime.Now; group.CompanyGroupName = "Test" + i.ToString(); company.AddCompanyGroup(group); } using (ITransaction transaction = session.BeginTransaction()) { session.Save(company); transaction.Commit(); } } using (ISession session = configure.BuildSessionFactory().OpenSession()) { var info = session.Get<Company>(1L); } using (ISession session = configure.BuildSessionFactory().OpenSession()) { using (ITransaction transaction = session.BeginTransaction()) { var info = session.Get<Company>(1L); session.Delete(info); transaction.Commit(); } } using (ISession session = configure.BuildSessionFactory().OpenSession()) { var pagesize = 10; var current = 1; var count = session.QueryOver<CompanyGroup>().Where(r => r.Company.CompanyId == 1).RowCount(); var infos = session.QueryOver<CompanyGroup>().Where(r => r.Company.CompanyId == 1).Skip(current * pagesize - pagesize).Take(pagesize).List(); Console.WriteLine(count); }
很简单实现了增删改查,级联操作,和多关系操作。
感谢李永京的NHibernate讲解,俺也是看着他的博客入门的,在他的博客里讲解的很详细,有兴趣的可以去看下。
一点一滴之NHibernate的更多相关文章
- Nhibernate的Session管理
参考:http://www.cnblogs.com/renrenqq/archive/2006/08/04/467688.html 但这个方法还不能解决Session缓存问题,由于创建Session需 ...
- "NHibernate.Exceptions.GenericADOException: could not load an entity" 解决方案
今天,测试一个项目的时候,抛出了这个莫名其妙的异常,然后就开始了一天的调试之旅... 花了很长时间,没有从代码找出任何问题... 那么到底哪里出问题呢? 根据下面那段长长的错误日志: -- ::, ...
- nhibernate连接11g数据库
我框架的数据映射用 nhibernate连接多数据库,这次又增加了oracle11g,负责开发的同事始终连接不上,悲催的sharepoint调试是在不方便... 下面描述下问题的解决,细节问题有3个: ...
- 全自动迁移数据库的实现 (Fluent NHibernate, Entity Framework Core)
在开发涉及到数据库的程序时,常会遇到一开始设计的结构不能满足需求需要再添加新字段或新表的情况,这时就需要进行数据库迁移. 实现数据库迁移有很多种办法,从手动管理各个版本的ddl脚本,到实现自己的mig ...
- 跟我学习NHibernate (1)
引言:Nibernate概述 NHibernate是一个ORM框架,NHibernate是一个把C#对象世界和关系世界数据库之间联系起来的一座桥梁.NHibernate 能自动映射实体模型到数据库,所 ...
- 让OData和NHibernate结合进行动态查询
OData是一个非常灵活的RESTful API,如果要做出强大的查询API,那么OData就强烈推荐了.http://www.odata.org/ OData的特点就是可以根据传入参数动态生成Ent ...
- MVC Nhibernate 示例
首先,非常感谢提出问题的朋友们,使得本人又去深入研究了NHibernate的<Session-Per-Request 模式>. 前言: 谈到NHibernate大伙并不陌生,搞Java ...
- Nhibernate mapping 文件编写
生成工具软件 现在生成工具软件有很多了,例如商业软件:NMG.CodeSmith.Visual NHibernate,开源软件:MyGeneration.NHibernate Modeller.AjG ...
- NHibernate之映射文件配置说明
NHibernate之映射文件配置说明 1. hibernate-mapping 这个元素包括以下可选的属性.schema属性,指明了这个映射所引用的表所在的schema名称.假若指定了这个属性, 表 ...
随机推荐
- js时间函数
时间 new Date() 获取时间,可以理解为是系统默认的函数. 从小括号里面获取系统时间日期,相当于在调用系统默认的函数. 年 getFullYear() 注意,有Full. 月 getMonth ...
- 每天一个linux命令(6):rmdir 命令
今天学习一下linux中命令: rmdir命令.rmdir是常用的命令,该命令的功能是删除空目录,一个目录被删除之前必须是空的.(注意,rm - r dir命令可代替rmdir,但是有很大危险性.)删 ...
- SpringMVC 架构
SpringMVC 架构 1. 前言 SpringMVC是目前java世界中最为广泛应用的web框架,最然从学习SpringMVC的第一个程序--helloworld至今,已有好几个年头.其间伴随着项 ...
- ThinkPHP中关于JS文件如何添加类似__PUBLIC__图片路径
在对html样式进行优化的时候,经常会用到Js/jquery进行一些跳转切换的样式,而我们常做的就是在Js/jquery代码中嵌url图片链接代码,以实现动态交互的页面效果. 如下图所示:
- Alcatraz的安装和使用
一.简单说明 Alcatraz 是一款 Xcode的插件管理工具,可以用来管理XCode的 插件.模版以及颜色配置的工具. 二.如何安装 1.github地址:https://github.com/a ...
- EnumHelper枚举常用操作类
在项目中需要把枚举填充到下拉框中,所以使用统一的方法实现,测试代码如下: namespace CutPictureTest.Comm { public class EnumHelper { publi ...
- Hadoop map和reduce数量估算
Hadoop在运行一个mapreduce job之前,需要估算这个job的maptask数和reducetask数.首先分析一下job的maptask数,当一个job提交时,jobclient首先分析 ...
- Java 多线程(1)-Thread和Runnable
一提到Java多线程,首先想到的是Thread继承和Runnable的接口实现 Thread继承 public class MyThread extends Thread { public void ...
- 【Vegas原创】安装rhel6.2,不能进图形化界面的终极解决方法
安装的时候,千万不要一路下一步,you should know,linux不是windows那么的傻瓜. 方法一: 在倒数最后一步,选择Desktop,而千万不要下一步,默认选择Basic Ser ...
- Linux Futex的设计与实现(转)
引子在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正确的运行使用glibc的程序" ...