C# 資料操作系列 - 12 NHibernate的增刪改查

月影西下發表於2020-05-22

0. 前言

上一篇《C# 資料操作系列 - 11 NHibernate 配置和結構介紹》 介紹了Nhibernate裡的配置內容。這一篇將帶領大家瞭解一下如何使用NHIbernate。之前提到NHibernate繼承了Hibernate的一些傳統:使用XML檔案進行配置,這一點也是備受爭議。不過,有社群愛好者開發了一個名為《Fluent NHibernate》的專案,用來支援NHibernate的流式配置。當然,NHibernate本身也提供了NHibernate.Mapping.ByCode模式。不過這一篇暫且略過,留待下文。

1. NHibernate對映檔案

對於NHibernate的對映檔案有個約定的名字:

<類名>.hbm.xml

這裡先為大家介紹一下對映檔案的格式:

1.1 hibernate-mapping 的說明

<hibernate-mapping
schema="schemaName" 									(1)
default-cascade="none|save-update" 						(2)
auto-import="true|false"		 						(3)
assembly="Eg" 											(4)
namespace="Eg" 											(5)
default-access="field|property|field.camecase..."		(6)
default-lazy="true|false" 								(7)
/>
  1. schema: 資料庫schema的名稱
  2. default-cascade:可選項,預設是none,一種預設的級聯風格
  3. auto-import:明確是否可以在查詢中使用非限定類名。
  4. assembly:指定對映物件所在的assembly,一般情況指的是專案名稱
  5. namespace:所在名稱空間
  6. default-access:可選的,預設是property,表示NHibernate的讀取資料列的策略,預設情況從Property 中讀取
  7. default-lazy:可選的,預設是true,是否啟動延遲載入

1.2 class的配置

一般情況下,class節點只需要指定name和table就可以了。接下來,讓我們探索class如何對映成的。

1.2.1 id

任何一個對映都必須宣告一個資料表的主鍵,大多數類也必須有一個唯一標示欄位用來區分不同的例項。

這裡介紹一下 id 節點的配置:

<id 
    name="PropertyName"
    type="typename"
    column="column_name">
    <generator class="generatorClass"/>
</id>
  • name : 對應的屬性名
  • type:對應的NHibernate型別
  • column:列名
  • generator:主鍵生成器,如果不需要引數可以直接在 id節點處新增,最常用的是native。

1.2.2 property

對映一個普通屬性就簡單多了,只需要進行以下配置即可:

<property
          name="propertyName"
          column="column_name"
          type="typename"
/>
  • name :類裡的屬性名
  • column:對應資料表的列名
  • type:資料庫中的型別

1.2.3 many-to-one

在Nhibernate中,多對一的配置是在一的一端,表示該類有一個外來鍵導航。

<many-to-one
             name="PropertyInOne"
             class="ManyClass"
             column="Column"
             ></many-to-one>

1.2.4 one-to-one

一對一的關係與多對一的關係比較相似,不同的地方在於一對一需要在雙方的對映關係裡均要維護,在有外來鍵的表/實體中 新增 constrained=“true”。

示例如下:

<one-to-one name="Person" class="Person"/>
<one-to-one name="Employee" class="Employee" constrained="true"/>

2. 增刪改查

Nhibernate的每次操作都基於一個Session,所以我們在運算元據庫的時候最好先持有一個可用的Session。接下來,我們就一個通用資料庫操作類為基礎,向大家分享一下我的想法。

首先,建立一個泛型模板類,並約束泛型為類:

public class Repository<T> where T: class
{

}

新增一個ISession屬性,用來後續訪問操作,並由構造方法賦值:

public Repository(ISession session)
{
    Session = session;
}

public ISession Session { get; }

2.1 新增

現在我們寫一下新增方法:

public object Add(T entity)
{
    var key= Session.Save(entity);
    return key;
}

public void Add(params T[] entities)
{
    foreach (var entity in entities)
    {
        Session.Save(entity);
    }
}

查了下,Save會返回當前持久化物件插入時生成的主鍵。

2.2 修改

NHibernate的修改與EF類似,也是由ISession監控了修改,不用做過多的操作。

2.3 刪除

NHibernate的刪除也十分簡單,直接通知ISession刪除某個持久化物件。

public void Delete(T entity)
{
    Session.Delete(entity);
}
public void Delete(params T[] entities)
{
    foreach (var entity in entities)
    {
        Session.Delete(entity);
    }
}

2.4 查詢

通常情況下,查詢需要結合實際業務來進行開發,當然為了通用,我在這裡選擇給呼叫方開放一個查詢物件:

public IQueryable<T> IqQueryable()
{
    return Session.Query<T>();
}

其中 IQueryable是一個介面,表示這是一個可查詢物件,通過Linq可以快捷的查詢。

3. 總結

嗯,NHibernate基礎使用篇到這裡可以暫告一段落了。後續的內容有機會再深挖,當然並不代表EF Core就沒有了。嗯嗯,沒毛病。下一篇就讓我來先替大夥看看SugarSQL是什麼情況吧。

不過在本篇內容完結之前,先補充一個NHibernate的SqlDialect選值:

資料庫 Dialect 備註
DB2 NHibernate.Dialect.DB2Dialect
DB2 for iSeries(OS/400) NHibernate.Dialect.DB2400Dialect
Firebird NHibernate.Dialect.FirebirdDialect 需要設定driver_class為NHibernate.Driver.FirebirdClientDriver
Informix NHibernate.Dialect.InformixDialect
Informix 9.40 NHibernate.Dialect.InformixDialect0940
Informix 10.00 NHibernate.Dialect.InformixDialect1000
Ingres NHibernate.Dialect.IngresDialect
Ingres 9 NHibernate.Dialect.Ingres9Dialect
Microsoft SQL Server 7 NHibernate.Dialect.MsSql7Dialect
Microsoft SQL Server 2000 NHibernate.Dialect.MsSql2000Dialect
Microsoft SQL Server 2005 NHibernate.Dialect.MsSql2005Dialect
Microsoft SQL Server 2008 NHibernate.Dialect.MsSql2008Dialect
Microsoft SQL Azure Server 2008 NHibernate.Dialect.MsSqlAzure2008Dialect
Microsoft SQL Server 2012 Hibernate.Dialect.MsSql2012Dialect
Microsoft SQL Server Compact Edition NHibernate.Dialect.MsSqlCeDialect
Microsoft SQL Server Compact Edition 4.0 NHibernate.Dialect.MsSqlCe40Dialect
MySQL 3 or 4 NHibernate.Dialect.MySQLDialect
MySQL 5 NHibernate.Dialect.MySQL5Dialect
MySQL 5 InnoDB NHibernate.Dialect.MySQL5InnoDBDialect
MySQL 5.5 NHibernate.Dialect.MySQL55Dialect
MySQL 5.5 Inno DB NHibernate.Dialect.MySQL55InnoDBDialect
Oracle NHibernate.Dialect.Oracle8iDialect
Oracle 9i NHibernate.Dialect.Oracle9iDialect
Oracle 10g, Oracle 11g NHibernate.Dialect.Oracle10gDialect
Oracle 12c NHibernate.Dialect.Oracle12cDialect
PostgreSQL NHibernate.Dialect.PostgreSQLDialect
PostgreSQL 8.1 NHibernate.Dialect.PostgreSQL81Dialect 支援8.1 的 FOR UPDATE NOWAIT
PostgreSQL 8.2 NHibernate.Dialect.PostgreSQL82Dialect 在DROP TABLE和DROP SEQUENCE 語句中支援 IF EXISTS關鍵字
PostgreSQL 8.3 NHibernate.Dialect.PostgreSQL83Dialect 支援XML型別
SQLite NHibernate.Dialect.SQLiteDialect 設定driver_class為NHibernate.Driver.SQLite20Driver
Sybase Adaptive Server Anywhere 9 NHibernate.Dialect.SybaseASA9Dialect
Sybase Adaptive Server Enterprise 15 NHibernate.Dialect.SybaseASE15Dialect
Sybase SQL Anywhere 10 NHibernate.Dialect.SybaseSQLAnywhere10Dialect
Sybase SQL Anywhere 11 NHibernate.Dialect.SybaseSQLAnywhere11Dialect
Sybase SQL Anywhere 12 NHibernate.Dialect.SybaseSQLAnywhere12Dialect

更多內容煩請關注我的部落格《高先生小屋》

file

相關文章