一点一滴之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名称.假若指定了这个属性, 表 ...
随机推荐
- javascript中重要概念-闭包-深入理解
在上次的分享中javascript--函数参数与闭包--详解,对闭包的解释不够深入.本人经过一段时间的学习,对闭包的概念又有了新的理解.于是便把学习的过程整理成文章,一是为了加深自己闭包的理解,二是给 ...
- 【原创】jmeter3.0在beanshell中输入中文乱码以及字体大小的更改
我使用的是最新的jmeter3.0版本,新建一个beanshell sampler,在里面输入中文,发现显示的是乱码,而且字体非常小,看着吃力,调研了一下,可以在bin/jmeter.properti ...
- atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 。打开浏览服务器文件夹java .net php
atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 .打开浏览服务器文件夹java .net php 1. 环境:::项目java web,需要打开浏览服 ...
- TF Boys (TensorFlow Boys ) 养成记(六)
圣诞节玩的有点嗨,差点忘记更新.祝大家昨天圣诞节快乐,再过几天元旦节快乐. 来继续学习,在/home/your_name/TensorFlow/cifar10/ 下新建文件夹cifar10_train ...
- c#之第四课
数组: , , , , , , -, -, }; foreach (int i in numbers) { System.Console.WriteLine(i); }
- JAVA “Run as administrator” “UAC disabled” alternative solution
Technorati 标签: psexec,run as administrator,UAC java.io.IOException: Cannot run program "psexec. ...
- 2014 Hangjs 见闻流水账第二天
前言 第一天传送门: 2014 Hangjs 见闻流水账第一天 写作风格跟第一天还是一样的. Slide 每个slide我都会根据自己的理解重新命名一次,用于表达自己的第一看法,主观意见,不喜可吐槽, ...
- [转]mongodb与mysql相比的优缺点
原文地址:http://blog.sina.com.cn/s/blog_966e430001019s8v.html 与关系型数据库相比,MongoDB的优点:①弱一致性(最终一致),更能保证用户的访问 ...
- Goldengate进程的拆分与合并
Goldengate的拆分与合并分类: ORACLE GoldenGate 2013-10-10 15:22 721人阅读 评论(0) 收藏 举报在使用Goldengate作为复制解决方案时,随着负载 ...
- ABAP报表中负值展示问题的处理方法
现象描述 在使用ABAP报表展示数据的时候会涉及到金额类字段,在手动计算金额的时候,有时会发生存在负值而无法正常展示的情况. 处理过程 ABAP报表的数据展示常用的方法有两种,分别是表控制和ALV ...