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智能感知用的,在做表配置映射的時候會智能提示)

現在地址:http://nhibernate.info/ 

安裝包如下:

解壓后,里面很多文件

其中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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM