天天看點

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語

最近在做項目的時候用到了NHibernate,使用它并不困難,但是很麻煩。如果我的資料庫有幾百張表如果想要一個個的映射豈不是很麻煩,是以這種情況下使用NHibernate就會很笨重,雖然這個ORM架構本身功能強大,但屬于重量級的在使用的時候太笨重了,是以需要在項目中改良。這時候就應運而生了FluentNHibernate,它是流暢版的NHibernate,支援所有的NHibernate功能,而且還封裝了配置檔案的映射功能,也就是說可以将映射使用C#代碼編寫,這樣在維護時就會很簡單。

       在沒有FluentNHibernate的情況下,如果使用NHibernate來做資料庫映射,那麼首先需要安裝NHibernate(也就是應用Nhibernate.dll),然後建立Nhibernate.cfg.xml資料庫配置檔案,然後建立映射檔案.xml,最後建立Session,直接對對象操作即可。雖然這樣做并不困難,但是很麻煩,想象下如果資料庫表有上百張,那使用這種方法映射不就很麻煩,笨重了嗎。

       那麼FluentNHibernate有什麼好處呢,它能夠省略建立映射檔案.xml,使用C#代碼編寫映射檔案,這樣做能在一定情況下簡化工作量,同時也便于對映射代碼進行修改,具體使用方法接下來會詳細讨論。

一、建立資料庫配置檔案

         首先建立一個資料庫的配置檔案,剛開始使用的話手動編寫太麻煩,這時候可以考慮使用自帶的配置檔案,在官網下載下傳後會有一個名為Configuration_Templates的檔案夾,裡面有不同資料庫的配置檔案,可以使用它的預設設定,但是需要将名稱改為Nhibernate.cfg.xml。這裡使用如下的配置:

[html] view plain copy print ?

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!-- This is the System.Data.dll provider for SQL Server -->  
  3. <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">  
  4.   <session-factory name="KaddzvoteNHibernateFactory">  
  5.     <property name="connection.driver_class">  
  6.       NHibernate.Driver.SqlClientDriver  
  7.     </property>  
  8.     <property name="connection.connection_string">  
  9.            Data Source=.;Initial Catalog=Mapping;Integrated Security=true;Pooling=True;Min Pool Size=20;Max Pool Size=60  
  10.     </property>  
  11.     <property name="dialect">  
  12.       NHibernate.Dialect.MsSql2005Dialect  
  13.     </property>  
  14.     <property name="current_session_context_class">thread_static</property>  
  15.     <property name="generate_statistics">true</property>  
  16.     <property name="proxyfactory.factory_class">NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate</property>  
  17.     <property name="query.substitutions">  
  18.       true 1, false 0, yes 'Y', no 'N'  
  19.     </property>  
  20.    <!--配置是否顯示sql語句,true代表顯示-->  
  21.     <property name="show_sql">true</property>  
  22.   </session-factory>  
  23. </hibernate-configuration>  
<?xml version="1.0" encoding="utf-8"?>
<!-- This is the System.Data.dll provider for SQL Server -->
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory name="KaddzvoteNHibernateFactory">
    <property name="connection.driver_class">
      NHibernate.Driver.SqlClientDriver
    </property>
    <property name="connection.connection_string">
           Data Source=.;Initial Catalog=Mapping;Integrated Security=true;Pooling=True;Min Pool Size=20;Max Pool Size=60
    </property>
    <property name="dialect">
      NHibernate.Dialect.MsSql2005Dialect
    </property>
    <property name="current_session_context_class">thread_static</property>
    <property name="generate_statistics">true</property>
    <property name="proxyfactory.factory_class">NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate</property>
    <property name="query.substitutions">
      true 1, false 0, yes 'Y', no 'N'
    </property>
   <!--配置是否顯示sql語句,true代表顯示-->
    <property name="show_sql">true</property>
  </session-factory>
</hibernate-configuration>
           

二、建立實體

        NHibernate的基本映射和Hibernate是完全相同的,有關基本的映射這裡不再詳細的讨論,可以翻閱筆者的前幾篇文章。下面自己做了一個小的項目Demo,示範如何使用NHibernate建立一個資料庫的映射,具體的資料庫結構圖如下:

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語

       上圖的資料庫結構圖中涵蓋了基本的映射關系,在實際的項目中也就是上面出現的幾種基本的關系,其中涵蓋了一對一、多對一、多對多的關聯關系,接下來将會使用FluentNHibernate來實作基本的映射關系。

  2.1 建立實體

        添加完配置檔案後使用第三方工具将資料庫表導出為實體對象,也就是添加資料庫表的實體對象。添加完成後繼續添加資料庫的映射類,添加映射類時需要繼承NHibernate的ClassMap<T>類,将資料庫實體放置到對象内部,這樣在映射時能夠直接使用,它使用的是泛型來實作的。資料庫表的實體如下代碼:

[csharp] view plain copy print ?

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Collections.ObjectModel;  
  4. using System.Linq;  
  5. using System.Text;  
  6. using System.Threading.Tasks;  
  7. using FluentNHibernate.Automapping;  
  8. using FluentNHibernate.Conventions;  
  9. using NHibernate;  
  10. using NHibernate.Collection.Generic;  
  11. namespace ClassLibrary1.mapping  
  12. {  
  13.     public abstract class Entity  
  14.     {  
  15.         virtual public int ID { get; set; }  
  16.     }  
  17.     public class User : Entity  
  18.     {  
  19.         virtual public string Name { get; set; }  
  20.         public virtual string No { get; set; }  
  21.         public virtual UserDetails UserDetails { get; set; }  
  22.     }  
  23.     public class Project : Entity  
  24.     {  
  25.         public Project()  
  26.         {  
  27.             Task=new List<Task>();  
  28.             Product=new List<Product>();  
  29.         }  
  30.         public virtual string Name { get; set; }  
  31.         public virtual User User { get; set; }  
  32.         public virtual IList<Product> Product { get; set; }   
  33.         public virtual IList<Task> Task{get;protected set; }  
  34.     }  
  35.     public class Product : Entity  
  36.     {  
  37.         public Product()  
  38.         {  
  39.             Project=new List<Project>();  
  40.         }  
  41.         public virtual IList<Project> Project { get; set; }   
  42.         public virtual string Name { get; set; }  
  43.         public virtual string Color { get; set; }  
  44.     }  
  45.     public class Task : Entity  
  46.     {  
  47.         public virtual string Name { get; set; }  
  48.         public virtual Project Project { get; set; }  
  49.     }  
  50.     public class UserDetails : Entity  
  51.     {  
  52.         public virtual User User { get; set; }  
  53.         public virtual int Sex { get; set; }  
  54.         public virtual int Age { get; set; }  
  55.         public virtual DateTime BirthDate { get; set; }  
  56.         public virtual decimal Height { get; set; }  
  57.     }  
  58. }  
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FluentNHibernate.Automapping;
using FluentNHibernate.Conventions;
using NHibernate;
using NHibernate.Collection.Generic;


namespace ClassLibrary1.mapping
{
    
    public abstract class Entity
    {
        virtual public int ID { get; set; }
    }

    public class User : Entity
    {
        virtual public string Name { get; set; }
        public virtual string No { get; set; }

        public virtual UserDetails UserDetails { get; set; }
    }

    public class Project : Entity
    {
        public Project()
        {
            Task=new List<Task>();
            Product=new List<Product>();
        }

        public virtual string Name { get; set; }
        public virtual User User { get; set; }

        public virtual IList<Product> Product { get; set; } 
        public virtual IList<Task> Task{get;protected set; }

    }

    public class Product : Entity
    {
        public Product()
        {
            Project=new List<Project>();
        }

        public virtual IList<Project> Project { get; set; } 
        public virtual string Name { get; set; }
        public virtual string Color { get; set; }
    }

    public class Task : Entity
    {
        public virtual string Name { get; set; }
        public virtual Project Project { get; set; }
    }

    public class UserDetails : Entity
    {
        public virtual User User { get; set; }
        public virtual int Sex { get; set; }
        public virtual int Age { get; set; }
        public virtual DateTime BirthDate { get; set; }
        public virtual decimal Height { get; set; }
    }
}
           

三、映射詳解

        在添加映射檔案時需要繼承FluentNHibernate的ClassMap<T>類,然後在類的構造函數中添加映射的方法,具體的方法是使用的lamuda表達式來映射的,方法的名稱跟配置檔案的名稱基本一緻,書寫也很友善,接下來将會拆分映射來詳細講解FluentNHibernate的Mapping使用方法。

  3.1 一對一映射

        首先來看看一對一的映射關系,使用者和使用者資訊表在實際中是一對一的關系,這兩個表之間是通過使用UserID來互相關聯的,它們有一個共同的ID,在插入Users表的同時也要寫入UserDetails表,是以需要添加一對一的限制關系,具體的在Users和UsersDetails兩表的映射方法如下代碼:

[csharp] view plain copy print ?

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
  1. public class UsersMapping : ClassMap<User>  
  2. {  
  3.     public UsersMapping()  
  4.     {  
  5.         Table("Users");  
  6.         LazyLoad();  
  7.         Id(x => x.ID).Column("UserID").GeneratedBy.Identity();  
  8.         HasOne(x => x.UserDetails).Cascade.All().PropertyRef("User");  
  9.         Map(x => x.Name).Nullable();  
  10.         Map(x => x.No).Nullable();  
  11.     }  
  12. }  
public class UsersMapping : ClassMap<User>
{
    public UsersMapping()
    {
        Table("Users");
        LazyLoad();
        Id(x => x.ID).Column("UserID").GeneratedBy.Identity();
        HasOne(x => x.UserDetails).Cascade.All().PropertyRef("User");
        Map(x => x.Name).Nullable();
        Map(x => x.No).Nullable();

    }
}
           

        Note:FluentNHibernate在映射時有很多種映射方法,比如Cascade它是指該對象在進行操作時關聯到的子對象的操作類型,上面指定了All說明所有的操作都會關聯到子表,還有SaveUpdate在添加和更新時關聯子表,另外還有None類型不推薦使用此類型因為會出現很多問題。

        UserDetails的映射中的主鍵ID是繼承自User類的是以在指定ID時需要添加Foreign外鍵關聯的屬性名,内部的參數一定要是UserDetails的屬性名。

[csharp] view plain copy print ?

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
  1. public class UserDetailsMapping : ClassMap<UserDetails>  
  2. {  
  3.     public UserDetailsMapping()  
  4.     {  
  5.         Table("UserDetails");  
  6.         LazyLoad();  
  7.         Id(x => x.ID).Column("UserID").GeneratedBy.Foreign("User");  
  8.         Map(x => x.Height).Nullable();  
  9.         Map(x => x.Age).Nullable();  
  10.         Map(x => x.Sex).Nullable();  
  11.         Map(x => x.BirthDate).Nullable();  
  12.         HasOne(x => x.User).Cascade.All();  
  13.     }  
  14. }  
public class UserDetailsMapping : ClassMap<UserDetails>
{
    public UserDetailsMapping()
    {
        Table("UserDetails");
        LazyLoad();
        Id(x => x.ID).Column("UserID").GeneratedBy.Foreign("User");
        Map(x => x.Height).Nullable();
        Map(x => x.Age).Nullable();
        Map(x => x.Sex).Nullable();
        Map(x => x.BirthDate).Nullable();
        HasOne(x => x.User).Cascade.All();
    }
}
           

       使用測試方法檢視映射結果,具體的測試方法如下:

[csharp] view plain copy print ?

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
  1. using System;  
  2. using System.Collections.Generic;  
  3. using ClassLibrary1.mapping;  
  4. using FluentNHibernate.Testing;  
  5. using ClassLibrary1;  
  6. using NHibernate;  
  7. using NUnit.Framework;  
  8. namespace UnitTestProject1  
  9. {  
  10.     [TestFixture]  
  11.     public class UnitTest1:NHConfig  
  12.     {  
  13.         [Test]  
  14.         public void TestUsers_UserDetails()  
  15.         {  
  16.             //get user from database  
  17.             User user1 = Session.Load<User>(1);  
  18.             //save the User data  
  19.             Session.Transaction.Begin();  
  20.             User user=new User()  
  21.             {  
  22.                 Name = "Jack",  
  23.                 No = "12321"  
  24.             };  
  25.             UserDetails userDetails=new UserDetails()  
  26.             {  
  27.                 Age = 12,  
  28.                 BirthDate = DateTime.Now.Date,  
  29.                 Height = 240,  
  30.                 Sex = 1  
  31.             };  
  32.             user.UserDetails = userDetails;  
  33.             userDetails.User = user;  
  34.             Session.Save(user);  
  35.             Session.Transaction.Commit();  
  36.         }  
  37.     }  
  38. }  
using System;
using System.Collections.Generic;
using ClassLibrary1.mapping;
using FluentNHibernate.Testing;
using ClassLibrary1;
using NHibernate;
using NUnit.Framework;
namespace UnitTestProject1
{
    [TestFixture]
    public class UnitTest1:NHConfig
    {
        [Test]
        public void TestUsers_UserDetails()
        {
            //get user from database
            User user1 = Session.Load<User>(1);

            //save the User data
            Session.Transaction.Begin();
            User user=new User()
            {
                Name = "Jack",
                No = "12321"
            };
            UserDetails userDetails=new UserDetails()
            {
                Age = 12,
                BirthDate = DateTime.Now.Date,
                Height = 240,
                Sex = 1
            };
            user.UserDetails = userDetails;
            userDetails.User = user;
            Session.Save(user);
            Session.Transaction.Commit();
        }
    }
}
           

       在get和save對象的地方添加斷點,Debug運作測試就會看到執行的結果。

  3.2 一對多/多對一

        一對多和多對一是相對而言的正如上例中的Projects和Tasks類似,一個Projects有多個Tasks,反過來說就是多個Tasks可能會對應一個Projects是以有時一對多的關系也就是多對一的關系,隻不過是一種特殊的多對一。這裡的多對一比較特殊,常見的多對一的關系比如學生和班級的關系,多個學生屬于一個班級。

         一對多的映射方法和一對一的映射方法其實很多地方是類似的,隻不過一對多的關系裡面要添加一個外鍵引用關系,然後在多的一端添加一個外鍵,在一的一端添加HasMany,映射到Projects和Tasks中就是在Tasks(多)中添加Project的外鍵。

   3.2.1 映射

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

[csharp] view plain copy print ?

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
  1. public class TasksMappping : ClassMap<ClassLibrary1.mapping.Task>  
  2. {  
  3.     public TasksMappping()  
  4.     {  
  5.         Table("Tasks");  
  6.         LazyLoad();  
  7.         Id(x => x.ID).Column("TaskID").GeneratedBy.Identity();  
  8.         References(x => x.Project).Nullable().Column("ProjectID").Cascade.None();  
  9.         Map(x => x.Name).Nullable();  
  10.     }  
  11. }  
public class TasksMappping : ClassMap<ClassLibrary1.mapping.Task>
{
    public TasksMappping()
    {
        Table("Tasks");
        LazyLoad();
        Id(x => x.ID).Column("TaskID").GeneratedBy.Identity();
        References(x => x.Project).Nullable().Column("ProjectID").Cascade.None();
        Map(x => x.Name).Nullable();
    }
}
           

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

[csharp] view plain copy print ?

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
  1. public class ProjectsMapping:ClassMap<Project>  
  2. {  
  3.     public ProjectsMapping()  
  4.     {  
  5.         Table("Projects");  
  6.         LazyLoad();  
  7.         Id(x => x.ID).Column("ProjectID").GeneratedBy.Identity();  
  8.         References(x => x.User).Column("UserID").Cascade.None();  
  9.         Map(x => x.Name).Nullable();  
  10.         HasMany(x => x.Task).KeyColumn("ProjectID").LazyLoad().Cascade.SaveUpdate();  
  11.      }  
  12. }  
public class ProjectsMapping:ClassMap<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();
     }
}
           

       Note:TasksMapping中的外鍵關系使用的是Cascade.None這說明它的操作不會涉及到Projects的操作,但是ProjectsMapping中使用了Cascade.SaveUpdate()方法是以在save或者update Projects的時候會連帶着修改Tasks。

   3.2.2 Unit Test

      編寫單元測試代碼如下:

[csharp] view plain copy print ?

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
  1. [Test]  
  2. public void TestOneToMany()  
  3. {  
  4.     Project project = Session.Get<Project>(15);  
  5.     //save the User data  
  6.     Session.Transaction.Begin();  
  7.     Task task = new Task()  
  8.     {  
  9.         Name ="create",  
  10.         Project = project  
  11.     };  
  12.     Session.Save(task);  
  13.     Session.Transaction.Commit();  
  14.     Task task1 = Session.Get<Task>(1);  
  15. }  
[Test]
public void TestOneToMany()
{
    Project project = Session.Get<Project>(15);

    //save the User data
    Session.Transaction.Begin();
    Task task = new Task()
    {
        Name ="create",
        Project = project
    };
    Session.Save(task);
    Session.Transaction.Commit();

    Task task1 = Session.Get<Task>(1);
}
           

  執行檢視結果:

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語

       這裡使用的一對多的關聯隻是單向的關聯,在關聯中不僅有單向的另外還有雙向關聯,具體使用方法這裡不再詳細讨論,有興趣學習的話可以翻閱筆者的前篇文章有關Hibernate的關聯關系。

  3.3 多對多

        上文詳細讨論了一對一、多對一/一對多的關系,使用FluentNHibernate來映射這種關系就很簡單了,最後繼續讨論多對多的關系,多對多的關系在使用的時候更類似于一對一的關系,因為它屬于雙向的關聯,是以需要在關聯的兩端同時添加HasManyToMany的映射方法,另外反應到資料庫中這其實是需要建立關聯表,利用第三張表來維護雙向的關系,具體的使用方法如下執行個體。

    3.3.1 映射

        在項目中常見的多對多的關系有很多,比如本例中使用的Product和Project的關系,一個Project會有有很多Product,同時一個Product也可能會在多個Project中,它們之間就形成了多對多的關聯關系。反映到映射關系中,代碼如下:

[csharp] view plain copy print ?

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
  1. public class ProjectsMapping:ClassMap<Project>  
  2. {  
  3.     public ProjectsMapping()  
  4.     {  
  5.         Table("Projects");  
  6.         LazyLoad();  
  7.         Id(x => x.ID).Column("ProjectID").GeneratedBy.Identity();  
  8.         References(x => x.User).Column("UserID").Cascade.None();  
  9.         Map(x => x.Name).Nullable();  
  10.         HasMany(x => x.Task).KeyColumn("ProjectID").LazyLoad().Cascade.SaveUpdate();  
  11.         HasManyToMany(x => x.Product).ParentKeyColumn("ProjectID").ChildKeyColumn("ProductID").Table("ProjectProduct");  
  12.     }  
  13. }  
  14. public class ProductMapping : ClassMap<Product>  
  15. {  
  16.     public ProductMapping()  
  17.     {  
  18.         Table("Product");  
  19.         Id(x => x.ID).Column("ProductID").GeneratedBy.Identity();  
  20.         Map(x => x.Name).Nullable();  
  21.         Map(x => x.Color).Nullable();  
  22.         HasManyToMany(x => x.Project).ParentKeyColumn("ProductID").ChildKeyColumn("ProjectID").Table("ProjectProduct");  
  23.     }  
  24. }  
public class ProjectsMapping:ClassMap<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 class ProductMapping : ClassMap<Product>
{
    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");
    }
}
           

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

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

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

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

  3.3.2  Unit Test

       最後添加一個測試方法來檢視映射的結果,是否實作了多對多的映射關系,具體測試方法如下。

[csharp] view plain copy print ?

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語
  1. [Test]  
  2. public void TestManyToMany()  
  3. {  
  4.     Session.Transaction.Begin();  
  5.     //get the Project  
  6.     ICriteria query = Session.CreateCriteria<Project>();  
  7.     IList<Project> projects = query.List<Project>();  
  8.     //create the Product  
  9.     Product product=new Product()  
  10.     {  
  11.         Name = "Product1",  
  12.         Color = "Red"  
  13.     };  
  14.     product.Project = projects;  
  15.     Session.Save(product);  
  16.     Session.Transaction.Commit();  
  17. }  
[Test]
public void TestManyToMany()
{
    Session.Transaction.Begin();
    //get the Project
    ICriteria query = Session.CreateCriteria<Project>();
    IList<Project> projects = query.List<Project>();

    //create the Product
    Product product=new Product()
    {
        Name = "Product1",
        Color = "Red"
    };
    product.Project = projects;
    Session.Save(product);
    Session.Transaction.Commit();
}
           

         Debug運作測試方法,運作到get projects處檢視projects所擷取的對象資訊如下圖:

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語

         從上圖可以看出已經擷取到了與projects相關聯的Product,這就是多對多的關系,在擷取projects時同時擷取了與它關聯的Products,如果這裡使用Lazyload方式的話就不會擷取所有的資訊,是以要根據具體的情況而定。

        繼續運作測試,成功執行。

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語

       檢視資料庫發現資料已經成功添加,如下圖:

FluentNHibernate之基本映射詳解一、建立資料庫配置檔案二、建立實體三、映射詳解結語

結語

         本文主要讨論了FluentNHibernate的基本使用技巧,突出讨論了一對一的雙向關聯映射,一對多的單向關聯和多對多的雙向關聯關系,它們使用相當簡單,因為有了FluentNHibernate,隻需要了解關聯的規則就可以了,從資料模型到對象模型真的就很簡單了。

         雖然使用FluentNHibernate在一定程度上減少了編寫代碼,但是并不能真正的解決代碼備援的繁瑣問題,可否有一中不需要編寫Mapping代碼的方法來實作映射關系呢?是的FluentNHibernate還封裝了一種AutoMapping方式來映射對象,是一種自動映射的方法,隻需要繼承實作資料庫表到對象的轉換規則就可以了,具體的實作方法将會在下篇文章中詳細讨論。