6.10 DataView类

DataView使你能够创建DataTable中所存储的数据的不同视图,从而可以使用不同排序顺序来显示表中的数据,并且可以按行状态或基于筛选器表达式来筛选数据。

与DataTable的Select方法不同的是,DataView提供基础DataTable中的数据的动态视图:内容、排序和成员关系会实时反映其更改。因此,使用DataView不会影响DataTable里的真实数据。例如,假设过滤一个表从而隐藏了某些行,这些行仍然在DataTable中,但它们却不能够通过DataView访问到。

6.10.1 排序数据

要使用DataView排序数据,就得先创建一个DataView对象。通常,创建DataView的方法有两种:

1)使用DataView构造函数。DataView构造函数可以为空,还可以采用DataTable作为单个参数,还可以同时采用DataTable与筛选条件、排序条件和行状态筛选器。如下面的示例代码演示如何使用DataView构造函数来创建一个DataView。其中,RowFilter、Sort列和DataViewRowState将与DataTable一起提供:


DataView dv=new DataView(ds.Tables["Employee"],

"department='软件研发部'",

"employeename",

DataViewRowState.CurrentRows);


2)创建对DataTable的DefaultView属性的引用。虽然可以在同一表上创建多个不同视图的DataView对象,但每个DataTable都有一个默认的DataView和它相关联。其中,默认的DataView可以通过DataView的DefaultView属性来指定,如下面的示例代码所示:


DataView dv=ds.Tables["Employee"].DefaultView;


对于使用DataView排序数据[ASC(升序)和DESC(降序)],可以使用如下三种方法:

1)直接在DataView构造函数里进行排序,如上面的示例所示。

2)使用Sort属性来显式地进行排序,如下面的代码所示:


dv.Sort="employeename";


3)使用ApplyDefaultSort属性自动以升序创建基于表的一个或多个主键列的排序顺序。只有当Sort属性为空引用或空字符串时以及表已定义主键时,ApplyDefaultSort才适用。其中,如果使用默认排序,则为true;否则为false。

6.10.2 过滤数据

除了可以使用DataView对数据进行排序之外,还可以利用逻辑操作符号与一系列条件来过滤数据,从而限制显示的结果。同样,使用DataView过滤数据的方法也有如下两种:

1)直接在DataView构造函数里进行过滤,如上面的示例所示。

2)通过显式地使用RowFilter属性来进行数据过滤,RowFilter属性与SQL语句中的where子句相似。如下面的代码所示:


dv.RowFilter="department='软件研发部'";


除了上面的一些简单的过滤方法之外,还可以通过关系来进行高级过滤。同时,DataView支持一些常用的聚合函数,如avg()、max()、min()、count()等。下面先来创建一个DataRelation,并将该关系添加到DataSet(ds):


DataRelation rel=new DataRelation("EmployeeSalary",

ds.Tables["Employee"].Columns["employeeid"],

ds.Tables["Salary"].Columns["employeeid"]);

ds.Relations.Add(rel);


现在,就可以利用上面的表关系来过滤数据了,如下面的代码所示:


DataView dv=new DataView(ds.Tables["Employee"]);

dv.RowFilter="max(Child(EmployeeSalary).salary)>3900";


还可以使用下面的形式将这些数据输出来,如下面的代码所示:


foreach(DataRowView rowView in dv)

{

for(int i=0;i<dv.Table.Columns.Count;i++)

{

Label1.Text+=rowView[i].ToString();

}

}


6.10.3 计算列

其实,在实际开发中,除了可以在表格处理直接从数据源中获取的数据字段之外,还可以加入自己定义的计算列。在读取或者更新数据时,这些计算列将被忽略,它们只是表示计算现有值的结果的组合。下面的示例演示了如何使用计算列。

作为示例,首先需要创建一个DataSet,如下面的代码所示:


public DataSet GetEmployee()

{

string connectionString=

WebConfigurationManager.ConnectionStrings

["ConnectionString"].ConnectionString;

string employeeSql="select*from Employee";

string salarySql="select*from Salary";

SqlConnection con=new SqlConnection(connectionString);

SqlDataAdapter adapter=new SqlDataAdapter(employeeSql, con);

DataSet ds=new DataSet();

using(con)

{

con.Open();

//将Employee表填充到DataSet

adapter.Fill(ds,"Employee");

//将Salary表填充到DataSet

adapter.SelectCommand.CommandText=salarySql;

adapter.Fill(ds,"Salary");

}

//将Salary与Employee通过employeeid来建立关系

DataRelation rel=new DataRelation("EmployeeSalary",

ds.Tables["Employee"].Columns["employeeid"],

ds.Tables["Salary"].Columns["employeeid"]);

ds.Relations.Add(rel);

return ds;

}


创建好DataSet之后,需要在该DataSet的Employee表中添加一些计算列,以方便显示。创建一个计算列时,只要简单地创建一个新的DataColumn对象,同时指定该DataColumn对象的名称、类型和Expression属性。最后,将创建的DataColumn对象用DataTable的Add()方法添加到Columns集合中就可以了。如下面的代码所示:


protected void Page_Load(object sender, EventArgs e)

{

DataSet ds=GetEmployee();

DataColumn total=new DataColumn("总工资",

typeof(double),"max(Child(EmployeeSalary).total)");

DataColumn salestax=new DataColumn("应交税款",

typeof(double),"max(Child(EmployeeSalary).salestax)");

DataColumn salary=new DataColumn("实际工资",

typeof(double),"max(Child(EmployeeSalary).salary)");

ds.Tables["Employee"].Columns.Add(total);

ds.Tables["Employee"].Columns.Add(salestax);

ds.Tables["Employee"].Columns.Add(salary);

GridView1.DataSource=ds.Tables["Employee"];

GridView1.DataBind();

}


示例运行结果如图6-35所示。

figure_0247_0174

图 6-35 示例运行结果

6.10.4 将DataSet、DataTable和DataView转换成XML

实际开发中,经常面临着将DataSet、DataTable和DataView转换成XML的相关处理。其实,要将DataSet、DataTable和DataView转换成XML,其方法很简单,只需要利用DataTable或者DataSet的WriteXml()方法就可以完成相关处理。WriteXml()方法提供了只将数据或同时将数据和架构从DataTable写入XML文档的方法。

代码清单6-4封装了将DataSet、DataTable和DataView转换成XML的常用方法,读者可以直接调用这些方法来完成相关的处理任务。

代码清单6-4 DataToXml.cs


using System;

using System.Collections.Generic;

using System.Data;

using System.Web;

using System.Text;

using System.Xml;

using System.IO;

namespace_6_4

{

public class DataToXml

{

///<summary>

///将DataTable对象转换成XML字符串

///</summary>

///<param name="dt">DataTable对象</param>

///<returns>XML字符串</returns>

public static string DataTableToXml(DataTable dt)

{

if(dt!=null)

{

MemoryStream ms=null;

XmlTextWriter writer=null;

try

{

ms=new MemoryStream();

//根据ms实例化writer

writer=new XmlTextWriter(ms, Encoding.Unicode);

//获取DataTable中的数据

dt.WriteXml(writer);

int count=((it)ms.Length;

byte[]temp=new byte[count];

ms.Seek(0,SeekOrigin.Begin);

ms.Read(temp,0,count);

//返回Unicode编码的文本

UnicodeEncoding ucode=new UnicodeEncoding();

string returnValue=

ucode.GetString(temp).Trim();

return returnValue;

}

catch(System.Exception ex)

{

throw ex;

}

finally

{

//释放资源

if(writer!=null)

{

writer.Close();

ms.Close();

ms.Dispose();

}

}

}

else

{

return"DataTable为null";

}

}

///<summary>

///将DataSet对象转换成XML字符串

///</summary>

///<param name="ds">DataSet对象</param>

///<returns>XML字符串</returns>

public static string DataSetToXml(DataSet ds)

{

if(ds!=null)

{

MemoryStream ms=null;

XmlTextWriter writer=null;

try

{

ms=new MemoryStream();

//根据ms实例化writer

writer=new XmlTextWriter(ms, Encoding.Unicode);

//获取DataSet中的数据

ds.WriteXml(writer);

int count=((it)ms.Length;

byte[]temp=new byte[count];

ms.Seek(0,SeekOrigin.Begin);

ms.Read(temp,0,count);

//返回Unicode编码的文本

UnicodeEncoding ucode=new UnicodeEncoding();

string returnValue=

ucode.GetString(temp).Trim();

return returnValue;

}

catch(System.Exception ex)

{

throw ex;

}

finally

{

//释放资源

if(writer!=null)

{

writer.Close();

ms.Close();

ms.Dispose();

}

}

}

else

{

return"DataSet为null";

}

}

///<summary>

///将DataSet对象中指定的Table转换成XML字符串

///</summary>

///<param name="ds">DataSet对象</param>

///<param name="tableIndex">DataSet对象中的Table索引</param>

///<returns>XML字符串</returns>

public static string DataSetToXml(DataSet ds,

int tableIndex)

{

if(tableIndex!=-1)

{

return DataTableToXml(ds.Tables[tableIndex]);

}

else

{

return DataSetToXml(ds);

}

}

///<summary>

///将DataView对象转换成XML字符串

///</summary>

///<param name="dv">DataView对象</param>

///<returns>XML字符串</returns>

public static string DataViewToXml(DataView dv)

{

return DataTableToXml(dv.Table);

}

///<summary>

///将DataTable对象数据保存为XML文件

///</summary>

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

///<param name="xmlPath">XML文件路径</param>

///<returns>bool值</returns>

public static bool DataTableToXml(DataTable dt,

string xmlPath)

{

if(((d!=null)&&(!string.IsNullOrEmpty(xmlPath)))

{

string path=

HttpContext.Current.Server.MapPath(xmlPath);

MemoryStream ms=null;

XmlTextWriter writer=null;

try

{

ms=new MemoryStream();

//根据ms实例化writer

writer=new XmlTextWriter(ms, Encoding.Unicode);

//获取dt中的数据

dt.WriteXml(writer);

int count=((it)ms.Length;

byte[]temp=new byte[count];

ms.Seek(0,SeekOrigin.Begin);

ms.Read(temp,0,count);

//返回Unicode编码的文本

UnicodeEncoding ucode=new UnicodeEncoding();

//写文件

StreamWriter sw=new StreamWriter(path);

sw.WriteLine("<?xml version=\"1.0\"

encoding=\"utf-8\"?>");

sw.WriteLine(ucode.GetString(temp).Trim());

sw.Close();

return true;

}

catch(System.Exception ex)

{

throw ex;

}

finally

{

//释放资源

if(writer!=null)

{

writer.Close();

ms.Close();

ms.Dispose();

}

}

}

else

{

return false;

}

}

///<summary>

///将DataSet对象数据保存为XML文件

///</summary>

///<param name="ds">DataSet</param>

///<param name="xmlPath">XML文件路径</param>

///<returns>bool值</returns>

public static bool DataSetToXml(DataSet ds, string xmlPath)

{

if(((d!=null)&&(!string.IsNullOrEmpty(xmlPath)))

{

string path=

HttpContext.Current.Server.MapPath(xmlPath);

MemoryStream ms=null;

XmlTextWriter writer=null;

try

{

ms=new MemoryStream();

//根据ms实例化writer

writer=new XmlTextWriter(ms, Encoding.Unicode);

//获取ds中的数据

ds.WriteXml(writer);

int count=((it)ms.Length;

byte[]temp=new byte[count];

ms.Seek(0,SeekOrigin.Begin);

ms.Read(temp,0,count);

//返回Unicode编码的文本

UnicodeEncoding ucode=new UnicodeEncoding();

//写文件

StreamWriter sw=new StreamWriter(path);

sw.WriteLine("<?xml version=\"1.0\"

encoding=\"utf-8\"?>");

sw.WriteLine(ucode.GetString(temp).Trim());

sw.Close();

return true;

}

catch(System.Exception ex)

{

throw ex;

}

finally

{

//释放资源

if(writer!=null)

{

writer.Close();

ms.Close();

ms.Dispose();

}

}

}

else

{

return false;

}

}

///<summary>

///将DataSet对象中指定的Table转换成XML文件

///</summary>

///<param name="ds">DataSet对象</param>

///<param name="tableIndex">DataSet对象中的Table索引</param>

///<param name="xmlPath">xml文件路径</param>

///<returns>bool值</returns>

public static bool DataSetToXml(DataSet ds,

int tableIndex, string xmlPath)

{

if(tableIndex!=-1)

{

return DataTableToXml(ds.Tables[tableIndex],xmlPath);

}

else

{

return DataSetToXml(ds, xmlPath);

}

}

///<summary>

///将DataView对象转换成XML文件

///</summary>

///<param name="dv">DataView对象</param>

///<param name="xmlPath">xml文件路径</param>

///<returns>bool值</returns>

public static bool DataViewToXml(DataView dv,

string xmlPath)

{

return DataTableToXml(dv.Table, xmlPath);

}

}

}


6.10.5 将XML转换成DataSet、DataTable

与WriteXml()使用方法一样,你也可以使用ReadXml()方法将XML架构和数据读入DataSet。代码清单6-5封装了将XML转换成DataSet、DataTable的常用方法,读者可以直接调用这些方法来完成相关的处理任务。

代码清单6-5 XmlToData.cs


using System;

using System.Collections.Generic;

using System.Data;

using System.Web;

using System.Text;

using System.Xml;

using System.IO;

namespace_6_4

{

public class XmlToData

{

///<summary>

///将Xml内容字符串转换成DataSet对象

///</summary>

///<param name="xml">Xml内容字符串</param>

///<returns>DataSet对象</returns>

public static DataSet XmlToDataSet(string xml)

{

if(!string.IsNullOrEmpty(xml))

{

StringReader strReader=null;

XmlTextReader reader=null;

try

{

DataSet ds=new DataSet();

//读取字符串中的信息

strReader=new StringReader(xml);

//获取strReader中的数据

reader=new XmlTextReader(strReader);

//ds获取reader中的数据

ds.ReadXml(reader);

return ds;

}

catch(Exception e)

{

throw e;

}

finally

{

//释放资源

if(reader!=null)

{

reader.Close();

strReader.Close();

strReader.Dispose();

}

}

}

else

{

return null;

}

}

///<summary>

///将Xml字符串转换成DataTable对象

///</summary>

///<param name="xml">Xml字符串</param>

///<param name="tableIndex">Table表索引</param>

///<returns>DataTable对象</returns>

public static DataTable XmlToDatatTable(string xml,

int tableIndex)

{

return XmlToDataSet(xml).Tables[tableIndex];

}

///<summary>

///将Xml字符串转换成DataTable对象

///</summary>

///<param name="xml">Xml字符串</param>

///<returns>DataTable对象</returns>

public static DataTable XmlToDatatTable(string xml)

{

return XmlToDataSet(xml).Tables[0];

}

///<summary>

///读取Xml文件信息,并转换成DataSet对象

///</summary>

///<param name="xmlPath">Xml文件地址</param>

///<returns>DataSet对象</returns>

public static DataSet XmlFileToDataSet(string xmlPath)

{

if(!string.IsNullOrEmpty(xmlPath))

{

string path=

HttpContext.Current.Server.MapPath(xmlPath);

StringReader strReader=null;

XmlTextReader reader=null;

try

{

XmlDocument xmldoc=new XmlDocument();

//根据地址加载Xml文件

xmldoc.Load(path);

DataSet ds=new DataSet();

//读取文件中的字符流

strReader=new StringReader(xmldoc.InnerXml);

//获取strReader中的数据

reader=new XmlTextReader(strReader);

//ds获取reader中的数据

ds.ReadXml(reader);

return ds;

}

catch(Exception e)

{

throw e;

}

finally

{

//释放资源

if(reader!=null)

{

reader.Close();

strReader.Close();

strReader.Dispose();

}

}

}

else

{

return null;

}

}

///<summary>

///读取Xml文件信息,并转换成DataTable对象

///</summary>

///<param name="xmlPath">xml文件路径</param>

///<param name="tableIndex">Table索引</param>

///<returns>DataTable对象</returns>

public static DataTable XmlToDataTable(string xmlPath,

int tableIndex)

{

return XmlFileToDataSet(xmlPath).Tables[tableIndex];

}

///<summary>

///读取Xml文件信息,并转换成DataTable对象

///</summary>

///<param name="xmlPath">xml文件路径</param>

///<returns>DataTable对象</returns>

public static DataTable XmlToDataTable(string xmlPath)

{

return XmlFileToDataSet(xmlPath).Tables[0];

}

}

}