這些年在作AgileEAS.NET SOA 中間件平臺的推廣、技術諮詢服務過程之中,特別是針對咱們最熟悉的醫療行業應用之中,針對大數據分析,大併發性能的需求,咱們也在慢慢的引用NoSQL技術來知足數據分析與性能等多方面的須要,也進一步完善咱們的SOA基石架構風格:php
在早些年,對NoSQL不是很瞭解這前,後端數據存儲都是存儲的單一的關係數據庫之上,可是在不少時間,這並非最優的,好比在醫療用戶之中針對一個病人的相關數據展現,及相關性分析,關於數據庫就不是最優的,另一個,電子病歷系統的之中的結構化/半結構化病歷文檔的存儲、檢索,以及更高級的應用,結構化病歷數據挖掘,以前使用關係數據庫存儲或者使用文件存儲,很難發揮病歷數據的科研和統計、分析需求。git
在目前咱們的醫療信息化應用之中,咱們針對這兩部分數據都引入了NoSQL存儲,針對住院患者的領域相關性數據==》即病人聚合根對象相關數據,咱們即在關係數據庫以多表存儲病人數據以及病人相關的醫囑、費用、檢驗、檢查、護理等相關信息,同時咱們也在NoSQL數據庫存儲患者的聚合根對象:程序員
在NoSQL數據庫之中的存儲:github
另外在電子病歷應用之中,病歷文檔也是直接存入NoSQL之中。mongodb
在接觸巨杉數據庫以前,咱們一直使用MongoDB這款NoSQL產品,這是一款廣爲人知的NoSQL產品,使用者衆多,C#的驅動也很是完善,案例也比比皆時。數據庫
巨杉數據庫是國人開發的一款企業級NoSQL數據庫,目前已開源,官網http://www.sequoiadb.com/。
初次瞭解到巨杉(sequoiadb)數據仍是源於一個客戶,由於咱們項目一直使用MongoDB,客戶就向咱們提到巨杉(sequoiadb)數據庫,說國內有人開發了這麼一個NoSQL數據庫,而且在平安銀行有過成功應用,而且由於是國人開發,因此應該相比較MongoDB,應該能獲得官方的支持,客戶也和巨杉(sequoiadb)官方的人有過接觸,官方也答應能夠作一些支持。後端
根據網上所公開的一些信息,巨杉(sequoiadb)數據庫和MongoDB很是的接近,都是文檔型數據庫,一樣的設計思路,集合和文檔,一樣的文檔格式,Json/Bson。
根據最近一段時間的瞭解和完善C#驅動的過程來講,相對MongoDB,巨杉(sequoiadb)提供了更加方便的圖形化部署和簡單的Web管理界面:架構
如下是SequoiaDB與MongoDB及其餘NoSQL數據的功能對比:併發
比較特別是的SequoiaDB支持事務和SQL語法,固然了,這兩點在目前狀況下咱們都使用使用過。運維
SequoiaDB官方提供C、C++、JAVA、C#、php、Python驅動以及REST架構風格的接口,據官方的說法是Java的驅動很成熟,可是C#的驅動很簡單,只能支持最基本的Bson格式的接口,以下代碼:
// Insert BsonDocument insertor = new BsonDocument(); insertor.Add("Last Name", "Lin"); insertor.Add("First Name", "Hetiu"); insertor.Add("Address", "SYSU"); BsonDocument sInsertor = new BsonDocument(); sInsertor.Add("Phone", "10086"); sInsertor.Add("EMail", "hetiu@yahoo.com.cn"); insertor.Add("Contact", sInsertor); ObjectId insertID = (ObjectId)coll.Insert(insertor); Assert.IsNotNull(insertID); // Update DBQuery query = new DBQuery(); BsonDocument updater = new BsonDocument(); BsonDocument matcher = new BsonDocument(); BsonDocument modifier = new BsonDocument(); updater.Add("Age", 25); modifier.Add("$set", updater); matcher.Add("First Name", "Hetiu"); query.Matcher = matcher; query.Modifier = modifier; coll.Update(query); // Query DBCursor cursor = coll.Query(query); Assert.IsNotNull(cursor); BsonDocument bson = cursor.Next(); Assert.IsNotNull(bson); Assert.IsTrue(bson["First Name"].AsString.Equals("Hetiu")); Assert.IsTrue(bson["Age"].AsInt32.Equals(25)); // Delete BsonDocument drop = new BsonDocument(); drop.Add("Last Name", "Lin"); coll.Delete(drop); query.Matcher = drop; cursor = coll.Query(query); Assert.IsNotNull(cursor); bson = cursor.Next(); Assert.IsNull(bson);
集合查詢:
for (int i = 0; i < 10; ++i) { string date = DateTime.Now.ToString(); BsonDocument insertor = new BsonDocument(); insertor.Add("operation", "Query"); insertor.Add("date", date); coll.Insert(insertor); } BsonDocument matcher = new BsonDocument(); DBQuery query = new DBQuery(); matcher.Add("operation", "Query"); query.Matcher = matcher; query.ReturnRowsCount = 5; query.SkipRowsCount = 5; DBCursor cursor = coll.Query(query); Assert.IsNotNull(cursor); int count = 0; while (cursor.Next() != null) { ++count; BsonDocument bson = cursor.Current(); Assert.IsNotNull(bson); } Assert.IsTrue(count == 5);
官方的代碼有點簡單,這不符合咱們寫代碼的風格,目前業務系統大量的使用對象操做和Linq處理,原始的Bson接口,這個不科學。
即然官方的驅動太簡單,不支持對象處理,也不支持Linq,很不科學,那麼應該怎麼辦呢,其實第一個觀點固然是放棄,咱們本來使用MongoDB跑的好好的,爲何要給本身找事呢,可是出於項目運維的觀點,以及支持國人產品的想法,最終決定本身完善和寫一個。
那麼如何來寫呢,固然是他山之石,能夠攻玉,由於以前作MongoDB開發,原始的驅動配置咱們的ORM跑起來也有一些問題,最先咱們使用的非MongoDB的官方驅動,而是第三方驅動samus,不支持Decimal類型,可是咱們項目之中有大量的Decimal類型,那麼辦呢,修改驅動,後來咱們又換成了MongoDB的官方驅動,由於XmlIgnore標籤和Id映射的問題也認真的讀過MongoDB的官方驅動,對MongoDB的C#驅動比較熟悉。
因此完善SequoiaDB的C#的思路就變成告終合SequoiaDB的原始驅動和MongoDB的官方驅動,提供一個相似於MongoDB驅動的操做風格的驅動,在SequoiaDB驅動的基礎上提供了,直接操做C#對象的方案和支持Linq進行查詢、修改、刪除的功能。
經本人完善修改以後的驅動的操做風格以下:
Sequoiadb sdb = new Sequoiadb("192.168.23.57:50000"); sdb.Connect("", ""); //求集合空間。 var cs = sdb.GetCollecitonSpace("dbo"); //求集合。 var coll = cs.GetCollection<HFareDetail>(); //執行數據插入。 List<HFareDetail> vList =null; using (AgileHIS.Entities.DbEntities db = new AgileHIS.Entities.DbEntities()) { vList = db.HFareDetails.ToList(); //插入。 foreach (var item in vList) { coll.Insert(item); } System.Console.WriteLine(string.Format("insert {0} records", vList.Count)); System.Console.ReadLine(); } //按條件修改某一條數據的幾個屬性值。 var v1 = vList.FirstOrDefault(); v1.Name = string.Empty; v1.Cash = decimal.Zero; coll.Update(v1, p => p.ID == v1.ID); //按條件指量修改,指定某幾個必,其餘屬性所有置空。 coll.Update(p => new HFareDetail { Cash = decimal.Zero, Name = string.Empty, Price = decimal.Zero }, p => p.ChargeTime >DateTime.Now.AddDays(-1)); //依據條件刪除 coll.Delete(p => p.ChargeTime > DateTime.Now.AddDays(-1)); //求Count int count = coll.AsQueryable<HFareDetail>() .Where(p => p.SourceID==0) .Count(); //Linq查詢Take\Skip。 var vList2 = coll.AsQueryable<HFareDetail>() .Where(p => p.CreateTime > DateTime.Now.Date.AddMonths(-12)) .Skip(10).Take(1000) .ToList(); System.Console.WriteLine(string.Format("query {0} records", vList.Count)); //Linq查詢過。 var vFare = coll.AsQueryable<HFareDetail>() .Where(p => p.CreateTime > DateTime.Now.Date.AddMonths(-12)) .FirstOrDefault(); System.Console.WriteLine(vFare); //Linq\聚合運算,目前由於測試驅動報錯,暫未實現 var sum = coll.AsQueryable<HFareDetail>() .Where(p => p.CreateTime > DateTime.Now.Date.AddMonths(-12)) .Sum(p => p.Cash); System.Console.ReadLine();
看看,代碼是否是很清爽,很方便了呢,沒有了bson,只有對象,Linq。
AgileEAS.NET SOA以前只支持MongoDB,最近要支持SequoiaDB,咱們就得考慮對原有代碼的兼容,或者說,更但願本身的醫療系統可以在業務上同時支持MongoDB和SequoiaDB,達到使用環境之中不論是選擇MongoDB仍是選擇SequoiaDB都是一樣的代碼,爲此,咱們在AgileEAS.NET SOA中間件之中定義了一個IStructDbProvider接口:
using System; using System.Collections.Generic; using System.Linq.Expressions; namespace EAS.Data { /// <summary> /// 結構化數據庫提供者接口定義。 /// </summary> /// <remarks> /// 爲AgileEAS.NET SOA 中間件NoSQL數據訪問提供標準接口定義。 /// </remarks> public interface IStructDbProvider { /// <summary> /// 打開鏈接。 /// </summary> void Connect(); /// <summary> /// 關閉鏈接。 /// </summary> void Close(); /// <summary> /// 鏈接是否打開。 /// </summary> bool IsOpen { get; } /// <summary> /// 對象插入。 /// </summary> /// <typeparam name="T">對象類型。</typeparam> /// <param name="item">對象實例。</param> void Insert<T>(T item) where T : class; /// <summary> /// 對象批量插入。 /// </summary> /// <typeparam name="T">對象類型。</typeparam> /// <param name="items">對象實例。</param> void InsertBatch<T>(System.Collections.Generic.IEnumerable<T> items) where T : class; /// <summary> /// 根據條件執行更新操做。 /// </summary> /// <typeparam name="T">對象類型。</typeparam> /// <param name="updater">更新表達式。</param> /// <param name="func">查詢條件。</param> void Update<T>(Expression<Func<T, T>> updater, Expression<Func<T, bool>> func) where T : class; /// <summary> /// 根據條件執行更新操做。 /// </summary> /// <typeparam name="T">對象類型。</typeparam> /// <param name="item">更新對象。</param> /// <param name="func">查詢條件。</param> void Update<T>(T item, System.Linq.Expressions.Expression<Func<T, bool>> func) where T : class; /// <summary> /// 根據條件刪除對象。 /// </summary> /// <typeparam name="T">對象類型。</typeparam> /// <param name="func">條件表達式。</param> void Delete<T>(Expression<Func<T, bool>> func) where T : class; /// <summary> /// 求出Linq查詢表達式。 /// </summary> /// <typeparam name="T">對象類型。</typeparam> /// <returns>對象表達式包裝。</returns> IQueryableWarp<T> Linq<T>() where T : class; /// <summary> /// 根據條件查詢數制。 /// </summary> /// <typeparam name="T">對象類型。</typeparam> /// <param name="where">條件。</param> /// <param name="skip">跳過記錄數。</param> /// <param name="take">取記錄數。</param> /// <returns>查詢結構。</returns> List<T> List<T>(Expression<Func<T, bool>> where, int skip, int take) where T : class; /// <summary> /// 根據條件求單條記錄。 /// </summary> /// <typeparam name="T">對象類型。</typeparam> /// <param name="where">條件。</param> /// <returns>對象實例。</returns> T Single<T>(Expression<Func<T, bool>> where) where T : class; } }
IStructDbProvider字面意思即爲結構化數據訪問提供者接口,本接口定義在EAS.MicroKernel.dll程序集之中,AgileEAS.NET SOA中間件同時提供了針對SequoiaDB和MongoDB數據庫的IStructDbProvider實現,EAS.Data.MongoDbProvider和EAS.Data.SequoiaDbProvider,這兩個實現類定義在EAS.Data.NoSQL.dll程序集之中。
由於統計使用了IStructDbProvider接口,咱們針對SequoiaDB和MongoDB的操做處理就統計成了以下代碼:
var vContainer = EAS.Context.ContextHelper.GetContext().Container; var dbProvider = vContainer.GetComponentInstance("StructDbProvider") as IStructDbProvider; //執行數據插入。 List<HFareDetail> vList = null; using (AgileHIS.Entities.DbEntities db = new AgileHIS.Entities.DbEntities()) { vList = db.HFareDetails.ToList(); //插入。 foreach (var item in vList) { dbProvider.Insert<HFareDetail>(item); } System.Console.WriteLine(string.Format("insert {0} records", vList.Count)); System.Console.ReadLine(); } //按條件修改某一條數據的幾個屬性值。 var v1 = vList.FirstOrDefault(); v1.Name = string.Empty; v1.Cash = decimal.Zero; dbProvider.Update<HFareDetail>(v1, p => p.ID == v1.ID); //按條件指量修改,指定某幾個必,其餘屬性所有置空。 dbProvider.Update<HFareDetail>(p => new HFareDetail { Cash = decimal.Zero, Name = string.Empty, Price = decimal.Zero }, p => p.ChargeTime > DateTime.Now.AddDays(-1)); //依據條件刪除 dbProvider.Delete<HFareDetail>(p => p.ChargeTime > DateTime.Now.AddDays(-1)); //求Count using (var queryWarp = dbProvider.Linq<HFareDetail>()) { int count = queryWarp.Queryable .Where(p => p.SourceID == 0) .Count(); //Linq查詢Take\Skip。 var vList2 = queryWarp.Queryable .Where(p => p.CreateTime > DateTime.Now.Date.AddMonths(-12)) .Skip(10).Take(1000) .ToList(); System.Console.WriteLine(string.Format("query {0} records", vList.Count)); //Linq查詢過。 var vFare = queryWarp.Queryable .Where(p => p.CreateTime > DateTime.Now.Date.AddMonths(-12)) .FirstOrDefault(); System.Console.WriteLine(vFare); //Linq\聚合運算,目前由於測試驅動報錯,暫未實現 var sum = queryWarp.Queryable .Where(p => p.CreateTime > DateTime.Now.Date.AddMonths(-12)) .Sum(p => p.Cash); } System.Console.ReadLine();
具體是使用SequoiaDB仍是使用MongoDB由系統配置文件來決定,使用SequoiaDB:
<!--StructDb/SequoiaDb--> <object name="StructDbProvider" assembly="EAS.Data.NoSQL" type="EAS.Data.SequoiaDbProvider" LifestyleType="Thread"> <property name="ConnectionString" type="string" value="192.168.23.57:50000"/> <property name="UserName" type="string" value=""/> <property name="Password" type="string" value=""/> <property name="CollectionSpace" type="string" value="his"/> </object>
使用MongoDB。
<!--StructDb/MongoDb--> <object name="StructDbProvider" assembly="EAS.Data.NoSQL" type="EAS.Data.MongoDbProvider" LifestyleType="Thread"> <property name="ConnectionString" type="string" value="mongodb://sa:sa@127.0.0.1:2222/his"/> <property name="DbName" type="string" value="his"/> </object>
本人爲SequoiaDB所寫的C#驅動,已提交託管到github,項目地址https://github.com/agilelab/SequoiaDB.Charp,歡迎你們下載,也歡迎你們和本人一道完善本驅動。
敏捷軟件工程實驗室,是一家研究、推廣和發展新技術,並致力於提供具備自主知識產權的業務基礎平臺軟件,以及基於業務基礎平臺開發的管理軟件的專業軟件提供商。主要業務是爲客戶提供軟件企業研發管理解決方案、企業管理軟件開發,以及相關的技術支持,管理及技術諮詢與培訓業務。
AgileEAS.NET SOA中間件平臺自2004年秋呱呱落地一來,我就一直在逐步完善和改進,也被應用於保險、醫療、電子商務、房地產、鐵路、教育等多個應用,但一直都是以我我的在推廣,2010年由於我辭職休息,我就想到把AgileEAS.NET推向市場,讓更多的人使用。
個人技術團隊成員都是合做多年的老朋友,由於這個平臺是免費的,因此也沒有什麼收入,都是由程序員的那種理想與信念堅持,在此我感謝一塊兒奮鬥的朋友。
AgileEAS.NET網站:http://www.agileeas.net
官方博客:http://eastjade.cnblogs.com
github:https://github.com/agilelab/eas
QQ:47920381,AgileEAS.NET
QQ羣:113723486(AgileEAS SOA 平臺)/上限1000人
199463175(AgileEAS SOA 交流)/上限1000人
212867943(AgileEAS.NET研究)/上限500人
147168308(AgileEAS.NET應用)/上限500人
172060626(深度AgileEAS.NET平臺)/上限500人
116773358(AgileEAS.NET 平臺)/上限500人
125643764(AgileEAS.NET探討)/上限500人
193486983(AgileEAS.NET 平臺)/上限500人
郵件:james@agilelab.cn,mail.james@qq.com,
電話:18629261335。