开源ORM之Dapper在项目中的尝试

  关于轻量级开源ORM-Dapper的介绍网上有太多例子,自己无意再重复介绍了,本文只是记录下Dapper在目前项目中的应用或者尝试。先说下背景,来到新公司有段时间了,这期间接触了几个项目,发现有一个问题就是所有这些项目的数据访问层无一例外的都是用最原始的ado.net(SqlHelper类只是对ado.net进行粗糙地封装),而且每次进行CRUD操作时都要传递数据库连接字符串和SqlParamerter数组,还有一些其他的额外参数,而且返回来的结果还得自己再调用另外的方法去反射得到具体的实体对象或实体集合。在现在各种ORM框架大行其道的今天,我实在是受够了目前这种编码的痛苦。于是,萌生了将轻量级的ORM-Dapper引入项目的想法。至于为什么不用EF,我的考虑是EF太过于庞大,而且会颠覆目前项目的开发方式,估计项目组成员接受不了,阻力肯定非常大。这个时候Dapper的好处就是可以无缝地,几乎不用改变现有开发方式就能应用到项目中。于是参考博客园他人博客最大限度地封装了一个DbHelper类,即DataProvider类,并自己先试用,自我认为封装比较彻底,别人用起来也比较顺手。以下是DataProvider类具体代码:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Configuration;
  4 using System.Data;
  5 using System.Data.Common;
  6 using System.Linq;
  7
  8 namespace Dapper
  9 {
 10     /// <summary>
 11     /// 数据库访问提供类
 12     /// </summary>
 13     public class DataProvider
 14     {
 15         /// <summary>
 16         /// 数据库连接字符串
 17         /// </summary>
 18         private string connectionString = string.Empty;
 19         /// <summary>
 20         /// 数据库提供程序名称
 21         /// </summary>
 22         private string providerName = "System.Data.SqlClient";
 23         /// <summary>
 24         /// 数据库连接信息缓存
 25         /// </summary>
 26         private static Dictionary<string, ConnectionInfo> cacheDic = new Dictionary<string, ConnectionInfo>();
 27
 28         /// <summary>
 29         /// 初始化数据库连接 - 默认为MSSQLSERVER连接
 30         /// </summary>
 31         public DataProvider()
 32             : this("ConnectionString")
 33         { }
 34         /// <summary>
 35         /// 根据指定的连接字符串名称初始化特定的数据库连接
 36         /// </summary>
 37         /// <param name="connectionString"></param>
 38         public DataProvider(string connectionStringName)
 39         {
 40             try
 41             {
 42                 if (!cacheDic.ContainsKey(connectionStringName))
 43                 {
 44                     var connectSetting = ConfigurationManager.ConnectionStrings[connectionStringName];
 45                     if (connectSetting == null)
 46                         throw new Exception("未设置数据库连接配置!");
 47                     this.providerName = connectSetting.ProviderName;
 48                     this.connectionString = connectSetting.ConnectionString;
 49                     if (string.IsNullOrEmpty(this.providerName) || string.IsNullOrEmpty(this.connectionString))
 50                         throw new Exception("数据库连接配置不正确!");
 51
 52                     if (!cacheDic.ContainsKey(connectionStringName) && this.TestConnection())
 53                     {
 54                         ConnectionInfo info = new ConnectionInfo(providerName, connectionString);
 55                         cacheDic.Add(connectionStringName, info);
 56                     }
 57                 }
 58                 else
 59                 {
 60                     providerName = cacheDic[connectionStringName].ProviderName;
 61                     connectionString = cacheDic[connectionStringName].ConnectionString;
 62                 }
 63             }
 64             catch (Exception ex)
 65             {
 66                 throw new Exception("初始化数据库连接出错," + ex.Message);
 67             }
 68         }
 69
 70         /// <summary>
 71         /// 测试数据库连接
 72         /// </summary>
 73         /// <returns></returns>
 74         private bool TestConnection()
 75         {
 76             bool result = true;
 77             try
 78             {
 79                 DbProviderFactory dbFactory = DbProviderFactories.GetFactory(providerName);
 80                 using (IDbConnection conn = dbFactory.CreateConnection())
 81                 {
 82                     conn.ConnectionString = connectionString;
 83                     conn.Open();
 84                 }
 85             }
 86             catch (Exception)
 87             {
 88                 result = false;
 89             }
 90             return result;
 91         }
 92         /// <summary>
 93         /// 创建并打开数据库连接
 94         /// </summary>
 95         /// <param name="providerName"></param>
 96         /// <param name="connectionString"></param>
 97         private IDbConnection CreateConnection()
 98         {
 99             DbProviderFactory dbFactory = DbProviderFactories.GetFactory(providerName);
100             IDbConnection conn = dbFactory.CreateConnection();
101             conn.ConnectionString = connectionString;
102             conn.Open();
103             return conn;
104         }
105
106         /// <summary>
107         /// 查询,并返回动态类型集合
108         /// </summary>
109         /// <param name="commondText"></param>
110         /// <param name="param"></param>
111         /// <param name="transaction"></param>
112         /// <param name="buffered"></param>
113         /// <param name="commandTimeout"></param>
114         /// <param name="commandType"></param>
115         /// <returns></returns>
116         public IEnumerable<dynamic> Query(string commondText, object param, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
117         {
118             using (IDbConnection conn = this.CreateConnection())
119             {
120                 return conn.Query(commondText, param, transaction, buffered, commandTimeout, commandType);
121             }
122         }
123         /// <summary>
124         /// 查询,并返回泛型实体对象集合
125         /// </summary>
126         /// <typeparam name="T"></typeparam>
127         /// <param name="commondText"></param>
128         /// <param name="param"></param>
129         /// <param name="transaction"></param>
130         /// <param name="buffered"></param>
131         /// <param name="commandTimeout"></param>
132         /// <param name="commandType"></param>
133         /// <returns></returns>
134         public IList<T> Query<T>(string commondText, object param, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null) where T : class,new()
135         {
136             using (IDbConnection conn = this.CreateConnection())
137             {
138                 var items = conn.Query<T>(commondText, param, transaction, buffered, commandTimeout, commandType);
139                 return items.ToList();
140             }
141         }
142         /// <summary>
143         /// 查询,并返回单个动态类型对象
144         /// </summary>
145         /// <param name="commondText"></param>
146         /// <param name="param"></param>
147         /// <param name="transaction"></param>
148         /// <param name="buffered"></param>
149         /// <param name="commandTimeout"></param>
150         /// <param name="commandType"></param>
151         /// <returns></returns>
152         public dynamic Single(string commondText, object param, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
153         {
154             using (IDbConnection conn = this.CreateConnection())
155             {
156                 return conn.Query(commondText, param, transaction, buffered, commandTimeout, commandType).FirstOrDefault();
157             }
158         }
159         /// <summary>
160         /// 查询,并返回单个实体类对象或默认值
161         /// </summary>
162         /// <typeparam name="T"></typeparam>
163         /// <param name="commondText"></param>
164         /// <param name="param"></param>
165         /// <param name="transaction"></param>
166         /// <param name="buffered"></param>
167         /// <param name="commandTimeout"></param>
168         /// <param name="commandType"></param>
169         /// <returns></returns>
170         public T SingleOrDefault<T>(string commondText, object param, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null) where T : class,new()
171         {
172             using (IDbConnection conn = this.CreateConnection())
173             {
174                 var items = conn.Query<T>(commondText, param, transaction, buffered, commandTimeout, commandType);
175                 return items.FirstOrDefault();
176             }
177         }
178         /// <summary>
179         /// 执行参数化的SQL语句,返回IDataReader
180         /// </summary>
181         /// <param name="commondText"></param>
182         /// <param name="param"></param>
183         /// <param name="transaction"></param>
184         /// <param name="commandTimeout"></param>
185         /// <returns></returns>
186         public IDataReader ExecuteReader(string commondText, object param, IDbTransaction transaction = null, int? commandTimeout = null)
187         {
188             using (IDbConnection conn = this.CreateConnection())
189             {
190                 return conn.ExecuteReader(commondText, param, transaction, commandTimeout);
191             }
192         }
193         /// <summary>
194         /// 执行参数化的SQL语句,并返回单个值(根据泛型类型,指定要返回的值的数据类型)
195         /// </summary>
196         /// <typeparam name="T"></typeparam>
197         /// <param name="commondText"></param>
198         /// <param name="param"></param>
199         /// <param name="transaction"></param>
200         /// <param name="commandTimeout"></param>
201         /// <returns></returns>
202         public T ExecuteScalar<T>(string commondText, object param, IDbTransaction transaction = null, int? commandTimeout = null)
203         {
204             using (IDbConnection conn = this.CreateConnection())
205             {
206                 return (T)conn.ExecuteScalar(commondText, param, transaction, commandTimeout);
207             }
208         }
209         /// <summary>
210         /// 执行参数化的SQL语句,并返回受影响的行数
211         /// </summary>
212         /// <param name="commondText"></param>
213         /// <param name="param"></param>
214         /// <param name="transaction"></param>
215         /// <param name="commandTimeout"></param>
216         /// <returns></returns>
217         public int ExecuteNonQuery(string commondText,object param,IDbTransaction transaction = null,int? commandTimeout = null)
218         {
219             using (IDbConnection conn = this.CreateConnection())
220             {
221                 return conn.Execute(commondText, param, transaction, commandTimeout);
222             }
223         }
224         /// <summary>
225         /// 执行参数化的SQL语句,并返回DataTable
226         /// </summary>
227         /// <param name="commondText"></param>
228         /// <param name="param"></param>
229         /// <param name="transaction"></param>
230         /// <param name="commandTimeout"></param>
231         /// <returns></returns>
232         public DataTable ExecuteDataTable(string commondText, object param, IDbTransaction transaction = null, int? commandTimeout = null)
233         {
234             using (IDbConnection conn = this.CreateConnection())
235             {
236                 DataTable dt = new DataTable();
237                 IDataReader reader = conn.ExecuteReader(commondText, param, transaction, commandTimeout);
238                 dt.Load(reader);
239                 return dt;
240             }
241         }
242     }
243     /// <summary>
244     /// 数据库连接信息
245     /// </summary>
246     public class ConnectionInfo
247     {
248         private string connectionString = string.Empty;
249         private string providerName = "System.Data.SqlClient";
250
251         /// <summary>
252         /// 数据库连接字符串
253         /// </summary>
254         public string ConnectionString
255         {
256             get { return connectionString; }
257         }
258         /// <summary>
259         /// 数据库提供程序名称
260         /// </summary>
261         public string ProviderName
262         {
263             get { return providerName; }
264         }
265
266         /// <summary>
267         /// 初始化数据库提供程序名称和连接字符串名称
268         /// </summary>
269         /// <param name="providerName"></param>
270         /// <param name="connectionName"></param>
271         public ConnectionInfo(string providerName, string connectionString)
272         {
273             this.connectionString = connectionString;
274             this.providerName = providerName;
275         }
276     }
277 }

DataProvider.cs

这样写好后,项目中只要引入SqlMapper.cs文件和DataProvider.cs这两个文件,就可以很方便的使用了。

比如以前通过ado.net操作数据库可能是这样的:

 1 // 插入一条数据
 2 string sqlText = "INSERT INTO T(col1,col2,col3....)VALUES(@col1,@col2,@col3....)";
 3 SqlParameter[] paramArray = new SqlParameter[] {
 4     new SqlParameter("col1", value1),
 5     new SqlParameter("col2", value2),
 6     new SqlParameter("col3", value3)
 7      ...
 8 };
 9  int count = SqlHelper.ExecuteNonequery(connectionString,sqlText,paramArray);
10
11 // 查询得到实体对象
12 DataSet ds = SqlHelper.QueryDataSet(connectionString, sqlText, paramArray);
13 if(ds != null & ds.Tables.Count > 0)
14     entity = SqlHelper.FillModel<Model>(ds.Tables[0]);

通过ado.net方式操作数据库

相应地,通过DataProvider类操作数据库就变成下面这样了:

1 // 实例化DataProvider对象
2 DataProvider dp = new DataProvider();
3 // 插入一条数据
4 string sqlText = "INSERT T(col1,col2,col3,...) VALUES(@col1,@col2,@clo3,..)
5 int count = dp.ExecuteNonequery(sqlText, model);
6 // 查询得到实体对象
7 entity = dp.Query<Model>(sqlText, param);

通过DataProvider对象操作数据库

  这样,对比之后,是不是感觉代码立马清爽许多,最主要的是原来的编码方式基本不会有什么变化,而且一旦表中字段特别多,或者需要进行批量插入等操作时,就不需要写一大堆参数赋值代码,这时候ORM框架的作用就体现出来了(这里先不谈Dapper的性能),可以说,引入Dapper对项目开发绝对是百利无一害的!

  然而,这一切并没有什么卵用,当我满怀希望地向开发经理介绍Dapper时,我担心的事情还是发生了,开发经理虽然肯定了这种做法,但终究还是没同意将Dapper引入项目的建议,当时心里瞬间感觉拔凉拔凉的了!

  因此,特以此博客记载一次不成功的尝试,但是对于新技术(或是能够提高生产力的事物)的追求,将不会就此终止!

时间: 2024-10-15 14:56:28

开源ORM之Dapper在项目中的尝试的相关文章

ORM Nhibernate框架在项目中的配置

在项目中使用 Nhibernet 时,一定要将 配置文件 .xml  编译方式设置为 嵌入式资源,否则在运行项目时就会出现错误. 以下是hibernate.cfg.xml 的配置,在配置中使用的是 Mysql 数据库 <?xml version="1.0" encoding="utf-8" ?> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"&g

Google如何从不断增加市场份额的安卓开源项目中获益

最近ABI research的调查数据显示,智能手机平台的市场份额分割出两个安卓阵营:具有Google特色的安卓(即主要由Open Handset Alliance的成员使用,由Google play支持和服务的安卓)和安卓开源计划AOSP(即可以免费让任何制造商用作自己的手机的操作系统的安卓). Google安卓系统占市场份额的65%,而AOSP为20%,遥遥领先于IOS和Windows Phone.很多人认为AOSP20%的市场份额对Google来说是个潜在的威胁,但我觉得Google已经找

简单ORM工具的设计和编写,自己项目中曾经用过的

http://www.cnblogs.com/szp1118/archive/2011/03/30/ORM.html 在之前的一个项目中自己编写了一个简单的ORM小工具,这次重新整理和重构了一下代码,之所以说简单是因为该小工具仅仅实现了增删改查的简单功能,不具备数据缓存,延迟加载,关联操作等高级功能.正因为简单所以用起来也不麻烦,代码也不是很复杂,但是在数据层至少可以减少70%以上的代码编写量,可以减少至少50%以上的SQL语句编写量. 设计思想:实体类中的非null属性都会作为SQL语句中的参

从国外开源项目中提取的继承类

javascript没有原生的继承语法,这确实很让人困惑,但是广大人民群从的智慧是无穷的.最近呢,正尝到一点从源码中学习的甜头,不分享一下实在难以平复激动的心情.前不久改造视频播放插件的时候,找到了videojs这个优秀的开源项目.经过一段时间深入学习它的源码,发现它的继承机制写的很好,而且短小精悍,于是决定把它拔离出来,做成一个单独的库,方便以后项目中使用. //定义一个命名空间 var xut = {}; /** * Core Object/Class for objects that us

导入开源库到基于Android Studio构建的项目中

前两天,谷歌发布了Android Studio 1.0的正式版,也有更多的人开始迁移到Android Studio进行开发.然而,网上很多的开源库,控件等还是以前的基于Eclipse进行开发,很多人不知道怎么导入到自己的基于Android Studio项目中来,微博上也有人私信我,让我来写写,正好今天回来的比较早,就写写吧.主要介绍一下常见的一些导包的场景. 前言 --project //项目目录 | build.gradle //项目的gradle配置文件 | settings.gradle

ios项目中引用其他开源项目

1. 将开源项目的.xcodeproj拖入项目frameworks 2. Build Phases下 Links Binary With Libraries 引入.a文件.Target Dependencies里引入开源项目文件 3. Build Setting下的 Search Paths 里 Header Search Paths 加入开源项目src目录 例:$(SOURCE_ROOT)/IBAForms/headers ,IBA放在项目根目录里,headers就是src 如果和项目根目录平

[转]C,C++开源项目中的100个Bugs

[转]C,C++开源项目中的100个Bugs http://tonybai.com/2013/04/10/100-bugs-in-c-cpp-opensource-projects/ 俄罗斯OOO Program Verification Systems公司用自己的静态源码分析产品PVS-Studio对一些知名的C/C++开源项目,诸如Apache Http Server.Chromium.Clang.CMake.MySQL等的源码进行了分析,找出了100个典型的Bugs. 个人觉得这份列表对C

如何在Android Studio项目中导入开源库?

前两天,谷歌发布了Android Studio 1.0的正式版,也有更多的人开始迁移到Android Studio进行开发.然而,网上很多的开源库,控件等还是以前的基于Eclipse进行开发,很多人不知道怎么导入到自己的基于Android Studio项目中来,微博上也有人私信我,让我来写写,正好今天回来的比较早,就写写吧.主要介绍一下常见的一些导包的场景. 前言 --project //项目目录 | build.gradle //项目的gradle配置文件 | settings.gradle

iOS项目中常用的第三方开源库

1.项目使用的第三方开源库 http://github.ibireme.com/github/list/ios/整理了比较常用的iOS第三方组件,以及github上的统计. 项目使用了CocoaPods(类似java中的maven)管理常用的第三方库,一些特殊的单独引用,下面介绍下比较好用的几个. (1)AFNetworking 目前比较推荐的iOS网络请求组件,默认网络请求是异步,通过block回调的方式对返回数据进行处理. 需要注意的是AFNetworking对服务器返回的ContentTy