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:
Users.hbm.xml:
hibernate.cfg.xml:
特別說明一下在Users.hbm.xml中,有一個欄位叫Assembly,這邊要填寫的是主應用程式或者主dll檔的名稱。在專案設定的Build/Output中可以看到Assembly name。
撰寫完程式以後,請在hibernate.cfg.xml點右鍵,選擇Properties。
並將Copy to output directory設定為Always copy。
A. 因為Mac版的VS建立的專案,少引入了System.Data的參考,如下圖引用即可。
A. 因為我的Server主機不提供SSL連線,所以資料庫的連接字串中,要記得設定SslMode=none。
Q. Photon Server的Log訊息出現 NHibernate.MappingException: No persister for: NoliahFantasyServer.Model.Users。
Q. Photon Server的Log訊息出現 System.IO.FileNotFoundException: 無法載入檔案或組件 'Iesi.Collections, Version=4.0.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4' 或其相依性的其中之一。系統找不到指定的檔案。
好的,所有問題都解決了以後,執行程式看看吧,可以看見確實有插入資料進來了。以下有多筆資料的原因是我執行了很多遍在解決問題,然後就不自覺地插入了很多筆。
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並安裝。
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功能的話就可以很快的解決這個問題。
留言
張貼留言