• LINQ查询返回DataTable类型[轉]與将DataTable序列化为Json格式【轉】


    (原文地址:http://xuzhihong1987.blog.163.com/blog/static/26731587201101853740294/)

    LINQ查询返回DataTable类型  

    在使用LINQ查询的时候,一般我们会返回List<T>或IList<T>类型,如下所示:

    例1:

            public List<TSample> GetList()

            {

                using (BPDataContext db = newBPDataContext(TCTC_ConnectionStrings.connStr))

                {

                    var q = from p in db.TSample

                            select p;

                    return q.ToList();

                }

            }

    例1实现的是一个最简单的列表查询,返回的是List<TSample>类型,本身没有任何问题!但是如果现在希望查询TSample表中的指定几列,代码应该是:

    var q = from p in db.TSample

               select new

              {

                     p.FID,

                     p.FName

              };

    return q.ToList();

    现在问题是返回类型该写什么呢?new{p.FID,p.FName}已经不是TSample类型了,又不支持返回值为List<T>的!

     

     

    可能的解决方案是:

    方法一:

    先扩展一个类SampleEx

        public class SampleEx

        {

            public Guid FID

            {

                get;

                set;

            }

            public string FName

            {

                get;

                set;

            }

        }

    然后返回List<SampleEx>类型

            public List<SampleEx> GetList()

            {

                using (BPDataContext db = newBPDataContext(TCTC_ConnectionStrings.connStr))

                {

                    var q = from p in db.TSample

                            select new SampleEx()

                            {

                                FID = p.FID,

                                FName = p.FName

                            };

                    return q.ToList();

                }

            }

    这样就达到了我们想要的目标。

     

    问题是解决了,但是再仔细想想这样的解决方案似乎可行性不强。因为在实际开发中我们经常查询两个表join查询,那么重新组合的字段就比较多了,要每个都去扩展单独的类,工作量太大!有些人可能会想到用试图,然后dbml会自动帮我们生成类,但是这个工作量也应该不小,天天建试图,要频繁跟新dbml文件的方式不怎么合理!最期望的方式就是不用构造自定义类型,经过转换返回我们需要的类型!

         下面通过一个方法来实现返回DataTable类型:

            /// <summary>

            /// LINQ返回DataTable类型

            /// </summary>

            /// <typeparam name="T"> </typeparam>

            /// <param name="varlist"> </param>

            /// <returns> </returns>

            public static DataTable ToDataTable<T>(IEnumerable<T> varlist)

            {

                DataTable dtReturn = new DataTable();

     

                // column names

                PropertyInfo[] oProps = null;

     

                if (varlist == null)

                    return dtReturn;

     

                foreach (T rec in varlist)

                {

                    if (oProps == null)

                    {

                        oProps = ((Type)rec.GetType()).GetProperties();

                        foreach (PropertyInfo pi in oProps)

                        {

                            Type colType = pi.PropertyType;

     

                            if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition()

                                 == typeof(Nullable<>)))

                            {

                                colType = colType.GetGenericArguments()[0];

                            }

     

                            dtReturn.Columns.Add(new DataColumn(pi.Name, colType));

                        }

                    }

     

                    DataRow dr = dtReturn.NewRow();

     

                    foreach (PropertyInfo pi in oProps)

                    {

                        dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value :pi.GetValue

                        (rec, null);

                    }

     

                    dtReturn.Rows.Add(dr);

                }

                return dtReturn;

            }

     

     

    如何使用?如下示例:

            /// <summary>

            /// 根据获取多个器具信息

            /// </summary>

            /// <param name="IDs"></param>

            /// <returns></returns>

            public DataTable GetByIDs(List<string> IDs)

            {

                using (BPDataContext db = newBPDataContext(TCTC_ConnectionStrings.connStr))

                {

                    var p = (from c in db.TSample

                             where IDs.Contains(c.FID.ToString())

                             select new

                             {

                                 c.FID,

                                 c.FName,

                                 c.FCode,

                                 c.FType,

                                 c.FProductUnit,

                                 c.FDeviceNo

                             }).ToList();

                    return LinqToDataTable.ToDataTable(p);

                }

            }

        到这里就达到了我们预期的方式!返回DataTable,那么对后面数据源直接绑定,或序列化为Json都非常方便了!

     

    序列化DataTable为Json格式的方法直接用微软的JavaScriptSerializer.Serialize()方法是会有问题的,我们需要自己写方法序列化,

    序列化代码详见:http://xuzhihong1987.blog.163.com/blog/static/26731587201101913722238/

     

    将DataTable序列化为Json格式

    很多时候我们希望将查询出的数据源格式(如:List<T>DataTable等)转换为Json格式,便于前台的JS的处理,尤其是在使用Extjs框架的时候,JsonStore异步(Ajax)请求的数据格式就是Json,那么后台序列化的就显得非常重要!

    当然序列化很简单,因为微软已经提供了序列化的方法,在引用命名空间(using System.Web.Script.Serialization;)后,即可使用内置的JavaScriptSerializer. Serialize()方法,使用方式如下:

    JavaScriptSerializer jss = new JavaScriptSerializer();

    string  strJson = jss.Serialize(t); //T t为泛型

    一般类型都能顺利序列化,但是如果此时传入的类型T为DataTable,那么就会发生异常了,出现”序列化类型为“System.Reflection.Module”的对象时检测到循环引用。的错误提示.

    将DataTable序列化为Json格式 - 飞天心宏 - 飞天心宏的博客

     

     

    究其原因,猜测可能是DataTable的成员DataRowTable属性又引用了DataTable本身,真正原因我没去分析。下面提供一种解决方式:

    /*

    * Copyright: Copyright: ?2010 Twilight软件开发工作室

    * Author: xuzhihong

    * Create date: 2010-3-24

    * Description: 将DataTable转换JSON对象

    *

    */

     

        public class ConventDataTableToJson

        {

              /// <summary>

               /// 序列化方法(带分页)

               /// </summary>

               /// <param name="dt"></param>

              /// <returns></returns>

            public static string Serialize(DataTable dt)

            {

                List<Dictionary<string, object>> list = newList<Dictionary<string, object>>();

                foreach (DataRow dr in dt.Rows)

                {

                    Dictionary<string, object> result = new Dictionary<string,object>();

                    foreach (DataColumn dc in dt.Columns)

                    {

                        result.Add(dc.ColumnName, dr[dc].ToString());

                    }

                    list.Add(result);

                }

                int count = 0;

                try

                {

                    count = Convert.ToInt32(dt.TableName);

                }

                catch (System.Exception ex)

                {

                    count = dt.Rows.Count;

                }

                string strReturn = "";

                if (count == 0)

                {

                    strReturn = "{"totalCount":0,"data":[]}";

                }

                else

                {

                    strReturn = ConventToJson(list, count);

                }

                return strReturn;

            }

     

            /// <summary>

            /// 转换为JSON对象

            /// </summary>

            /// <returns></returns>

            public static string ConventToJson<T>(List<T> list, int count)

            {

                JavaScriptSerializer serializer = new JavaScriptSerializer();

                string strJson = serializer.Serialize(list);

                strJson = strJson.Substring(1);

                strJson = strJson.Insert(0, "{totalCount:" + count + ",data:[");

                strJson += "}";

     

                return strJson;

            }

     

            /// <summary>

            /// 不需要分页

            /// </summary>

            /// <param name="dt"></param>

            /// <param name="flag">false</param>

            /// <returns></returns>

            public static string Serialize(DataTable dt,bool flag)

            {

                JavaScriptSerializer serializer = new JavaScriptSerializer();

                List<Dictionary<string, object>> list = newList<Dictionary<string, object>>();

                foreach (DataRow dr in dt.Rows)

                {

                    Dictionary<string, object> result = new Dictionary<string,object>();

                    foreach (DataColumn dc in dt.Columns)

                    {

                        result.Add(dc.ColumnName, dr[dc].ToString());

                    }

                    list.Add(result);

                }

                return serializer.Serialize(list); ;

            }

    }

     

     

     

    原理非常简单,主要思想就是利用Dictionary<string, object>字典,将DataRow属性名/值存储在List<Dictionary<string, object>>中,这样List<T>是能被正常序列化的。

     

    说明:在带分页的序列化方法,我做了一个格式设置,主要是为了序列化为Extjs的JsonStore要求的格式,序列化的Json字符串如下:(下面的字符串只有一条记录)

    {totalCount:1,data:[{"FID":"71e78220-8074-4f17-9f7b-c2413bf0ac4e","FTaskID":"b4f42e8e-a457-424c-888c-b874128ffb57","FTaskCode":"20110119-01","FTestItemID":"9a8c3c7a-f8c2-41f0-a279-4d50575f5f89","FTestItemName":"盖总成分离指安装高度及分离指端面跳动量测定","FAssignTag":"0","FTestCompleteTag":"0","FType":"1","FReTestTag":"1","FReTestFromTag":"1","FHasOriginalFile":"0","FInSampleNumber":"","FSerialNumber":"","FTestRemark":"","FReceiver":"","FReceiveTime":"","FEndTag":"1","FSampleModel":"234","FIsUrgent":"0","FSampleName":"","RowNumber":"1"}]}

     

    其中:totalCount和dat对应JS的totalProperty和root配置项。

            var store = new Ext.data.JsonStore({

                proxynew Ext.data.HttpProxy({ urlVars.Url}),

                idProperty'FID',

                root'data',

                totalProperty'totalCount',

                fields: ['FID''FCode''FDuName''FSampleName'],

                baseParams: { sign'GetByCondition'start: 0, limitVars.PageSizeconditionExt.encode(Vars.Condition) }

            });

     

                                                                                                             飞天心宏  2011-01-19

  • 相关阅读:
    第1课 Git、谁与争锋
    程序员最真实的10个瞬间
    程序员最真实的10个瞬间
    一文读懂前端缓存
    一文读懂前端缓存
    一文读懂前端缓存
    EF使用CodeFirst创建数据库和表
    EF使用CodeFirst创建数据库和表
    EF使用CodeFirst创建数据库和表
    ASP.NET MVC的过滤器笔记
  • 原文地址:https://www.cnblogs.com/keepee/p/8615047.html
Copyright © 2020-2023  润新知