NHibernate入门
由于新公司用的是NHibernate数据库ORM, 所以也是在学习中,以前用Entity Framework,所以希望一步一步的学习。
要了解一个新技术,最经典的是从Hellow World!开始。
我们要完成的任务:
- 一、使用Visual Studio 2015 建立一个控制台项目
- 二、使用NuGet安装NHibernate
- 三、下载NHibernate(上面用Nuget安装了,为什么还要下载呢?因为下载包里有个文件要用到,给VS智能感知用的,在做表配置映射的时候会智能提示)
- 四、添加一个本地数据库文件,用以建测试数据库用
- 五、配置NHibernate,包括:
- 六、编写代码,读取数据库记录
- 七、对数据的CRUD操作。
- 八、数据库改为MySQL,目前公司在用MySQL
下面我们就一步一步安装上面的步骤完成任务
一、新建控制台项目:NHFirstDemo
二、使用NuGet安装NHibernate
安装完成后的类库引用多了2个项,其他没有变。(多个packages.config,Nuget配置文件)
三、下载NHibernate(上面用Nuget安装了,为什么还要下载呢?因为下载包里有个文件要用到,给VS智能感知用的,在做表配置映射的时候会智能提示)
安装包如下:
解压后,里面很多文件
其中Required_Bins 包括我们需要的文件
四、添加一个本地数据库文件 DemoDB,用以建测试数据库用
创建表User,3个字段,id主键,标识,不为空。Name50个字符串可空,Age 整形,可空,建议规范命名,首字母大写,字符串用nvarchar 类型不会有乱码出现
随便插入几条测试数据:
五、配置NHibernate,包括:
创建映射文件,一个实体一个文件,User.hbm.xml,双击打开该文件,然后在空白处右击选择属性导入智能提示文件
看看,有智能提示了
User.hbm.xml 文件内容:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" schema="NHFirstDemo" namespace="NHFirstDemo.NHFirstDemo"> <class name="User"> <id name="Id" generator="hilo" /> <property name="Name" /> <property name="Age" /> </class> </hibernate-mapping>
再新加一个实体类(POCO)文件 User.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace NHFirstDemo { public class User { public virtual int Id { get; set; } public virtual string Name { get; set; } public virtual int Age { get; set; } } }
=====================================================================================================
换一个类来做示例
Customer.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace NHibernateDemoApp { public class Customer { public virtual int Id { get; set; } public virtual string FirstName { get; set; } public virtual string LastName { get; set; } public virtual double AverageRating { get; set; } public virtual int Points { get; set; } public virtual bool HasGoldStatus { get; set; } public virtual DateTime MemberSince { get; set; } public virtual CustomerCreditRating CreditRating { get; set; } public virtual string Street { get; set; } public virtual string City { get; set; } /// <summary> /// 省份 /// </summary> public virtual string Province { get; set; } public virtual string Country { get; set; } } public enum CustomerCreditRating { /// <summary> /// 卓越的;极好的;杰出的 /// </summary> Excellent, /// <summary> /// 非常棒 /// </summary> VeryVeryGood, /// <summary> /// 很好 /// </summary> VeryGood, /// <summary> /// 好 /// </summary> Good, /// <summary> /// 一般 /// </summary> Neutral, /// <summary> /// 差 /// </summary> Poor, /// <summary> /// 惨不忍睹 /// </summary> Terrible } }
对应的映射文件 Customer.hbm.xml
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateDemoApp" namespace="NHibernateDemoApp"> <class name="Customer" table="Customer"> <id name="Id"> <generator class="native" /> </id> <property name="FirstName" not-null="true" /> <property name="LastName" not-null="true" /> <property name="AverageRating" /> <property name="Points" /> <property name="HasGoldStatus" /> <property name="MemberSince" /> <property name="CreditRating" type="CustomerCreditRating" /> <property name="Street" /> <property name="City" /> <property name="Province" /> <property name="Country" /> </class> </hibernate-mapping>
- 注意hibernate-mapping的assembly、namespace属性要填写正确
- class的name属性表示类名,table是映射的表名,如果类名称和表名称相同,可以省略table属性
- property的name属性是类的属性名,如果类属性名和表的列名相同,可以省略column属性
- property的type属性表示.net类属性映射的NHibernate数据类型。如果是int、bool、double这样的.net基础数据类型,则可以省略
- property的type属性如果是DateTime、string,也可以省略
- property的not-null属性对应关系表的列的nullable属性,默认值是false。因此,如果允许为空,则可以省略
- id表示主键,name为主键名,<generator class="native"/>表示数据表的主键按简单Identity的自增算法生成新记录主键值(NHibernate提供了多种主键值生成算法,这里只用最简单的Identity算法)
- 文件名必须以.hbm.xml结尾
连接配置数据库
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NHibernate.Cfg; using NHibernate.Dialect; using NHibernate.Driver; using System.Reflection; namespace NHibernateDemoApp { class Program { static void Main( string [] args) { var cfg = new Configuration(); //Configuration类对象相当于ADO.Net的Connection对象,但是他包含更丰富的配置信息。 //调用cfg.DataBaseIntegration方法进行配置,这里配置了:数据库连接字符串、使用连接的Driver类SqlClientDriver和使用Dialect类MsSql2008Dialect cfg.DataBaseIntegration(x => { x.ConnectionString = "Data Source=localhost;Initial Catalog=NHibernateDemoDB;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" ; x.Driver<SqlClientDriver>(); x.Dialect<MsSql2008Dialect>(); }); cfg.AddAssembly(Assembly.GetExecutingAssembly()); //告诉NHibernate去哪里找xml映射文件信息 var sefact = cfg.BuildSessionFactory(); //SessionFactory和Session是NHibernate的基础类,SessionFactory编译所有的元数据,产生Session。Session封装了所有的NHibernate方法 using ( var session = sefact.OpenSession()) { using ( var tx = session.BeginTransaction()) { // tx.Commit(); Console.WriteLine( "Well Done" ); } Console.ReadLine(); } } } } |
改进上面的操作方法
|
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NHibernate.Cfg; using NHibernate.Dialect; using NHibernate.Driver; using System.Reflection; using NHibernate; namespace NHibernateDemoApp { class Program { private static ISessionFactory _sessionFactory; public static ISessionFactory SessionFactory { get { //SessionFactory的创建很占用系统资源,一般在整个应用程序中只创建一次。因此,这里通过判断if (_sessionFactory == null)实现一个最简单的单例模式。 if (_sessionFactory == null ) { var cfg = new Configuration(); cfg.DataBaseIntegration(x => { x.ConnectionString = "Data Source=localhost;Initial Catalog=NHibernateDemoDB;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" ; x.Driver<SqlClientDriver>(); x.Dialect<MsSql2008Dialect>(); }); cfg.AddAssembly(Assembly.GetExecutingAssembly()); _sessionFactory = cfg.BuildSessionFactory(); } return _sessionFactory; } } private static IList<Customer> GetAll() { using ( var session = SessionFactory.OpenSession()) { IList<Customer> list = session.CreateCriteria<Customer>().List<Customer>(); return list; } } private static Customer GetById( int id) { using ( var session = SessionFactory.OpenSession()) { Customer customer = session.Get<Customer>(id); return customer; } } /// <summary> /// 新增客户 /// </summary> /// <param name="customer">客户对象</param> /// <returns>插入后的客户ID</returns> private static int Insert(Customer customer) { using ( var session = SessionFactory.OpenSession()) { var identifier = session.Save(customer); //插入新记录,返回新纪录主键值 session.Flush(); //增删改操作完成之后需要调用session.Flush()方法,将对象持久化写入数据库。如果不调用此方法,方法结束后修改记录不能写入到数据库 return Convert.ToInt32(identifier); } } private static void Update(Customer customer) { using ( var session = SessionFactory.OpenSession()) { session.SaveOrUpdate(customer); //如果被调用的Customer对象在数据库里不存在(新记录),则插入新记录,否则修改该记录 session.Flush(); } } private static void Delete( int id) { using ( var session = SessionFactory.OpenSession()) { var customer = session.Load<Customer>(id); session.Delete(customer); //传入Customer对象进行删除 session.Flush(); } } static void Main( string [] args) { #region 原始链接数据库方法 /* var cfg = new Configuration();//Configuration类对象相当于ADO.Net的Connection对象,但是他包含更丰富的配置信息。 //调用cfg.DataBaseIntegration方法进行配置,这里配置了:数据库连接字符串、使用连接的Driver类SqlClientDriver和使用Dialect类MsSql2008Dialect cfg.DataBaseIntegration(x => { x.ConnectionString = "Data Source=localhost;Initial Catalog=NHibernateDemoDB;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"; x.Driver<SqlClientDriver>(); x.Dialect<MsSql2008Dialect>(); }); cfg.AddAssembly(Assembly.GetExecutingAssembly());//告诉NHibernate去哪里找xml映射文件信息 var sefact = cfg.BuildSessionFactory();//SessionFactory和Session是NHibernate的基础类,SessionFactory编译所有的元数据,产生Session。Session封装了所有的NHibernate方法 using (var session = sefact.OpenSession()) { using (var tx = session.BeginTransaction()) { // tx.Commit(); Console.WriteLine("Well Done"); } Console.ReadLine(); } */ #endregion Customer newCustomer = CreateCustomer(); int customerId = Insert(newCustomer); Console.WriteLine( "新客户ID:{0}" , customerId); IList<Customer> list = GetAll(); Console.WriteLine( "客户列表数量:{0}" , list.Count); foreach ( var item in list) { Console.WriteLine( "{0} {1}" , item.FirstName, item.LastName); } var customer = GetById(customerId); Console.WriteLine( "GetById: {0} {1}" , customer.FirstName, customer.LastName); customer.LastName = "Chen" ; Update(customer); var updatedCustomer = GetById(customerId); Console.WriteLine( "updated: {0} {1}" , updatedCustomer.FirstName, updatedCustomer.LastName); Delete(customerId); var existedCustomer = GetById(customerId); Console.WriteLine( "after deleted: existing: {0}" , existedCustomer != null ); Console.ReadLine(); } //示例数据 private static Customer CreateCustomer() { var customer = new Customer { FirstName = "Daniel" , LastName = "Tang" , Points = 100, HasGoldStatus = true , MemberSince = new DateTime(2012, 1, 1), CreditRating = CustomerCreditRating.Good, AverageRating = 42.42424242, Street = "123 Somewhere Avenue" , City = "Nowhere" , Province = "Alberta" , Country = "Canada" }; return customer; } } } |
莫谈他人高薪,且看闲时谁在拼.