日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Fluent NHibernate关系映射

發布時間:2024/9/5 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Fluent NHibernate关系映射 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.好處:Fluent NHibernate讓你不再需要去寫NHibernate的標準映射文件(.hbm.xml), 方便了我們的代碼重構,提供了代碼的易讀性,并精簡了項目代碼

實現:

(1)、首先我們通過nuget包管理器添加FluentNHibernate與NHibernate的引用。

(2)、編寫實體類,注意實體的屬性都是virtual

(3)、實體類編寫完成以后我們用代碼的方式實現對實體的映射

Fluent NHibernate主要實現的映射關系:一對一、一對多、多對一、多對多

下面介紹幾種映射關系中主講一對多關聯屬性

?

2. 一對一映射 HasOne<>()

2.1. 定義支持的關聯屬性

Cascade 指該對象在進行操作時關聯到的子對象的操作類型

PropertyRef屬性一般用來解決遺留數據庫一對多關系的問題

PropertyRef被關聯到此外鍵的類中的對應屬性的名字,若沒指定,使用被關聯類的主鍵.

PropertyRef不是數據庫表中的字段名,而是定義的類中的屬性名

Fetch??? 在外連接抓取或者序列選擇抓取選擇其一.

class:被關聯的類的名字

constrained ?表明該類對應的表對應的數據庫表,和被關聯的對象所對應的數據庫表之間,通過一個外鍵引用對主鍵進行約束。 這個選項影響Save()和Delete()在級聯執行時的先后順序以及決定該關聯能否被委托

2.1.1.映射范例

用戶和用戶信息表在實際中是一對一的關系,這兩個表之間是通過使用UserID來相互關聯的,UserDetail使用的主鍵ID與User的ID是一致的,所以我們要使用Foregin來獲取User的ID,它們有一個共同的ID,在插入Users表的同時也要寫入UserDetail表,所以需要添加一對一的限制關系,具體的在User和UsersDetai兩表的映射方法如下代碼

  public UserMap() 

{ 

???????? Table("Users");?

    Id(u => u.UserID).GeneratedBy.Identity() ; 

    Map(u => u.UserName); 

    Map(u => u.Password); 

    Map(u => u.CreateTime); 

    HasOne<UserDetail>(u => u.Detail).Cascade.All().PropertyRef("User"); 

} 

  public UserDetailMap() 

{ 

Table("UserDetais");?

    Id(u => u.UserID).Column("UserID").GeneratedBy.Foreign("User"); 

    HasOne<User>(d => d.User).Cascade.All().Constrained(); 

    Map(u => u.LastUpdated).Nullable(); 

    Component<PersonName>(u => u.Name, p => 

    { 

      p.Map(o => o.FirstName).Column("[First Name]"); 

      p.Map(o => o.LastName).Column("[Last Name]"); 

    }); 

} 

2.1.2.補充說明

上面指定了All說明所有的操作都會關聯到子表,還有SaveUpdate在添加和更新時關聯子表,另外還有None類型不推薦使用此類型因為會出現很多問題。

一對一延遲加載

有時對我們來說,只需要User就可以了,我不需要查詢UserDetail,或許你會說,使用以下方式來進行延遲加載:

HasOne<UserDetail>(u => u.Detail).Cascade.All().LazyLoad();

雖然Fluent支持,雖然編譯通過,但在創建ISessionFactory的時候,卻會拋出異常,因為NHibernate不支持HasOne的不支持一對一的延遲Lazy加載的特性, 可以用:

HasOne<UserDetail>(u => u.Detail).Cascade.All().Fetch.Select();

HasOne<User>(d => d.User).Cascade.All().Constrained();

?

3. 一對多HasMany<>() / 多對一 References<>()

3.1. 定義支持的關聯屬性

KeyColumn? 表示主鍵名

Cascade表示級聯取值,決定是否把對對象的改動反映到數據庫中,所以Cascade對所有的關聯關系都起作用, Cascade是操作上的連鎖反映,Cascade取值可能是以下:

AllDeleteOrphan?????? 在關聯對象失去宿主(解除父子關系)時,自動刪除不屬于父對象的子對象, 也支持級聯刪除和級聯保存更新.

DeleteOrphan?????????? 刪除所有和當前對象解除關聯關系的對象????????

All???????????????? 級聯刪除, 級聯更新,但解除父子關系時不會自動刪除子對象.

Delete????????????????????????????????? 級聯刪除, 但不具備級聯保存和更新

None???????????????????????????????????? 所有操作均不進行級聯操作

SaveUpdate??????????????????????? 級聯保存(load以后如果子對象發生了更新,也會級聯更新). 在執行save/update/saveOrUpdate時進行關聯操作,它不會級聯刪除

Inverse() ???所描述的是對象之間關聯關系的維護方式,作用是:是否將對集合對象的修改反映到數據庫中。Inverse表示對集合對象的修改會被反映到數據庫中;

為了維持兩個實體類(表)的關系,而添加的一些屬性,該屬性可能在兩個實體類(表)或者在一個獨立的表里面,這個要看這雙方直接的對應關系了: 這里的維護指的是當主控方進行增刪改查操作時,會同時對關聯關系進行對應的更新,Inverse是操作上的連鎖反映。

ForeignKeyConstraintName?? 外鍵約束名

Access?? NHibernate用來訪問屬性的策略。

unique: 為外鍵字段生成一個唯一約束。此外, 這也可以用作PropertyRef的目標屬性。這使關聯同時具有 一對一的效果。

OptimisticLock? 定這個屬性在做更新時是否需要獲得樂觀鎖定(OptimisticLock)。 換句話說,它決定這個屬性發生臟數據時版本(version)的值是否增長。

NotFound?? 指定外鍵引用的數據不存在時如何處理: ignore會將數據不存在作為關聯到一個空對象(null)處理。

IsProxy???? 指定一個類或者接口,在延遲裝載時作為代理使用。

Schema

3.1.1. 映射范例

一個用戶可以擁有多個訂單,一個訂單只能擁有一個用戶,對于用戶來說,不需要每次都加載訂單列表,反之訂單可能每次都需要加載用戶信息。

  public UserMap() 

{ 

???????? Table("Users");?

    Id(u => u.UserID).GeneratedBy.Identity() ; 

    Map(u => u.UserName); 

    Map(u => u.Password); 

    Map(u => u.CreateTime); 

    HasOne<UserDetail>(u => u.Detail).Cascade.All().Fetch.Select(); //一對一映射用戶和用戶信息表

    HasMany<Order>(u => u.Orders).AsSet().KeyColumn("UserID").Cascade.All(); 處理一對多關系的映射,一個User可以有多個訂單, 關聯的數據表進行懶加載,主鍵名為UserID,級聯關系所有操作

}

  public OrderMap() 

  { 

?????????????????? Table("Orders");?

    Id(o => o.OrderID).GeneratedBy.Identity(); 

    Map(o => o.Price); 

    Map(o => o.State).CustomType<OrderState>(); 

    Map(o => o.Address); 

    Map(o => o.Coignee); 

    Map(o => o.CreateTime); 

    Map(o => o.Zip); 

    References<User>(o => o.User).Not.LazyLoad().Column("UserID");  //處理多對一關系,多個Order可以屬于一個User

  } 

?

/// <summary>

??????? /// 映射關系實體類的構造函數

??????? /// 在構造函數中處理好映射關系

??????? /// </summary>

??????? public CustomerMapping()

??????? {

??????????? //指定持久化類對應的數據表

??????????? Table("TB_Customer");

??????? ????//自動增長的id

??????????? //Id(i => i.CustomerID);

??????????? //映射關系

??????????? Id<Guid>("CustomerID").GeneratedBy.GuidComb();

??????????? //指定主鍵后一定要加上主鍵字段的映射關系,不然返回的id為new Guid(),也就是一串0

??????????? Map(m => m.CustomerID).Nullable();

??????????? Map(m => m.CustomerAddress).Length(50).Nullable();

??????????? Map(m => m.CustomerName).Length(32).Nullable();

??????????? Map(m => m.Version);

??????????? //處理一對多關系的映射,一個客戶可以有多個訂單

??????????? //關聯的數據表進行懶加載,主鍵名為CustomerID,級聯關系所有操作,cascade:All|delete|saveorUpdate,級聯刪除時需加上Inverse()

??????????? //???? Inverse the ownership of this entity. Make the other side of the relationship

??????????? //???? responsible for saving.

??????????? HasMany<Order>(h => h.Orders).LazyLoad().AsSet().KeyColumn("CustomerID").Cascade.All().Inverse();

??????? }

?

首先是Tasks表的映射,因為Tasks表是多的一端,所以要添加對Projects表的外鍵引用關系,另外因為是一種外鍵引用不關系到父表的操作,所以這里可以使用Cascade.None()。

??? public TasksMappping()

??? {

??????? Table("Tasks");

??????? LazyLoad();

??????? Id(x => x.ID).Column("TaskID").GeneratedBy.Identity();

??????? References(x => x.Project).Nullable().Column("ProjectID").Cascade.None();//處理多對一關系,多個Tasks可以屬于一個Project

??????? Map(x => x.Name).Nullable();

??? }

在Projects表中,因為該表中的一個ID會對應多個Tasks所以在添加HasMany方法,來表明Projects和Tasks的多對一的關系,如下代碼它會涉及到任務的添加和更新操作,所以需要使用Cascade.SaveUpdate()。

??? public ProjectsMapping()

??? {

??????? Table("Projects");

??????? LazyLoad();

??????? Id(x => x.ID).Column("ProjectID").GeneratedBy.Identity();

??????? References(x => x.User).Column("UserID").Cascade.None(); //它的操作不會涉及到Projects的操作

??????? Map(x => x.Name).Nullable();

??????? HasMany(x => x.Task).KeyColumn("ProjectID").LazyLoad().Cascade.SaveUpdate();

//在save或者update Projects的時候會連帶著修改Tasks

???? }

3.1.2.補充說明

一對多的映射,比起一對一來說還相對的簡單點,默認是延遲加載,如果項目中,有些地方,需要立即加載,我們也可以使用 FetchMode.Eager 來加載;

?

4. 多對多映射 HasManyToMany <>()

4.1. 定義支持的關聯屬性

ParentKeyColumn??????? 定義與A表關聯的字段名

ChildKeyColumn???????? 定義與B表關聯的字段名

Table????????????????? 關系表

4.1.1. 映射范例

比如電子商務站的訂單和產品的關系

  public ProductMap() 

  { 

Table("Products");

    Id(p => p.ProductID); 

    HasManyToMany<Order>(p => p.Orders) 

      .AsSet() 

      .LazyLoad() 

      .ParentKeyColumn("ProductID") 

      .ChildKeyColumn("OrderID") 

      .Table("OrderProduct"); 

 

    Map(p => p.CreateTime); 

    Map(p => p.Name); 

    Map(p => p.Price); 

  } 

  public OrderMap() 

  { 

Table("Orders");

    Id(o => o.OrderID).GeneratedBy.Identity(); 

    HasManyToMany<Product>(o => o.Products) 

      .AsSet() 

      .Not.LazyLoad() 

      .Cascade.All() 

      .ParentKeyColumn("OrderID") 

      .ChildKeyColumn("ProductID") 

      .Table("OrderProduct"); 

 

    Map(o => o.Price); 

    Map(o => o.State).CustomType<OrderState>(); 

    Map(o => o.Address); 

    Map(o => o.Coignee); 

    Map(o => o.CreateTime); 

    Map(o => o.Zip); 

    References<User>(o => o.User).Not.LazyLoad().Column("UserID"); //多個訂單屬于一個客戶

  } 

這里我們用了一個單獨的一個表OrderProduct來保存這個多對多關系

?

比如 一個Project會有有很多Product,同時一個Product也可能會在多個Project中

??? public ProjectsMapping()

??? {

??????? Table("Projects");

??????? LazyLoad();

??????? Id(x => x.ID).Column("ProjectID").GeneratedBy.Identity();

??????? References(x => x.User).Column("UserID").Cascade.None();

??????? Map(x => x.Name).Nullable();

??????? HasMany(x => x.Task).KeyColumn("ProjectID").LazyLoad().Cascade.SaveUpdate();

??????? HasManyToMany(x => x.Product).ParentKeyColumn("ProjectID").ChildKeyColumn("ProductID").Table("ProjectProduct");

??? }

??? public ProductMapping()

??? {

??????? Table("Product");

??????? Id(x => x.ID).Column("ProductID").GeneratedBy.Identity();

??????? Map(x => x.Name).Nullable();

??????? Map(x => x.Color).Nullable();

??????? HasManyToMany(x => x.Project).ParentKeyColumn("ProductID").ChildKeyColumn("ProjectID").Table("ProjectProduct");

??? }

4.1.2.補充說明

具體添加關聯的步驟如下:

(1)在映射的兩端同時添加HasManyToMany的關系這樣就形成了雙向的關聯關系

(2)指定映射的ParentKey和ChildKey,一般會將對象本身的ID指定為ParentKey,關聯對象的ID指定為ChildKey

(3)指定關聯關系的關系表,使用Table方法指定關聯表,如上示例的Table("ProjectProduct")。

?

?

以上只為突出一對一的雙向關聯映射,一對多的單向關聯和多對多的雙向關聯關系

轉載于:https://www.cnblogs.com/shy1766IT/p/4855176.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的Fluent NHibernate关系映射的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。