一、背景

前几天看公司一个新项目的底层使用了dapper,大家都知道dapper是一个非常强大的半自动化orm,帮程序员解决了繁琐的mapping问题,用起来非常爽,但我还是遇到了一件非常不爽的事情,如下代码所示:

public class UserDAL : BaseDAL{ public List<UserModel> GetList() {  using (SqlConnection conn = new SqlConnection(ConnectionString))  {   var list = conn.Query<UserModel>("select * from users").ToList();   return list;  } } public bool Insert() {  using (SqlConnection conn = new SqlConnection(ConnectionString))  {   var execnum = conn.Execute("insert into xxx ");   return execnum > 0;  } } public bool Update() {  using (SqlConnection conn = new SqlConnection(ConnectionString))  {   var execnum = conn.Execute("update xxx ....");   return execnum > 0;  } }}public class UserModel {}

扫一下代码是不是总感觉哪里不对劲,是的,为了能使用上Dapper的扩展方法,这里面每个方法中都配上了模板化的 using (SqlConnection conn = new SqlConnection(ConnectionString)),虽然这样写逻辑上没有任何问题,但我有洁癖哈,接下来试着封装一下,嘿嘿,用更少的代码做更多的事情。

二、模板化代码封装探索

1、将模板化的代码提取到父类中

仔细看上面的模板代码你会发现,真正的业务逻辑是写在 using 中的,而该块中只需要拿到一个 conn 就可以了,其他的统一提取封装到父类中,这就可以用到 委托函数啦,对不对,用这个思路代码修改如下:

public class BaseDAL{ protected string ConnectionString { get; set; } public T Execute<T>(Func<SqlConnection, T> func) {  using (SqlConnection connection = new SqlConnection(ConnectionString))  {   return func(connection);  } }}

 

有了父类通用的 Execute 方法,接下来子类中就可以直接用它啦,改造如下:

public class UserDAL : BaseDAL{ public List<UserModel> GetList() {  return Execute((conn) =>  {   var list = conn.Query<UserModel>("select * from users").ToList();   return list;  }); } public bool Insert() {  return Execute((conn) =>  {   var execnum = conn.Execute("insert into xxx ");   return execnum > 0;  }); } public bool Update() {  return Execute((conn) =>  {   var execnum = conn.Execute("update xxx ....");   return execnum > 0;  }); }}

改造之后代码是不是清晰多了,仅仅这一个通用方法貌似还不行,起码 ConnectionString 不能框死。

2、增加Connec.........