浅谈业务逻辑与数据访问
前言
写这篇博客只是发表个人的看法,探讨如何搭建高效实用的框架,有不完善的地方可以留言补充.
正文
说起业务逻辑大家并不陌生,不管是简单易懂的三层架构,还是复杂的DDD,都脱离不了业务逻辑,从字面意思理解,无非就是处理一些业务规则,这里不深究这些文字游戏,重点来说说我们工作中业务逻辑与数据的交互.
这里拿三层框架来举例,UI,BLL,DAL,我们习惯把程序这样划分,很多猿友认为BLL有点累赘,很通用的做法是在UI里直接访问DAL,在DAL里编写sql,来实现一个功能,咋一看上去功能确实ok,做WEB开发的猿友都知道核心功能往往只有那么一两个,其它大多数都是简单的增删改查(分页),60%的时间花费在前端数据的填充,30%的时间花费在DAL编写sql,有些远见的猿友会考虑到后期的维护,代码的复用...然而在天朝,死道友不死贫道,为了自己不加班,往往会导致后面接手你项目的人通宵加班,这些都是后话了,随着项目的越来越大,后期的拓展,慢慢发现前面有很多是曾相识的功能,这时候就会纠结,是重构还是在原有上面修改,因为不存在BLL,只能去重构或修改DAL里的sql语句,后期让别人去维护这个项目会更糟.
如何搭建高效实用的框架,让自己用的爽,让别人维护的舒服?这里回归BLL,常规的BLL直接拿DAL的数据返回给UI,看起来很弱,但是也属于业务逻辑的一部分,就好比哈巴狗跟藏獒一样,都是犬类,所以我把BLL分成两块,代码如下
1 #region ((((((((((((((((((((((数据操作)))))))))))))))))))))))))))) 2 3 /// <summary> 4 /// 公共的操作数据库方法,不可改变 5 /// </summary> 6 /// <param name="dto">dto参数集合</param> 7 /// <param name="db">数据库操作对象</param> 8 /// <returns></returns> 9 #region //////////////公共方法区////////////////////// 10 #region ================查询====================== 11 public users GetModel(Dtb_Users dto,Database db = null) 12 { 13 return d_user.GetModel(dto,db); 14 } 15 public users GetModel(object id, Database db = null) 16 { 17 if (db == null) 18 { 19 return d_user.Get(id); 20 } 21 else 22 { 23 return d_user.Get(id, db); 24 } 25 } 26 public List<users> GetList(Dtb_Users dto, Database db = null) 27 { 28 return d_user.GetList(dto,db); 29 } 30 public DataTable GetTable(Dtb_Users dto, Database db = null) 31 { 32 return d_user.GetTable(dto,db); 33 } 34 35 public bool Exists(int id, Database db = null) 36 { 37 return d_user.Exists(id,db); 38 } 39 40 public int GetCount(Dtb_Users dto, Database db = null) 41 { 42 return d_user.GetCount(dto, db); 43 } 44 #endregion 45 46 #region ================修改====================== 47 public bool Edit(users m_user,Database db = null) 48 { 49 var res = d_user.Edit(m_user,db); 50 return res.ToBool(); 51 } 52 #endregion 53 54 #region ================添加====================== 55 public int Add(users m_user, Database db = null) 56 { 57 var res = d_user.Add(m_user,db); 58 return res.ToInt32(); 59 } 60 #endregion 61 62 #region ================删除====================== 63 public bool Del(object id, Database db = null) 64 { 65 var res = d_user.Del(id,db); 66 return res.ToBool(); 67 } 68 #endregion 69 70 #endregion 71 72 73 /// <summary> 74 /// 拓展方法由sql语法拼接而成,不依赖dto,更加的精简,联合查询,主表对象必须是此model 75 /// </summary> 76 /// <param name="dto">dto参数集合</param> 77 /// <param name="db">事务锁</param> 78 /// <returns></returns> 79 #region //////////////拓展方法区////////////////////// 80 #region ================查询====================== 81 82 #region ****************普通查询********************** 83 84 /// <summary> 85 /// 查询id 86 /// </summary> 87 /// <param name="userName">用户名</param> 88 /// <param name="mobile">手机号</param> 89 /// <param name="db">数据库操作对象</param> 90 /// <returns>id</returns> 91 public int GetById(string userName,string mobile,Database db = null) 92 { 93 if (db == null) db = this.db; 94 string sql = "select id from dsxy_users where user_name=@0 and mobile=@1"; 95 DataTable dt = db.QueryTable(sql,userName,mobile); 96 var res = dt.Rows[0][0]; 97 return res.ToInt32(); 98 } 99 /// <summary> 100 /// 查询model 101 /// </summary> 102 /// <param name="userName">用户名</param> 103 /// <param name="mobile">手机号</param> 104 /// <param name="db">数据库操作对象</param> 105 /// <returns>m_user</returns> 106 public DataTable GetModel(string userName, string mobile, Database db = null) 107 { 108 if (db == null) db = this.db; 109 string sql = "select id from dsxy_users where user_name=@0 and mobile=@1"; 110 DataTable dt = db.QueryTable(sql, userName,mobile); 111 return dt; 112 } 113 #endregion 114 115 #region ################关联查询####################### 116 /// <summary> 117 /// 查询用户等级 118 /// </summary> 119 /// <param name="userName">用户名</param> 120 /// <param name="mobile">手机号</param> 121 /// <param name="db">数据库操作对象</param> 122 /// <returns>用户等级</returns> 123 public string GetByGroup(string userName, string mobile, Database db = null) 124 { 125 if (db == null) db = this.db; 126 StringBuilder sb = new StringBuilder(); 127 sb.Append("select g.title from dsxy_users u "); 128 sb.Append("left join dsxy_user_groups g on u.group_id = g.id "); 129 sb.Append("where u.user_name = @0 and u.mobile = @1 "); 130 string sql = sb.ToString(); 131 DataTable dt = db.QueryTable(sql, userName,mobile); 132 var res = dt.Rows[0][0]; 133 return res.ToString(); 134 } 135 136 #endregion 137 138 #endregion 139 #region ================修改====================== 140 /// <summary> 141 /// 修改用户邮箱 142 /// </summary> 143 /// <param name="userName">用户名</param> 144 /// <param name="mobile">手机号</param> 145 /// <param name="email">新邮箱</param> 146 /// <param name="db">数据库操作对象</param> 147 /// <returns>bool</returns> 148 public bool EditEmail(string userName, string mobile,string email, Database db = null) 149 { 150 if (db == null) db = this.db; 151 string sql = "update dsxy_users set email=@0 where user_name = @1 and mobile = @2 "; 152 var res = db.Execute(sql, email, userName, mobile); 153 return res.ToBool(); 154 } 155 156 /// <summary> 157 /// 修改用户登录时间 158 /// </summary> 159 /// <param name="id">用户id</param> 160 /// <param name="db"></param> 161 /// <returns></returns> 162 public bool EditLoginTime(int id, Database db = null) 163 { 164 if (db == null) db = this.db; 165 string sql = "update dsxy_users set logintime=@0 where id=@1 "; 166 var res = db.Execute(sql, DateTime.Now, id); 167 return res.ToBool(); 168 } 169 #endregion 170 #region ================添加====================== 171 172 /// <summary> 173 /// 添加用户(返回成功失败) 174 /// </summary> 175 /// <param name="userName">用户名</param> 176 /// <param name="mobile">手机号</param> 177 /// <param name="pwd">密码</param> 178 /// <param name="db">数据库操作对象</param> 179 /// <returns>用户id</returns> 180 public bool AddUser(string userName, string mobile, string pwd, Database db = null) 181 { 182 if (db == null) db = this.db; 183 string sql = "insert into dsxy_users(user_name,mobile,password)values(@0,@1,@2) "; 184 var res = db.Execute(sql, userName, mobile,pwd); 185 return res.ToBool(); 186 } 187 188 #endregion 189 #region ================删除====================== 190 /// <summary> 191 /// 删除用户 192 /// </summary> 193 /// <param name="userName">用户名</param> 194 /// <param name="mobile">手机号</param> 195 /// <param name="db">数据库操作对象</param> 196 /// <returns>bool</returns> 197 public bool Del(string userName, string mobile,Database db = null) 198 { 199 if (db == null) db = this.db; 200 string sql = "delete dsxy_users where user_name = @0 and mobile = @1 "; 201 var res = db.Execute(sql, userName, mobile); 202 return res.ToBool(); 203 } 204 #endregion 205 #endregion 206 207 #endregion 208 209 #region ((((((((((((((((((((((业务逻辑)))))))))))))))))))))))))))) 210 public string Login(string username, string userpwd, string code,string codes) 211 { 212 Validation vali = new Validation(); 213 var res = vali.v_login(username, userpwd, code, codes); 214 //记录最近登录时间,无ip验证,单点登录 215 return res; 216 } 217 218 219 public users Login(string username, string userpwd) 220 { 221 Common common = new Common(); 222 users m_user = d_user.GetModel(new Dsxy.DTO.Dtb_Users() { user_name = username, password = common.md5(userpwd) });//普通登录 223 if (m_user == null) 224 { 225 m_user = d_user.GetModel(new Dsxy.DTO.Dtb_Users() { mobile = username, password = common.md5(userpwd) });//手机号码登陆 226 } 227 if (m_user != null) 228 { 229 //保存用户状态 230 Cookies.OYY_TOKEN = Rule.CreateToken(m_user.id); 231 } 232 return m_user; 233 } 234 235 236 237 public string m_Login(string mobile, string model_code) 238 { 239 Validation vali = new Validation(); 240 var res = vali.v_m_login(mobile,model_code); 241 if (res == "1") 242 { 243 m_Login(mobile); 244 } 245 return res; 246 } 247 248 public users m_Login(string mobile) 249 { 250 users m_user = d_user.GetModel(new Dsxy.DTO.Dtb_Users() { mobile = mobile });//手机号登录 251 if (m_user == null) 252 { 253 //这里只需注册逻辑(委托) 254 Delegates.dg_register dg_reg = new Delegates.dg_register(register); 255 int userid = dg_reg(mobile); 256 m_user = GetModel(userid); 257 } 258 //保存用户状态 259 Cookies.OYY_TOKEN = Rule.CreateToken(m_user.id); 260 return m_user; 261 } 262 263 public string register(string username, string mobile, string code, string pwd, string pwds) 264 { 265 Validation vali = new Validation(); 266 var res = vali.v_register(username, mobile,code,pwd,pwds); 267 if (res == "1") 268 { 269 register(mobile); 270 } 271 return res; 272 } 273 274 /// <summary> 275 /// 注册逻辑,返回用户id 276 /// </summary> 277 /// <param name="mobile"></param> 278 /// <param name="username"></param> 279 /// <param name="pwd"></param> 280 /// <returns></returns> 281 public int register(string mobile,string username = null, string pwd = null) 282 { 283 users m_user = new users(); 284 m_user.group_id = 1; 285 Random r = new Random(); 286 var sjs = "oyy" + r.Next(1000, 9999).ToString(); 287 m_user.user_name = username.IsNull()?mobile:username; 288 m_user.password = pwd; 289 m_user.mobile = mobile; 290 m_user.nick_name = username.IsNull() ? sjs : username; 291 m_user.reg_time = DateTime.Now; 292 m_user.reg_ip = common.Utils.getIp(); 293 m_user.LoginTime = DateTime.Now; 294 var res = Add(m_user); 295 if (res.ToBool()) 296 { 297 //保存用户状态 298 Cookies.OYY_TOKEN = Rule.CreateToken(m_user.id); 299 } 300 return res; 301 } 302 public string retrievepwd(string mobile, string code, string pwd, string pwds) 303 { 304 Validation vali = new Validation(); 305 var res = vali.v_retrievepwd(mobile, code, pwd, pwds); 306 if (res == "1") 307 { 308 retrievepwd(mobile,pwd); 309 } 310 return res; 311 } 312 313 /// <summary> 314 /// 找回密码逻辑 315 /// </summary> 316 /// <param name="mobile"></param> 317 /// <param name="pwd"></param> 318 /// <returns></returns> 319 public bool retrievepwd(string mobile,string pwd) 320 { 321 Common com = new Common(); 322 users m_user = GetModel(new Dtb_Users() { mobile = mobile }); 323 m_user.password = com.md5(pwd); 324 var res = Edit(m_user); 325 return res; 326 } 327 /// <summary> 328 /// 获取用户登录对象,没有则返回null 329 /// </summary> 330 /// <returns></returns> 331 public users GetUser() 332 { 333 Validation b_vali = new Validation(); 334 users m_user = b_vali.v_Authorization(); 335 return m_user; 336 } 337 #endregion
第一块是数据操作,数据操作分两个区域,公共方法区(封装了操作DAL的一些公共方法,增删改查 分页 排序),拓展方法区(可以通过手动编写sql来实现一些复杂的sql操作),这里的底层我使用的是PetaPoco,感兴趣的可以去学习下,还是非常便捷的,DAL我根据PetaPoco进行了一些拓展,让它能够更友好的调用PetaPoco,新增了一个层DTO(一个参数列表,每个Model都有一个与它对应的DTO,BLL,DAL),为此我特意写了一套简单的生成模板代码,可以根据表直接生成DTO,BLL,DAL,Model.
第二块是业务逻辑,UI需要操作哪些数据,我们就写对应的方法就可以了,这里的方法只是单纯的访问数据,遇到复杂逻辑注意要写事务,在关联的主表的BLL里面写对应的方法,调用别的BLL里的一些逻辑方法,让每个BLL职责单一
流程如下:UI调用BLL的业务逻辑function,BLL的业务逻辑function调用BLL的数据访问function
当框架搭好之后(基本都是直接生成),工作的时间花费30%为前端,60%为业务逻辑,后期的拓展也只是新增业务逻辑里的function即可!