由於新公司用的是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; } } }
持續更新,這只是個開始....
http://www.codeproject.com/Articles/830326/CRUD-Operations-with-ASP-NET-Web-API-using-FluentN
http://www.codeproject.com/Articles/891056/Automatic-Table-Generation-in-any-database-by-NHib