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”的对象时检测到循环引用。”的错误提示.

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

 

究其原因,猜测可能是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

上一篇:http 响应头之location


下一篇:原生JS实现图片放大镜插件