Related Posts Plugin for WordPress, Blogger...

6-8 Database Manipulation By NHibernate

接下來要進展到資料庫抓取資料的部分嘍~我接下來會使用NHibernate這套ORM工具簡單的實作帳號註冊、登入等功能,NHibernate是原Java平台的Hibernate的.NET移植版本,以目前網路上可找到的多達30種以上的ORM工具中,NHibernate算是相當完整的。當然,要使用微軟的Enity Framework也可以,目前Enity Framework的更新速度相當快,而且也逐漸改善傳統ORM被人詬病的一些問題。網路上有許多討論,可以參考看看:

https://www.zhihu.com/question/26225619
https://www.zhihu.com/question/36296603
http://www.cnblogs.com/shy1766IT/p/5533320.html

不過本章就不討論太多NHiberante跟Enity Framework的比較啦。如果有人已經有自己愛用的ORM工具,或是只想單純寫SQL的話,就自己跳過這一章吧!

首先,我安裝了一個MySQL資料庫,建立一個資料庫名稱為NoliahFantasy,資料表名稱users,資料表欄位的設定有id, account, pwd, registerdate,如下圖。

由於MySQL的安裝與操作,在網路上已經有一堆教學了,我就不再贅述。推薦兩篇文章供大家參考:

Windows 上的 MySQL 安裝教學 (使用 MySQL Installer)
https://jerrynest.io/windows-mysql-installer/

簡單的 MySQL 使用教學
https://jerrynest.io/mysql-tutorial/

按照上述兩篇文章就可以完成安裝以及資料庫的建立了。接著,我們要在Server端的專案引入MySQL與NHibernate的dll檔。建議使用Visual Studio的Nuget功能,因為NHibernate的dll有使用到其他第三方的dll,通常自己手動的話容易有遺漏,我就曾經深受這問題所苦,弄了好久最後還是使用了Nuget。

對專案點右鍵,選擇Add/Add NuGet Packages。

然後在右上方的搜尋框中輸入nhibernate,搜尋到以後將第一個選項打勾並按下Add Package,同時你會看到他的Dependencies非常多。

安裝過程中可能會跳出要你同意License的按鈕,請按下Accept。

同理,使用上述相同方式搜尋mysql並安裝。

接著注意,你的專案要新增Mappings與Model資料夾,Mappings要有Users.hbm.xml,Model要有Users.cs,以及新增hibernate.cfg.xml文件。

Users.cs:該類別是ORM中用來對應Table的類別,我們會在Users.cs中定義一些屬性,其屬性會對應到Table的每個Column,當我們想操作Users的資料時,只需如OOP的方式操作Users類別即可,無需撰寫SQL語法。

Users.hbm.xml:由於nhibernate無法自動判斷你的Users.cs中有哪些屬性要對應到哪些Column,所以我們要撰寫.hbm.xml檔進行手動Mapping。

hibernate.cfg.xml:nhibernate的設定文件,設定你的資料庫版本、資料庫的Driver,以及連線字串。

以下提供三個檔案的原始碼:
Users.cs:

using System;
namespace NoliahFantasyServer.Model
{
    public class Users
    {
        public virtual int Id { get; set; }
        public virtual string Account { get; set;  }
        public virtual string Pwd { get; set; }
        public virtual DateTime Registerdate { get; set; }
    }
}


Users.hbm.xml:



  
    
        
            
        
        
        
        
    
  


hibernate.cfg.xml:



  
    NHibernate.Connection.DriverConnectionProvider
        
    NHibernate.Dialect.MySQL5Dialect
        
    NHibernate.Driver.MySqlDataDriver
        
    Server=localhost;Database=noliahfantasy;User ID=noliah;Password=noliah;SslMode=none
    
    true
  


特別說明一下在Users.hbm.xml中,有一個欄位叫Assembly,這邊要填寫的是主應用程式或者主dll檔的名稱。在專案設定的Build/Output中可以看到Assembly name。


撰寫完程式以後,請在hibernate.cfg.xml點右鍵,選擇Properties。

並將Copy to output directory設定為Always copy。

接著在Users.hbm.xml點右鍵,選擇Properties。

Build action選擇EmbeddedResource,若沒有選擇此選項的話,就不會將xml檔打包進dll檔,到時候Mapping就會出問題。麻煩的是以後有Mapping的xml都要記得調這個設定。

接著來修改Server的NoliahFantasyServer.cs程式嘍,程式碼都有註解了就自己看吧:


using System;
using System.IO;
using Photon.SocketServer;
using ExitGames.Logging;
using ExitGames.Logging.Log4Net;
using log4net.Config;
using NHibernate;
using NHibernate.Cfg;
using NoliahFantasyServer.Model;

namespace NoliahFantasyServer
{
    public class NoliahFantasyServer : ApplicationBase
    {

        public static readonly ILogger logger = LogManager.GetCurrentClassLogger();
        public NoliahFantasyServer()
        {
        }

        // 當Client端發出Request的時候
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            return new MyClientPeer(initRequest);
        }

        // Server端啟動的時候初始化
        protected override void Setup()
        {
            LoggerInit();
            ConnectToMySQL();
        }

        // Server端關閉的時候
        protected override void TearDown()
        {
        }

        void LoggerInit()
        {
            // 日誌初始化
            log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = 
                Path.Combine(this.ApplicationRootPath, "bin_Win64", "log");
            FileInfo loggerConfig = new FileInfo(Path.Combine(this.BinaryPath, "log4net.config"));
            if (loggerConfig.Exists)
            {
                // 設置使用log4net的Log功能
                LogManager.SetLoggerFactory(ExitGames.Logging.Log4Net.Log4NetLoggerFactory.Instance);
                // 讓log4net讀取config
                XmlConfigurator.ConfigureAndWatch(loggerConfig);
            }
            logger.Info("Setup Log4Net Compeleted!");
        }

        void ConnectToMySQL(){
            Configuration conf = new Configuration();
            // 解析hibernate.cfg.xml
            conf.Configure();
            // 輸入Application的名稱,並自動解析Mappings文件
            conf.AddAssembly(typeof(NoliahFantasyServer).Assembly);

            // 發起Session才能使用CRUD功能
            ISessionFactory sessionFactory = null;
            ISession session = null;
            try{
                sessionFactory = conf.BuildSessionFactory();
                // 發起Session
                session = sessionFactory.OpenSession();
                Users users = new Users(){
                    Account="abs", Pwd="dsa"
                };
                // 使用Save方法將Class傳給資料庫
                session.Save(users);

            }catch(Exception e){
                logger.Error(e);
            }finally{
                if(session != null){
                    session.Close();
                }
                if(sessionFactory != null){
                    sessionFactory.Close();
                }
            }
        }
    }
}


底下紀錄一下我在這階段遇到的一些疑難雜症,因為Visual Studio for Mac版本跟原本的VS不一樣,所以建立專案的時候常遇到很多在Windows開發時不會遇到的問題,大抵上都是因為少了些什麼。如果有這方面困惱的朋友,最快的解決方法就是直接跟Windows版本的VS專案進行比較吧,或者在Windows的VS建立專案以後再移植到Mac電腦上開發。

Q. 使用ISession的時候出現了The type 'DbConnection' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Data, Version=4.0.0.0, Culture=neutral, Public KeyToken=b77a5c561934e089'.

A. 因為Mac版的VS建立的專案,少引入了System.Data的參考,如下圖引用即可。


Q. Photon Server的Log訊息出現 MySql.Data.MySqlClient.MySqlException (0x80004005): The host localhost does not support SSL connections.

A. 因為我的Server主機不提供SSL連線,所以資料庫的連接字串中,要記得設定SslMode=none。

Q. Photon Server的Log訊息出現 NHibernate.MappingException: No persister for: NoliahFantasyServer.Model.Users。


A. 問題主因為找不到Mapping文件,很多可能性,比方說資料夾的名稱錯誤、hbm.xml的名稱錯誤,而我的問題原因是沒有將該文件嵌入dll檔中,如下圖進行Properties的設定即可。


Q. Photon Server的Log訊息出現 System.IO.FileNotFoundException: 無法載入檔案或組件 'Iesi.Collections, Version=4.0.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4' 或其相依性的其中之一。系統找不到指定的檔案。

A. 這一類的問題苦惱超久,總之就是缺少引入跟NHibernate相依賴的其他dll,所以使用NuGet功能的話就可以很快的解決這個問題。


好的,所有問題都解決了以後,執行程式看看吧,可以看見確實有插入資料進來了。以下有多筆資料的原因是我執行了很多遍在解決問題,然後就不自覺地插入了很多筆。

留言