(原文地址: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的成员DataRow的Table属性又引用了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({

proxy: new Ext.data.HttpProxy({ url: Vars.Url}),

idProperty: 'FID',

root: 'data',

totalProperty: 'totalCount',

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

baseParams: { sign: 'GetByCondition', start: 0, limit: Vars.PageSize, condition: Ext.encode(Vars.Condition) }

});

飞天心宏  2011-01-19

LINQ查询返回DataTable类型[轉]與将DataTable序列化为Json格式【轉】的更多相关文章

  1. LINQ查询返回DataTable类型

    个人感觉Linq实用灵活性很大,参考一篇大牛的文章LINQ查询返回DataTable类型 http://xuzhihong1987.blog.163.com/blog/static/267315872 ...

  2. 转:LINQ查询返回DataTable类型

    动态绑定ReportViewer虽然之前实现过,但现在弄起来还是有点晕,主要是过去没有使用Linq,数据的操作经常用到DataTable,可以直接拿来使用,现在用Linq更方便,也懒得再用之前的数据库 ...

  3. .NET LINQ查询操作中的类型关系

    LINQ 查询操作中的类型关系      若要有效编写查询,您应该了解完整的查询操作中的变量类型是如何全部彼此关联的. 如果您了解这些关系,就能够更容易地理解文档中的 LINQ 示例和代码示例. 另外 ...

  4. Hibernate应用SQL查询返回实体类型

    Hibernate应用SQL查询返回实体类型 Hibernate使用SQL查询返回实体类型 以前,使用SQL查询,结果放在 RS 结果集中,还要去转换影射到Java类中.Hibernate中,可以自动 ...

  5. 使用DataContractJsonSerializer类将类型实例序列化为JSON字符串和反序列化为实例对象 分类: JSON 前端 2014-11-10 10:20 97人阅读 评论(1) 收藏

    一.JSON简介 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式. JSON是"名值对"的集合.结构由大 ...

  6. 把Linq查询返回的var类型的数据 转换为DataTable EF连接查询

    问题:我要获得一个角色下对应的所有用户,需要两表连接查询,虽然返回的只有用户数据,但是我想到若是返回的不只是用户数据,而还要加上角色信息,那么我返回什么类型呢,返回var吗,这样不行. 于是我网上找找 ...

  7. C#3.0新增功能09 LINQ 基础06 LINQ 查询操作中的类型关系

    连载目录    [已更新最新开发文章,点击查看详细] 若要有效编写查询,应了解完整的查询操作中的变量类型是如何全部彼此关联的. 如果了解这些关系,就能够更容易地理解文档中的 LINQ 示例和代码示例. ...

  8. HQL查询——查询返回对象类型分析

    关于HQL查询,我们可以结合hibernate的API文档,重点围绕org.hibernate.Query接口,分析其方法,此接口的实例对象是通过通过session.对象的creatQuery(Str ...

  9. mybatis group by查询返回map类型

    故事的发生是这样的. . . . . . . 一天 我发现我们的页面显示了这样的汇总统计数据,看起来体验还不错哦-- 然后,我发现代码是这样滴:分开每个状态分别去查询数量. 额e,可是为嘛不使用简单便 ...

随机推荐

  1. ios系统的特点

    iOS优势 1). 比较稳定,因为他是一个完全封闭的系统,不开源,但是这个系统有他自己严格管理体系,比如app store的app应用:他有自己的评审规则,另外很多软件是需要收费的,这在一定程度上也说 ...

  2. 【C/C++】计算两个整数的最大公约数和最小公倍数

    算法一 任何>1的整数都可以写成一个或多个素数因子乘积的形式,且素数乘积因子以非递减序出现. 则整数x,y可以分别标记为:x=p1x1p2x2...pmxm y=p1y1p2y2...pmym ...

  3. BZOJ2120:数颜色(数状数组套主席树)(带修改的莫对)

    墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P ...

  4. HDU3440 House Man (差分约束)

    In Fuzhou, there is a crazy super man. He can’t fly, but he could jump from housetop to housetop. To ...

  5. codevs 2102 石子归并2

    传送门 2102 石子归并 2  时间限制: 10 s  空间限制: 256000 KB  题目等级 : 黄金 Gold   题目描述 Description 在一个园形操场的四周摆放N堆石子,现要将 ...

  6. bzoj 4260 Codechef REBXOR——trie树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4260 一段的异或和就是两个前缀的异或和.正反扫两边,用trie树算每个位置为左/右端点时最大 ...

  7. 23.java方法的深入

    深入: public class MethodTest05{ public static void main(String[] args){ int i=m1(ture); System.out.pr ...

  8. HashMap为什么比数组查询快

    通常数组不直接保存值,而是通过保存值的list.然后对list中的“值”使用equals方法比较,这部分查询速度自然慢.但是如果有好的散列函数,数组的每个位置就只有较少的“值”.因此,不是查询所有的l ...

  9. Ubuntu 安装indicator-sysmonitor

    之前就像安装一个软件用来查看Ubuntu的CPU, 内存, 网速情况, 终于让我碰到了--indicator-sysmonitor 仅需三条命令, 你值得拥有: sudo add-apt-reposi ...

  10. Firebug的安装与使用

    第一步,点击 Firefox 浏览器上的“工具”选项,然后点击“附加软件”,在弹出的小窗口中,点击右下角的“获取扩展”选项,如图 4 所示. 图 4. 获取扩展 第二步,在点击“获取扩展”选项后,打开 ...