一、关于NoSQL的项目需求

这些年在做AgileEAS.NET SOA 中间件平台的推广、技术咨询服务过程之中,特别是针对我们最熟悉的医疗行业应用之中,针对大数据分析,大并发性能的需求,我们也在慢慢的引用NoSQL技术来满足数据分析与性能等多方面的需要,也进一步完善我们的SOA基石架构风格:

在早些年,对NoSQL不是很了解这前,后端数据存储都是存储的单一的关系数据库之上,但是在很多时间,这并不是最优的,比如在医疗用户之中针对一个病人的相关数据展示,及相关性分析,关于数据库就不是最优的,另外一个,电子病历系统的之中的结构化/半结构化病历文档的存储、检索,以及更高级的应用,结构化病历数据挖掘,之前使用关系数据库存储或者使用文件存储,很难发挥病历数据的科研和统计、分析需求。

在目前我们的医疗信息化应用之中,我们针对这两部分数据都引入了NoSQL存储,针对住院患者的领域相关性数据==》即病人聚合根对象相关数据,我们即在关系数据库以多表存储病人数据以及病人相关的医嘱、费用、检验、检查、护理等相关信息,同时我们也在NoSQL数据库存储患者的聚合根对象:

在NoSQL数据库之中的存储:

另外在电子病历应用之中,病历文档也是直接存入NoSQL之中。

在接触巨杉数据库之前,我们一直使用MongoDB这款NoSQL产品,这是一款广为人知的NoSQL产品,使用者众多,C#的驱动也非常完善,案例也比比皆时。

三、关于巨杉(sequoiadb)数据库

巨杉数据库是国人开发的一款企业级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#驱动

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", "");
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", );
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()); // 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 = ; i < ; ++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 = ;
query.SkipRowsCount = ;
DBCursor cursor = coll.Query(query);
Assert.IsNotNull(cursor);
int count = ;
while (cursor.Next() != null)
{
++count;
BsonDocument bson = cursor.Current();
Assert.IsNotNull(bson);
}
Assert.IsTrue(count == );

官方的代码有点简单,这不符合我们写代码的风格,目前业务系统大量的使用对象操作和Linq处理,原始的Bson接口,这个不科学。

五、完善改造SequoiaDB的C#驱动

即然官方的驱动太简单,不支持对象处理,也不支持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(-));
//依据条件删除
coll.Delete(p => p.ChargeTime > DateTime.Now.AddDays(-)); //求Count
int count = coll.AsQueryable<HFareDetail>()
.Where(p => p.SourceID==)
.Count(); //Linq查询Take\Skip。
var vList2 = coll.AsQueryable<HFareDetail>()
.Where(p => p.CreateTime > DateTime.Now.Date.AddMonths(-))
.Skip().Take()
.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(-))
.FirstOrDefault();
System.Console.WriteLine(vFare); //Linq\聚合运算,目前因为测试驱动报错,暂未实现
var sum = coll.AsQueryable<HFareDetail>()
.Where(p => p.CreateTime > DateTime.Now.Date.AddMonths(-))
.Sum(p => p.Cash); System.Console.ReadLine();

看看,代码是不是很清爽,很方便了呢,没有了bson,只有对象,Linq。

六、SequoiaDB、MongoDB与AgileEAS.NET SOA整合

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(-));
//依据条件删除
dbProvider.Delete<HFareDetail>(p => p.ChargeTime > DateTime.Now.AddDays(-)); //求Count
using (var queryWarp = dbProvider.Linq<HFareDetail>())
{
int count = queryWarp.Queryable
.Where(p => p.SourceID == )
.Count(); //Linq查询Take\Skip。
var vList2 = queryWarp.Queryable
.Where(p => p.CreateTime > DateTime.Now.Date.AddMonths(-))
.Skip().Take()
.ToList();
System.Console.WriteLine(string.Format("query {0} records", vList.Count)); //Linq查询过。
var vFare = queryWarp.Queryable
.Where(p => p.CreateTime > DateTime.Now.Date.AddMonths(-))
.FirstOrDefault();
System.Console.WriteLine(vFare); //Linq\聚合运算,目前因为测试驱动报错,暂未实现
var sum = queryWarp.Queryable
.Where(p => p.CreateTime > DateTime.Now.Date.AddMonths(-))
.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#驱动源代码托管、下载

本人为SequoiaDB所写的C#驱动,已提交托管到github,项目地址https://github.com/agilelab/SequoiaDB.Charp,欢迎大家下载,也欢迎大家和本人一道完善本驱动。

八、联系我们

敏捷软件工程实验室,是一家研究、推广和发展新技术,并致力于提供具有自主知识产权的业务基础平台软件,以及基于业务基础平台开发的管理软件的专业软件提供商。主要业务是为客户提供软件企业研发管理解决方案、企业管理软件开发,以及相关的技术支持,管理及技术咨询与培训业务。

AgileEAS.NET SOA中间件平台自2004年秋呱呱落地一来,我就一直在逐步完善和改进,也被应用于保险、医疗、电子商务、房地产、铁路、教育等多个应用,但一直都是以我个人在推广,2010年因为我辞职休息,我就想到把AgileEAS.NET推向市场,让更多的人使用。

我的技术团队成员都是合作多年的老朋友,因为这个平台是免费的,所以也没有什么收入,都是由程序员的那种理想与信念坚持,在此我感谢一起奋斗的朋友。

团队网站:http://www.agilelab.cn

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。

本人为巨杉数据库(开源NoSQL)写的C#驱动,支持Linq,全部开源,已提交github的更多相关文章

  1. 巨杉数据库加入CNCF云原生应用计算基金会,共建开源技术生态

    近日,巨杉数据库正式加入全球顶级开源社区,云原生应用计算基金会 (Cloud Native Computing Foundation,以下简称CNCF),成为CNCF基金会会员,是中国最早加入的开源云 ...

  2. 巨杉数据库SequoiaDB】巨杉Tech | SequoiaDB 分布式事务实现原理简介

    1 分布式事务背景 随着分布式数据库技术的发展越来越成熟,业内对于分布式数据库的要求也由曾经只用满足解决海量数据的存储和读取这类边缘业务向核心交易业务转变.分布式数据库如果要满足核心账务类交易需求,则 ...

  3. 巨杉数据库入选年度Gartner Peer Insights报告,获得市场高度评价

    Gartner Peer Insights 年度评选结果于近日出炉,在数据库管理系统市场报告中,巨杉数据库获得了总平均分4.7(满分5分)的成绩,在众多国际厂商中位居第三,是国内唯一一家入选的数据库厂 ...

  4. 巨杉数据库 MySQL兼容项目正式开源

    9月7日.8日,2018  ODF 开源数据库论坛,在北京盛大开幕.在大会上,巨杉数据库正式发布了巨杉全新的MySQL/MariaDB兼容架构,并将项目正式开源. 开源数据库论坛(ODF)是中国开源数 ...

  5. 【巨杉数据库SequoiaDB】企业级和开源领域“两开花”,巨杉引领国产数据库创新

    2019年12月15日,OSC 源创会·年终盛典在深圳圆满举行.巨杉数据库作为业界领先的金融级分布式数据库厂商, 获得 “2019年开源数据库先锋企业” 及 “2019 GVP-Gitee最有价值开源 ...

  6. 深入学习sequoiadb巨杉数据库及python连接方式

    随着公司日益复杂与多变的需求,以及迅速扩展带来的海量数据业务,我们需要在提供高效服务的同时,降低其设备与程序维护成本.算了,不吹了,说白了就是需要从巨杉数据库中抓取大量的数据,但是我现在不会,所以需要 ...

  7. 非关系型数据库(NoSql)

    最近了解了一点非关系型数据库,刚刚接触,觉得这是一个很好的方向,对于大数据 方面的处理,非关系型数据库能起到至关重要的地位.这里我主要是整理了一些前辈的经验,仅供参考. 关系型数据库的特点 1.关系型 ...

  8. 【操作教程】利用YCSB测试巨杉数据库性能

    一.前言 巨杉数据库(SequoiaDB)是国内第一款新一代文档型分布式数据库,巨杉数据库由巨杉软件完全自主研发,拥有完全自主知识产权,不基于任何其它的开源项目.SequoiaDB数据库是为分布式存储 ...

  9. 【巨杉答疑】巨杉数据库和mongodb有什么关系吗?

    哈罗,艾瑞巴蒂~巨杉答疑栏目今日上线啦! 巨杉数据库作为商业化开源软件,已经拥有大量社区用户.开源至今,大到分布式数据库原理.架构问题,小到SDB巨杉数据库的安装使用问题,大家似乎都有很多问题想要和我 ...

随机推荐

  1. mfc+vtk

    MFC中view类主要处理显示视图,doc类处理文档,mainframe主要为整个窗口的和工程的设置管理.由此,VTK与MFC联合编程时,需要主要的是数据操作,以及显示要很好的与MFC中的结构结合,做 ...

  2. 【译文】JNI编程

    原文链接: https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html   没有逐字翻译,解说了文章的大 ...

  3. SQL Server基线算法(同比和环比)

    基线介绍 基线为历史数据统计而成的数据,具有参考价值,并利用基线数据与当前值的对比,通过一定的报警机制,形成实时监控架构.SQL Server计数器采用同比和环比两种方式. 同比:可以计算未来一周的基 ...

  4. REDHAT一总复习1 NTP更改时区,并验证时区设置是否正确

    把计算机时区调整到巴哈马(这是个啥地方?听都没听过.) 使用 tzselect  进行确定时区,并进行可对话性的设置,按照对应的序号,射进去就行了. 使用:timedatectl set-timezo ...

  5. 用Model-View-ViewModel构建iOS App

    如果你已经开发一段时间的iOS应用,你一定听说过Model-View-Controller,即MVC.MVC是构建iOS App的标准模式.然而,最近我已经越来越厌倦MVC的一些缺点.在本文,我将重温 ...

  6. D3.js学习(四)

    上一节我们已经学习了线条样式和格栅的绘制,在这一节中我们将要根据之前绘制的线条对图表进行填充,首先来看一下我们的目标吧 在这个图表中,我们对位于线条下面的空间进行了填充,那么,如何改做到呢? 设置填充 ...

  7. 用递归调用实现字符串反转(java版)

    写一个函数,输入int型,返回整数逆序后的字符串.如:输入123,返回“321”. 要求必须用递归,不能用全局变量,输入必须是一个参数,必须返回字符串. public static String re ...

  8. Xcode will continue when iPad is finished. "Could not find Developer Disk Image"

    1:  Xcode will continue when iPad is finished. 等待进度条读取完成即可: 2: xcode,安装新版本的iOS 的 xcode 支持文件 的路径: /ap ...

  9. 【Python文件处理】递归批处理文件夹子目录内所有txt数据

    因为有个需求,需要处理文件夹内所有txt文件,将txt里面的数据筛选,重新存储. 虽然手工可以做,但想到了python一直主张的是自动化测试,就想试着写一个自动化处理数据的程序. 一.分析数据格式 需 ...

  10. debian 或者kali 安装git

    安装git 是时候动手尝试下 Git 了,不过得先安装好它.有许多种安装方式,主要分为两种,一种是通过编译源代码来安装:另一种是使用为特定平台预编译好的安装包. 源码安装 若是条件允许,从源代码安装有 ...