最近花了二个月的业余时间重写了我以前的通用数据访问层, 由于是重写,所以我给这个项目取了个新名字:ClownFish
如果需要了解ClownFish的使用方法,请点击ClownFish 使用说明
ClownFish是什么?
ClownFish 是我编写的一个通用数据访问层,设计它的目的是为了:
1. 方便在 .net 项目中执行数据访问任务。
2. 避免直接使用ADO.NET带来的一大堆高度类似的繁琐代码。
3. 提供出色的性能满足实际项目需要。
ClownFish 具有以下一些技术特色:
1. 高性能:比手写代码还快的执行速度。
2. 简单:执行查询、将查询结果转成实体列表、获取输出参数。 一个调用完成三个步骤。
3. 方便:提供专用的代码生成器,直接生成调用代码或者实体类型定义代码。
4. 通用:可以非常简单地实现对多种数据库的支持。
5. 灵活:支持存储过程,参数化SQL,或者将SQL语句保存在XML配置文件中。
6. 可监控:提供一个Profiler工具,让您可以随时了解详细的数据库访问情况。
ClownFish不仅继承了老版本的通用数据访问层的全部优点, 而且在高性能,方便性,灵活性,以及代码可读性方面有了更出色的设计。
在最新的版本中,ClownFish不仅仅只是一个通用数据访问层, 还提供了:专用的代码生成器,XmlCommand管理工具,Profiler工具,它们都会为ClownFish提供更多功能。
ClownFish 是一个可免费的数据访问组件,您可以把它应用在您的 .net 项目中,让它简化您的开发工作。
比手写代码还快的执行速度
提高性能是创建ClownFish项目的重要原因之一,这次优化的主要目标是:比手写代码还快的执行速度。
为了让您对ClownFish的性能留有较深刻的印象,下面我将通过一个实际案例来测试它的速度。
首先,我定义了一个实体类型:
定义这个实体类型,我关注的是它所包含的数据成员的数量,而不是那些数据成员的含义。
我认为这个类型的数据成员数量应该还是比较接近多数实际场景的。
下面再来看看如何从数据库中加载它们:
代码中,首先定义了一个参数化的SQL查询语句,然后就是纯手工的ADO.NET代码,循环调用SqlDataReader.Read()方法,再从SqlDataReader中根据字段名称获取数据写入到实体对象的属性中。
这段代码够【手工化】吧? 由于这段代码没用使用反射代码,所以如果想追求性能,我想大家都会这样写。
在我的测试程序中,上面那段代码被下面这段代码调用:
测试代码应该没有问题吧?
再来看一下使用ClownFish的等效测试代码:
[TestMethod("ClownFish,SQLSERVER", 2)] public class Test_ClownFish_ShareConnection : IPerformanceTest { private UiParameters uiParam; private ClownFish.DbContext db; public Test_ClownFish_ShareConnection(UiParameters param) { this.uiParam = param; this.db = new ClownFish.DbContext(false); } public List<OrderInfo> Run() { var parameter = new { TopN = uiParam.PageSize }; return ClownFish.DbHelper.FillList<OrderInfo>( TestHelper.QueryText, parameter, db, ClownFish.CommandKind.SqlTextWithParams); } public void Dispose() { db.Dispose(); } }
比较这二段代码,不难看出:使用 ClownFish 所需的代码量要 少很多。
如果我以下面的测试参数执行性能测试:
可以得到下面的测试结果:
图形反映的结果很直观:ClownFish 完成测试所需时间比手写代码要略快点。
或许有些人认为:快这么一点,意义不大!
但您想过没有:ClownFish PK的对象是【手工版的专用代码】啊!
其实这个测试并没有把 ClownFish 性能很好的体现出来,因为中间有SQLSERVER的执行时间,以及跨进程的调用开销。 这二个因素所花的成本影响了ClownFish的性能优势。
下面,我又做了一组测试:直接从DataTable中加载数据。
我之所以选择这个测试方法,是因为它也是一种常见的使用方案:
我们可以将原始导出到XML文件中,然后使用XML文件做离线数据,这样可以减少对数据库的访问压力。
老版本的通用数据访问层也一直支持这个功能,所以这次就选择了这个测试方法。
说明:实际使用时,我会从XML读出数据到DataTable,供后面使用(转成实体类型只是其中的一种使用数据的方式)。
在测试之前,我们来看一下手工代码是什么样的:
看到这个版本的LoadOrderInfo方法,您会有什么感觉?是不是很无奈?
没办法,ADO.NET就是这样设计的。写这样的代码会让人心烦(这是我的感受)!
测试调用代码:
测试代码应该没有问题吧?
再来看一下使用ClownFish的等效测试代码:
[TestMethod("ClownFish,DataTable", 6)] public class Test_ClownFish_LoadDataTable : IPerformanceTest { public Test_ClownFish_LoadDataTable(UiParameters param) { } public void Dispose() { } public List<OrderInfo> Run() { return ClownFish.DbHelper.FillListFromTable<OrderInfo>(TestHelper.GetOrderInfoTable()); } }
使用 ClownFish 的代码仍然要短很多!
下面继续使用前面的测试参数来运行测试程序,得到以下测试结果:
Excel图形直观反映出 ClownFish 的速度要 比手工代码 快一倍 还不止。
看完这二个测试,ClownFish 有没有给您留下二个印象?
1. 代码量很少。
2. 性能很好。