• Linq行转列


    通过企业微信返回的打卡数据,数据是那种打一次卡,就有一次记录的格式。

    表结构为

    CREATE TABLE t_Checkindata
    (
    Cid int identity(1,1) primary key,
    userid varchar(10), --用户id
    groupname varchar(50), --打卡规则名称
    checkin_type varchar(20), --打卡类型。字符串,目前有:上班打卡,下班打卡,外出打卡
    exception_type varchar(100), --异常类型,字符串,包括:时间异常,地点异常,未打卡,wifi异常,非常用设备。如果有多个异常,以分号间隔
    checkin_time int --打卡时间戳
    )
    表结构非常简单,但是在前端展示数据时,反馈不清晰。根据对userid分组,使员工每天上下班打卡的时间能够同行显示。

    一、Linq 子查询行转列

              var query = from c in db.t_Checkindatas
                                        where (c.checkin_time < EndTime && c.checkin_time > StartTime && (c.t_Users.UserDepart == depart || c.t_Users.CorpName == depart))
                                        orderby c.checkin_time descending
                                        group c by c.userid into g
                                        select new
                                        {
                                            userid = g.Key,
                                            groupname = g.Select(u => u.groupname).FirstOrDefault(),
                                            exception_type = g.Select(u => u.exception_type).FirstOrDefault(),
                                            上班打卡 = (from d in g
                                                    where d.checkin_type == "上班打卡"
                                                    select d.checkin_time).Min(),
                                            下班打卡 = (from d in g
                                                    where d.checkin_type == "下班打卡"
                                                    select d.checkin_time).Max()

     

    对于代码中的where条件可以忽略,我这里是根据所选的部门和日期来筛选哪天的数据。

    返回exception_type的值处理有点问题,因为同一个人的打卡数据上午的打卡记录是正常的,下午因为忘记了而未打卡。

    此时两条数据,上午正常打卡返回的值为空,而下午返回的值为未打卡。所以对整天的数据进行降序排列,利用FirstOrDefault返回第一个序列的值。

    二、Linq 实现DataTable行转列

    因水平有限,我原始数据为List,这个解决方法是查找此类问题时,找到一位前辈多年前写过的博客,依葫芦画瓢,照搬下来解决的。

    所以怎么办呢,我得先把我List数据转为DataTable,头又疼了,这怎么转呢?请手动打开百度,搜索此标题。。。留下了没有技术的眼泪.jpg

            /// <summary>
            /// 将类型为list的打卡数据行转列后返回datatable
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="list">原始打卡数据</param>
            /// <returns></returns>
            public static DataTable ToDatatable3<T>(List<T> list)
            {
                using (MVCDBAdmin db = new MVCDBAdmin())
                {
                    DataTable source = ToDataTable2(list);//List转为DataTable
    
                    DataTable dt = new DataTable();
                    dt.Columns.Add("userid");
                    dt.Columns.Add("groupname");
                    dt.Columns.Add("exception_type");
    
                    var columns = (from x in source.Rows.Cast<DataRow>() select x[3].ToString()).Distinct();
                    foreach (var item in columns)
                    {
                        dt.Columns.Add(item).DefaultValue = 0;
                    }
                    var data = from x in source.Rows.Cast<DataRow>()
                               group x by x[0] into g
                               select new { Key = g.Key.ToString(), Items = g };
                    data.ToList().ForEach(x =>
                    {
                        string[] array = new string[dt.Columns.Count];
                        array[0] = x.Key;
                        array[1] = x.Items.ToList<DataRow>()[0]["groupname"].ToString();
                        array[2] = x.Items.ToList<DataRow>()[0]["exception_type"].ToString();
                        for (int i = 3; i < dt.Columns.Count; i++)
                        {
                            array[i] = (from y in x.Items
                                        where y[3].ToString() == dt.Columns[i].ToString()
                                        select y[4].ToString()
                                       ).FirstOrDefault(); //SingleOrDefault 若返回多个元素会发生异常
                            //如上班卡迟到,因为忘记打卡而申请补打,此时会有2条上班卡的记录,将引起报错
                            //暂使用FirstOrDefault返回打卡时间最早的那条记录,补卡申请完成后,系统会自动设置上班卡为标准起始时间
                        }
                        dt.Rows.Add(array);
                    }); 
                    return dt;
                }
            } 

    行转列完成后,我又将DataTable转换成List返回给前台。这绕来绕去的,有点无奈。

    参考博客地址:

    Linq DataTable行转列 https://www.cnblogs.com/li-peng/archive/2012/02/27/2370213.html#commentform

    关于List和DataTable 互相转换 https://www.cnblogs.com/shiyh/p/7478241.html

     

  • 相关阅读:
    Java 正则表达式
    Java 设计模式系列(二三)访问者模式(Vistor)
    Java 设计模式系列(十五)观察者模式(Observer)
    Java 设计模式系列(十八)备忘录模式(Memento)
    Java 设计模式系列(二十)状态模式
    Java 设计模式系列(十五)迭代器模式(Iterator)
    Java 设计模式系列(十三)模板方法
    Java 设计模式系列(十二)策略模式(Strategy)
    Java 设计模式系列(二二)责任链模式
    Java 设计模式系列(十四)命令模式(Command)
  • 原文地址:https://www.cnblogs.com/qinsikao/p/12462041.html
Copyright © 2020-2023  润新知