zoukankan      html  css  js  c++  java
  • LayIM项目之基础数据获取代码优化,Dapper取代ADO.NET

    前言

      最近在开发LayIM融云版,也在进行项目重构,现在在看之前的代码,简直不敢直视。不过不知道以后看现在的代码是不是也是糟糕的一批。LayIM有个接口,一般接触过的开发人员都不会生疏,就是init接口。接口返回的数据大概就是酱紫的:

     1 {
     2     "code": 0,
     3     "msg": "",
     4     "data": {
     5         "mine": {
     6             "username": "纸飞机",
     7             "id": "100000",
     8             "status": "online",
     9             "sign": "在深邃的编码世界,做一枚轻盈的纸飞机",
    10             "avatar": "/images/default.jpg"
    11         },
    12         "friend": [
    13             {
    14                 "groupname": "前端码屌",
    15                 "id": 1,
    16                 "online": 2,
    17                 "list": [
    18                     {
    19                         "username": "贤心",
    20                         "id": "100001",
    21                         "avatar": "/images/default.jpg",
    22                         "sign": "这些都是测试数据,实际使用请严格按照该格式返回"
    23                     },
    24                     {
    25                         "username": "Z_子晴",
    26                         "id": "108101",
    27                         "avatar": "/images/default.jpg",
    28                         "sign": "微电商达人"
    29                     }
    30                 ]
    31             },
    32             {
    33                 "groupname": "网红",
    34                 "id": 2,
    35                 "online": 3,
    36                 "list": [
    37                     {
    38                         "username": "罗玉凤",
    39                         "id": "121286",
    40                         "avatar": "/images/default.jpg",
    41                         "sign": "在自己实力不济的时候,不要去相信什么媒体和记者。他们不是善良的人,有时候候他们的采访对当事人而言就是陷阱"
    42                     },
    43                     {
    44                         "username": "长泽梓Azusa",
    45                         "id": "100001222",
    46                         "sign": "我是日本女艺人长泽あずさ",
    47                         "avatar": "/images/default.jpg"
    48                     }
    49                 ]
    50             }
    51         ],
    52         "group": [
    53             {
    54                 "groupname": "前端群",
    55                 "id": "101",
    56                 "avatar": "/images/default.jpg"
    57             },
    58             {
    59                 "groupname": "Fly社区官方群",
    60                 "id": "102",
    61                 "avatar": "/images/default.jpg"
    62             }
    63         ]
    64     }
    65 }
    LayIM init接口数据

      总之,里面嵌套了很多关系,比如,我的好友分组和好友的关系,还有其他的一些数据,其实,仔细分析一下,也就会各个击破了。今天的重点不是这个数据,而是关于获取这段数据代码的重构。

    之前的代码

      之前用的ADO.NET直接读取的DataSet,然后进行数据处理,主要麻烦的是,还需要手动写DataTable转Model的过程,还要处理关系,比较繁琐,并且需要知道其中的字段。(当然,dapper也需要对应)。先看一下之前的代码,总之这段代码就是很古老的一种形式。

     private  BaseListResult ToBaseListResult(DataSet ds)
            {
                if (ds.Tables.Count > 0)
                {
                    if (ds.Tables[0].Rows.Count ==0) {
                        return new BaseListResult();
                    }
                    //当前用户的信息
                    var rowMine = ds.Tables[0].Rows[0];
                    //用户组信息
                    var rowFriendDetails = ds.Tables[2].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[1].Rows.Cast<DataRow>().Select(x => new FriendGroupEntity
                    {
                        id = x["id"].ToInt(),
                        groupname = x["name"].ToString(),
                        online = 0,
                        list = rowFriendDetails.Where(f => f.groupid == x["id"].ToInt())
                    });
                    //群组信息
                    var group = ds.Tables[3].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[4].Rows.Cast<DataRow>().Select(x => x[0].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,重构代码确实是有意思的事情,后续我会将各种体会做总结,如果能和读者产生共鸣那是最好不过的了。

  • 相关阅读:
    STM32F107的DAC配置
    步进电机工作原理
    winform笔记本蓝牙与外部蓝牙设备通信
    C#里三种强制类型转换
    IE6/7BUG之OL有序列表没顺序
    IE6/7BUG之列表UL楼梯
    IE6/7BUG之A超链接无效
    IE6/7BUG之overflow:hidden无效
    linux shell 管道命令(pipe)使用及与shell重定向区别
    UGUI研究院之全面理解图集与使用
  • 原文地址:https://www.cnblogs.com/panzi/p/6323728.html
Copyright © 2011-2022 走看看