LayIM项目之基础数据获取代码优化,Dapper取代ADO.NET
前言
最近在开发LayIM融云版,也在进行项目重构,现在在看之前的代码,简直不敢直视。不过不知道以后看现在的代码是不是也是糟糕的一批。LayIM有个接口,一般接触过的开发人员都不会生疏,就是init接口。接口返回的数据大概就是酱紫的:
 {
     "code": 0,
     "msg": "",
     "data": {
         "mine": {
             "username": "纸飞机",
             "id": "100000",
             "status": "online",
             "sign": "在深邃的编码世界,做一枚轻盈的纸飞机",
             "avatar": "/images/default.jpg"
         },
         "friend": [
             {
                 "groupname": "前端码屌",
                 "id": 1,
                 "online": 2,
                 "list": [
                     {
                         "username": "贤心",
                         "id": "100001",
                         "avatar": "/images/default.jpg",
                         "sign": "这些都是测试数据,实际使用请严格按照该格式返回"
                     },
                     {
                         "username": "Z_子晴",
                         "id": "108101",
                         "avatar": "/images/default.jpg",
                         "sign": "微电商达人"
                     }
                 ]
             },
             {
                 "groupname": "网红",
                 "id": 2,
                 "online": 3,
                 "list": [
                     {
                         "username": "罗玉凤",
                         "id": "121286",
                         "avatar": "/images/default.jpg",
                         "sign": "在自己实力不济的时候,不要去相信什么媒体和记者。他们不是善良的人,有时候候他们的采访对当事人而言就是陷阱"
                     },
                     {
                         "username": "长泽梓Azusa",
                         "id": "100001222",
                         "sign": "我是日本女艺人长泽あずさ",
                         "avatar": "/images/default.jpg"
                     }
                 ]
             }
         ],
         "group": [
             {
                 "groupname": "前端群",
                 "id": "101",
                 "avatar": "/images/default.jpg"
             },
             {
                 "groupname": "Fly社区官方群",
                 "id": "102",
                 "avatar": "/images/default.jpg"
             }
         ]
     }
 }
LayIM init接口数据
总之,里面嵌套了很多关系,比如,我的好友分组和好友的关系,还有其他的一些数据,其实,仔细分析一下,也就会各个击破了。今天的重点不是这个数据,而是关于获取这段数据代码的重构。
之前的代码
之前用的ADO.NET直接读取的DataSet,然后进行数据处理,主要麻烦的是,还需要手动写DataTable转Model的过程,还要处理关系,比较繁琐,并且需要知道其中的字段。(当然,dapper也需要对应)。先看一下之前的代码,总之这段代码就是很古老的一种形式。
private BaseListResult ToBaseListResult(DataSet ds)
{
if (ds.Tables.Count > )
{
if (ds.Tables[].Rows.Count ==) {
return new BaseListResult();
}
//当前用户的信息
var rowMine = ds.Tables[].Rows[];
//用户组信息
var rowFriendDetails = ds.Tables[].Rows.Cast<DataRow>().Select(x => new GroupUserEntity
{
id = x["uid"].ToInt(),
avatar = x["avatar"].ToString(),
groupid = x["gid"].ToInt(),
remarkname = x["remarkname"].ToString(),
username = x["nickname"].ToString(),
sign = x["sign"].ToString(),
//status之前的字段是为空的,现在我们把他的在线状态加上,IsOnline方法接收一个userid参数,从Redis缓存中读取该用户是否在线并返回
status = LayIMCache.Instance.IsOnline(x["uid"].ToInt()) ? "online" : "hide"
}).OrderByDescending(x => x.status);//这里要根据用户是否在线这个字段排序,保证在线用户都在好友列表最上边
//用户组信息,执行分组
var friend = ds.Tables[].Rows.Cast<DataRow>().Select(x => new FriendGroupEntity
{
id = x["id"].ToInt(),
groupname = x["name"].ToString(),
online = ,
list = rowFriendDetails.Where(f => f.groupid == x["id"].ToInt())
});
//群组信息
var group = ds.Tables[].Rows.Cast<DataRow>().Select(x => new GroupEntity
{
id = x["id"].ToInt(),
groupname = x["name"].ToString(),
avatar = x["avatar"].ToString(),
groupdesc = x["groupdesc"].ToString()
});
//用户皮肤,第一个是默认正在使用的
List<string> skin = ds.Tables[].Rows.Cast<DataRow>().Select(x => x[].ToString()).ToList(); BaseListResult result = new BaseListResult
{
mine = new UserEntity
{
id = rowMine["id"].ToInt(),
avatar = rowMine["avatar"].ToString(),
sign = rowMine["sign"].ToString(),
username = rowMine["nickname"].ToString(),
status = "online"
},
friend = friend,
group = group,
skin = skin
};
return result;
}
return null;
}
下面,我们改用Dapper试试。重构过程先不谈,看一下重构后的代码处理:
public BaseListResult Handle(SqlMapper.GridReader reader)
{
var result = new BaseListResult();
//用户本人数据
result.mine = reader.ReadFirst<UserEntity>();
//处理friend逻辑 start
var friend = reader.Read<FriendGroupEntity>();
var groupUsers = reader.Read<GroupUserEntity>();
friend.ToList().ForEach(f =>
{
//每一组的人分配给各个组
f.list = groupUsers?.Where(x => x.groupid == f.id);
});
result.friend = friend;
//处理friend逻辑 end
//读取用户所在群
result.group = reader.Read<GroupEntity>();
return result;
}
Dapper相较于ADO.NET比起来,就清爽多了,首先,处理GridReader,然后直接调用Read<T>方法,直接将表值转换为Model,不过Model的值需要对应。然后转换完之后,在进行一步逻辑处理,就是将相应的用户跟好友分组的id对应上。最后一个返回,这样看起来就清爽了许多,也不用处理的很麻烦。下文记录一下我的开发思路。
代码思路
首先要解决一个问题就是,解耦的问题,Dapper中有一个方法就是 QueryMultiple ,他是返回一个GridReader 对象,然后进行处理。那么这个GridReader对象又必须在连接开着的时候使用,所以,不能直接返回然后关闭对象,所以,可以采用接口的形式,将处理方法提出去,或者,我刚才恰好想到的就是用Func<SqlMapper.GridReader,TResult> 方式来处理结果。我的代码如下:
public static T QueryMultiple<T>(string sql, object param,CommandType commandType = CommandType.Text, IMultipleHandler<T> handler=null)
{
using (var connection = getConnection())
{
using (var multi = connection.QueryMultiple(sql, param,commandType: commandType))
{
if (handler == null) {
return default(T);
}
return handler.Handle(multi);
}
}
}
其中的IMultipleHandler 中就一个方法,Handle方法,参数为GridReader。然后返回 T类型的结果。所以上文中,我的调用方式很简单了,就是传入相应的处理类就可以了。
public class UserBaseListHandler : IMultipleHandler<BaseListResult>
其实我刚才突然想到,或许用Func更方便。不用再定义类继承接口了。此篇,Over,重构代码确实是有意思的事情,后续我会将各种体会做总结,如果能和读者产生共鸣那是最好不过的了。
LayIM项目之基础数据获取代码优化,Dapper取代ADO.NET的更多相关文章
- Asp.Net Core 项目搭建 基础配置 和MySql 的使用
		一.开发环境准备 1.安装Visual Studio 2015,我这里安装的是专业版. 2.安装.NET Core SDK相关 需要安装 Visual Studio 2015 update3和NET ... 
- 从零一起学Spring Boot之LayIM项目长成记(四) Spring Boot  JPA 深入了解
		前言 本篇内容主要是一些关于JPA的常用的一些用法等.内容也是很多是看其他博客学来的,顺道在本系列博客里抽出一篇作为总结.下面让我们来看看吧. 不过我更推荐大家读本篇:https://lufficc. ... 
- 从零一起学Spring Boot之LayIM项目长成记(三) 数据库的简单设计和JPA的简单使用。
		前言 今天是第三篇了,上一篇简单模拟了数据,实现了LayIM页面的数据加载.那么今天呢就要用数据库的数据了.闲言少叙,书归正传,让我们开始吧. 数据库 之前有好多小伙伴问我数据库是怎么设计的.我个人用 ... 
- 从零一起学Spring Boot之LayIM项目长成记(二) LayIM初体验
		前言 接上篇,已经完成了一个SpringBoot项目的基本搭建.那么现在就要考虑要做什么,怎么做的问题.所以本篇内容不多,带大家一起来简单了解一下要做的东西,之前有很多人不知道从哪里下手,那么今天我带 ... 
- 从零一起学Spring Boot之LayIM项目长成记(一) 初见 Spring Boot
		项目背景 之前写过LayIM的.NET版后端实现,后来又写过一版Java的.当时用的是servlet,websocket和jdbc.虽然时间过去很久了,但是仍有些同学在关注.偶然间我听说了Spring ... 
- Karaf 依赖equinox and felix,karaf 本Apache的很多项目作为基础框架
		6月17日是Apache Karaf作为Apache顶级项目.Karaf是个运行时包,包含了一个OSGi框架(Equinox或Felix).一个命令shell(Felix Gogo)及默认情况下内置的 ... 
- VC项目配置基础以及快捷键(收藏)
		来自http://blog.csdn.net/phunxm/article/details/5082488 一.IDE基础配置 1.字体 VC6中“Tools→Options→Format→Font” ... 
- 从零一起学Spring Boot之LayIM项目长成记(五)websocket
		前言 距离上一篇已经比较久的时间了,项目也是开了个头.并且,由于网上的关于Spring Boot的websocket讲解也比较多.于是我采用了另外的一个通讯框架 t-io 来实现LayIM中的通讯功能 ... 
- Go推出的主要目的之一就是G内部大东西太多了,系统级开发巨型项目非常痛苦,Go定位取代C++,Go以简单取胜(KISS)
		以前为了做compiler,研读+实现了几乎所有种类的语言.现在看语法手册几乎很快就可以理解整个语言的内容.后来我对比了一下go和rust,发现go的类型系统简直就是拼凑的.这会导致跟C语言一样,需要 ... 
随机推荐
- vuex 实现vue中多个组件之间数据同步以及数据共享。
			http://pan.baidu.com/s/1hrJfpli demo下载地址 前言 在一些项目中有很多数据状态之间要实现数据共享状态共享,例如购物车的数据.用户的登录状态等等.vue父元素是可以 ... 
- golang获取变量数据类型
			如果某个函数的入参是interface{},有下面几种方式可以获取入参的方法: 1 fmt: import "fmt" func main() { v := "hello ... 
- mysql自定义变量
			mysql可以实现自定义变量,使用方式非常简单,代码如下: SELECT @i:=@i + 1 // 查询变量,值+1 FROM () i // 声明变量,初始值为0 如果有多条数据,那么这个变量就会 ... 
- javaEE Design Patter(2)详解3个设计模式
			Factory (bean creating) Proxy(Agent)(Aop)书有~ Templete(springMVC Facelets)//此处及以上忽略 工厂模式(Factory) 工厂模 ... 
- Javaweb之EL表达式
			1.EL表达式简介 EL全名为Expression Language.EL的主要作用为: 获取数据:EL表达式主要用于替换jsp页面中的脚本表达式,以从各种类型的web域中检索java对象,获取数据. ... 
- ApplicationHost.config文件被破坏导致IIS崩溃
			“”Application Host Helper Service 在尝试删除历史目录“C:\inetpub\history\CFGHISTORY_0000000475”时遇到错误.将跳过并忽略此目录 ... 
- 谈谈我从工作中理解的CDN
			一.CDN定义 CDN的全称是Content Delivery Network,即内容分发网络.其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快.更稳定.通过 ... 
- PL/SQL 快速连接数据库
			打开PL/SQL 登录窗口,在数据库地址写入 服务器名:端口号/sid 即可, 例如: 192.168.100.100:1521/test 
- Python-网络编程(一)
			首先我们python基础部分已经学完了,而socket是我们基础进阶的课程,也就是说,你自己现在完全可以写一些小程序了,但是前面的学习和练习,我们写的代码都是在自己的电脑上运行的,虽然我们学过了模块引 ... 
- HTML5学习笔记之canvas
			标签 canvas标签有一个默认宽高:300*150: canvas的宽高一般写到行间样式中,写在style会有问题详细请看这里: 绘制环境 要绘图先要获取到绘制环境: var oC = docume ... 
