ADO.NET中的视图和过滤器

ado|视图

ADO.NET中有一层对象,用来创建任意数据源的抽象模型。其中包括DataSet,DataTable,DataRow,DataView,DataRelation等等。

所有这些对象都定义在System.Data名字空间。它们形成一个抽象模型,使得无论针对Windows Form,Web Form还是Web Service进行编程,都可以使用相同的编程接口。
在实际应用中,这些对象大多会对诸如SQL Server一类的关系型数据库中的数据进行操作。但是,它们可以处理各种数据,而不管它的物理存储媒介。
你可以使用DataSet对象来打包和关联各表中的数据,用DataTable类来处理表格类型的数据,而DataRow对象可以处理表中某一行的数据。
这三个对象都是对数据进行打包,但有不同的逻辑聚合层次。DataSetDataTable和其他的组合。而DataTableDataRow和其他的组合。DataRow是字段和其他的组合。但是这些对象中都没有内建过滤和排序的功能。
ADO.NET提供了一些类来处理这个数据库应用程序中的重要方面。在.Net Beta2中,这方面最重要的两个对象就是DataViewDataViewManager
注意:DataViewManager是Beta2中特有的。在Beta1中,相应的功能由DataSetView完成。

定制数据视图
DataView类用来表示定制的DataTable的视图。DataTableDataView的关系是遵循著名的设计模式--文档/视图模式,其中DataTable是文档,而Dataview是视图。
在任何时候,你都可以有多个基于相同数据的不同的视图。更重要的是,你可以对每一个具有自己一套属性、方法、事件的视图作为独立的对象进行处理。这也代表了相对ADO一个巨大的飞跃。
ADO Recordset可以定义过滤字符串。一旦你建立了该字符窜,只有匹配特定标准的数据才能够进行读写。Filter属性的工作原理同动态WHERE子句很相似。它只是简单的在同一recordset对象视图上隐藏了某些记录。
在ADO中,你从没有一个独立的视图对象。一个过滤过的recordset总是同一个对象,只不过显示出的记录比它实际数量少一些而已。
如果你不需要同时处理一些不同的视图,上述问题并不要紧。编程接口赋予了recordset既可以是表也可以是视图的功能。但是在创建时,这不能同时发生。在某一特定时刻,recordset只能是没有过滤字符串的表或者是激活了过滤字符串的视图。
Recordset的克隆提供了较好解决这个结构限制的方法。正如Clonation and the Case of Table Dolly, Part 1中所说的,克隆recordset相对开销较少,因为它不复制数据,只是复制recordset的基本构造。要处理同一数据两个或两个以上的视图,你可以利用两个或两个以上克隆,各自有一套相应的过滤字符串。


图一 在ADO中处理同一recordset不同的视图
在ADO.NET中,你可以使用新型对象模型所提供的DataView对象。ADO.NET的DataView对象用来表示给定数据表的定制的视图,但你可以像处理单独的对象一样处理它。DataView对象保留了对表的一个引用并允许对它进行更新。


图二 在ADO.NET中对同一数据表的不同视图进行操作
功能上而言,使用ADO Recordset克隆与使用特殊的视图对象完成的是同样的功能,都是让你实现过滤,对所选的数据行进行操作,并同时处理多个视图。

深入DataView对象
DataView对象继承了MarshalByValueComponent并实现了一组接口使之在数据绑定控件中可用。 Public Class DataView
Inherits MarshalByValueComponent
Implements IBindingList, IList, ICollection,IEnumerable, _
ITypedList, ISupportInitialize
由MarshalByValueComponent派生的类是.NET远程组件,可以通过值来列集--即序列化对象到目标应用程序域。(详见以下关于.NET组件的更多细节)
DataView中的内容可以通过许多编程接口进行操作,包括集合,列表和枚举器。IBindingList接口确保了该类提供所有用来支持复杂的和简单的数据绑定的必要特征。
总的来说,DataView对象可以用来达到两个目的。第一,视图对于关联DataTable对象和数据绑定控件中的DataSource域是很重要的。第二,它也对连接的DataTable提供了一层包装,让你能够进行过滤,排序,编辑和浏览。
DataView并不是唯一的可以通过传值进行远程操作的数据驱动类。DataSet和DataTable也具有同样的能力,特别是在互操作的场景下。

创建DataView public DataView();
public DataView(DataTable);
DataView只有同已经存在的、很可能是非空的DataTable对象连接后才可用。通常,这个连接在构造时就指定了。
DataView dv;
dv = new DataView(theDataSet.Tables["Employees"]);
但是,你也可以先创建一个新的视图,然后再用Table属性同表相关联。
DataView dv = new DataView();
dv.Table = theDataSet.Tables["Employees"];
DataView构造函数使你由DataTable中得到一个DataView对象。如果需要,反之亦可。事实上,DataTable对象的DefaultView属性返回一个该表的DataView对象。
DataView dv = dt.DefaultView;
一旦你有了DataView对象, 你可以利用它的属性来建立你希望用户见到的数据行集。一般,你可以使用下列属性:

  • RowFilter
  • Sort

前者可以定制视图中可见数据应匹配的规则。而后者通过表达式来进行排序。当然你可以使用这两者的任意组合。

设置过滤 RowFilter是一个可读写的属性,用来读取和设置表过滤的表达式。
public virtual string RowFilter {get; set;}
你可以用列名,逻辑和数字运算符和常量的任意合法组合组成表达式。以下是一些例子: dv.RowFilter = "Country = 'USA'";
dv.RowFilter = "EmployeeID >5 AND Birthdate < #1/31/82#"
dv.RowFilter = "Description LIKE '*product*'"
让我们来看一下过滤器的基本规则和运算符。
过滤字符串是表达式的逻辑连接。可以用AND,OR,NOT来连接成一个较短的表达式,也可以使用圆括号来组成子句,指定优先的运算。
通常包含列名的子句同字母、数字、日期或另一个列名进行比较。这里,可以使用关系运算符和算术运算符,如>=, <, >, +, *, % (取模)等等。
如果要选取的行并不能方便地通过算术或逻辑运算符表达,你可以使用IN操作符。以下代码显示如何选取一个随机行:
dv.RowFilter = "employeeID IN (2,4,5)"
你也可以使用通配符*和%,它们同LIKE运算符一起使用时显得更有用。它们都表示任意数量的字符,可以相互替代使用。
请注意,如果在LIKE子句中已经有了*或%字符,你必须用方括号将其括起,以免歧义。如果很不幸,字符串中方括号本身也存在了,那么它也必须用将本身括起。这样,匹配语句会如下所示:
dv.RowFilter = "Description LIKE '[[]*[]]product[[]*[]]"
通配符只允许在过滤字符串的开头或结尾处使用,而不能在字符串中间出现。例如,下列语句会产生运行时错误:
dv.RowFilter = "Description LIKE 'prod*ct"
字符串必须以单引号括起,而日期型必须以#符号括起。字符型值可以使用小数点和科学计数法。
RowFilter也支持聚合函数,如SUM, COUNT, MIN,MAX, and AVG。如果表中没有数据行,那么函数将返回NULL。
在介绍RowFilter表达式的最后,让我们讨论三个很便利的函数:Len,IIF和Substring。
正如其名,Len()返回特定表达式的长度。该表达式可以是一个列名,也可以是其他合法的表达式。
Substring()返回指定的表达式自特定位置开始,特定长度的字符子串。
我最喜欢用的是IIF(),它按照逻辑表达式的值有一到两个值。IIF是IF-THEN-ELSE语句的紧凑表达。语法如下:
IIF(expression, if_true, if_false)
通过该函数,可以建立非常复杂的过滤字符串。例如,假定你从SQL Server的Northwind数据库中取得Employees表,下列表达式可以选出那些employeeID小于6且lastname为偶数个字符和employeeID大于6且lastname为奇数个字符的员工。
IIF(employeeID<6, Len(lastname) %2 =0, Len(lastname) %2 >0)
下图显示了结果(样品应用程序会在稍后讨论)
图三 对Northwind中的表进行过滤
例子程序是一个Windows Form应用程序,其中使用了两个datagrid
控件来实现master/detail结构。一个grid在载入时生成,即在SQL
Server data adapter完成数据读取工作之后。请注意,data
adapter是Beta 2中引入的,在Beta 1中相应的是SQLDataSetCommand类。<BR>

预排视图
在上面的举例中,datagrid必须负责预排视图中的数据行,以便刷新用户界面。这个自动机制是.NET
数据绑定的产物。Datagrid是通过DataSource属性来获取数据的数据绑定控件。DataView是一个可数据绑定的类,可构建DataSource属性的内容。<BR>
如果你想使用datagrid之外的另一个控件,应该怎么办呢?又如果你不想使用自动数据绑定呢?应该怎样预排视图中所选的数据行呢?<BR>
DataView的Table属性指向相应的数据表,但DataTable并不保存过滤信息。所以,预排表中的数据注定是不可行的。虽然DataTableDataView是紧密相联的,但它们各自保持独立,并执行独立的功能。<BR>
以下Visual Basic .NET代码段显示了如何遍历视图中所有的数据行,并加入到listbox中。
Dim dv As New DataView()
dv = ds.Tables("Employees").DefaultView
dv.RowFilter = "employeeid >5"

ListBox1.Items.Clear()
Dim buf As String
Dim dr As DataRowView
For Each dr In dv
buf = ""
buf &= dr("lastname").ToString()& ", " & dr("firstName").ToString()
ListBox1.Items.Add(buf)
Next
正如前面说提到的,DataView是可枚举的类,因此你可以安全的将它传给For..Each语句。Count属性存储了视图中数据行数,以便在For..Next循环中使用。
要访问视图中某一行,可以使用DataRowView类。DataRowView可表示DataRow的视图,就像DataView表达DataTable定制的视图一样。
总的来说,DataRow最多有四种状态:default,original,current和proposed。这些状态由DataRowVersion枚举类型设置,由RowVersion属性表达。
DataRow的视图只能是其中某一种状态。
数据行的默认(default)版本只有当其列在构造时设定了默认值时才有。而初始(original)版本是指在最后一次调用表的AcceptChanges后,从数剧源中得到数据行或快照。当前(Current)版本是指当前的数据行,包括所有当时发生的更新。Proposed状态只存在于调用BeginEdit和EndEdit的编辑过程中。
可以通过访问DataRow相同的语法访问DataRowView。这里最重要的属性叫Item。

排序和其他便捷的特性
DataView支持Sort属性,可以用来对视图中的内容排序。Sort由用逗号分隔的列名表达式进行排序。通过在任何列名后加ASC或者DESC限定词,可以使得字段按照上升或者下降的顺序排列。如果没有方向限定词,默认顺序为ASC。
DataView是内存中的对象,所以排序在本地进行,无需调用数据库服务器。
RowStateFilter是DataView另一有趣的属性。它可以用任何预定义的标准来过滤DataTable中的内容。下表中是DataViewRowState枚举类型的所有取值: CurrentRows包括所有未更新的、新的和修改的数据行Deleted所有自上次调用AcceptChanges后删除的数据行ModifiedCurrent所有自上次调用AcceptChanges后修改过的数据行ModifiedOriginal所有自上次调用AcceptChanges后original版本的数据行New所有自上次调用AcceptChanges后新添加的行OriginalRows返回初始数据行,包含unchanged和deleted 的Unchanged所有未更新的数据行
如果要操作非连接的数据,所有更新都在对DataTable调用AcceptChanges后生效。对单一行的更新在调用DataRowAcceptChanges后生效。类似的,这些更新可以通过调用DataTableDataRow对象的RejectChanges来取消。
DataView对象还有一些属性,如AllowEdit,AllowDeleteAllowNew,用来得到或设定是否允许更新的值。它们的默认值设为True,允许任何种类的更新。如果在标志设为False时,你想要完成相应的更新操作,会有一个运行时错误发生。

DataViewManager类
DataTable对象的DefaultView属性用来返回一个DataView对象,作为数据表中内容的默认视图。它按照自然顺序读取数据并显示表中所有的行,而不使用任何过滤。
theMasterGrid.DataSource = m_ds.Tables("Employees").DefaultView
如果需要数据特定的视图,你可以进行排序并/或对DefaultView对象直接进行过滤。
m_ds.Tables("Employees").DefaultView.Sort = "lastname"
theMasterGrid.DataSource = m_ds.Tables("Employees").DefaultViewDataViewManager类是用来存储DataSet中所有表的视图设置。
可以通过传递一个合法的非空的DataSet给类的构造函数来创建DataViewManager
Dim dvm As DataViewManager
dvm = New DataViewManager(m_ds)
也可以通过DataSet对象的DefaultViewManager属性直接得到:
Dim dvm As DataViewManager = m_ds.DefaultViewManager
重要的是DataViewManager类是同一个DataSet相关联的。下面是另一种可行的方法:
Dim dvm As New DataViewManager()
dvm.DataSet = m_ds
DataViewManager最重要的属性是DataViewSettings,一个DataViewSetting对象的集合。

Dim dvs As DataViewSetting
dvs = dvm.DataViewSettings("Employees")
dvs.Sort = "lastname"
DataViewSetting对象包含了表视图的参数信息。当将数据绑定到对数据敏感的控件时,使用DataViewManager而不是DataSet或DataTable可以保留你的视图设置(过滤和排序字段)

theMasterGrid.DataSource = dvm
theMasterGrid.DataMember = "Employees"
在这里,视图按照DataViewSetting中对Employees表指定的自动进行排序和过滤。换而言之,DataViewSetting类是对特定表的视图的一种缓存。

下一步
上述例子程序用filter实现了master/detail结构。如果使用.NET中特有的数据绑定控件(如datagrid),能够更好的达到这个目的。在以后的专栏中,我将论述内存中的数据关系,以及它们是如何影响master/detail结构的设计的。
对话:你是否需要控件或组件?

在.NET中有很多术语经常可以替代使用。这里特别指出的是:类,组件,对象和控件。在此,我提供了一张表,来表述每个术语的恰当的含义。我们经常将它们当成同义词。

需要牢记在心的是整个.NET架构是由类组成的。所以你从中得到的任何东西,首先,是一个类。在.NET环境中,控件和组件不是同一种类。至于对象,可以认为是运行着的.NET类的实例。
组件是一个特殊的类,它实现了Icomponent接口或派生于实现了Icomponent接口的类。
控件是提供了用户界面功能的组件。在.NET架构中,可以找到两类控件:客户端的Windows Forms 控件和ASP.NET server 控件。
Icomponent接口包含在Idisposable接口中,并提供了一种确定的方法清除资源。
Public Interface IComponent
Inherits IDisposable
这种释放资源的方法和标准的.NET垃圾收集器可以二者选一。通过实现Idisposable,你定义了一个Dispose方法。这样通过编程,你可以显式的释放对象而无须等待垃圾收集器来处理。
.NET组件知道怎样在应用程序域(application domain)中如何串联。这有两种方法:通过引用或通过值,基本功能分别内建于MarshalByRefComponet和MarshalByValueComponent类中。.NET component类,事实上,实现了Idisposable,但直接或间接继承了上述两个类中的一个。
应用程序域是一种轻量级进程。通过引用来列集对象意味着proxy/stub实体对会被创建并处理远程调用。而通过值则意味着该对象的序列化的拷贝传递越过域的边界。
控件是更特殊化的对象,它还提供了用户界面元素。当然,一个控件总是一个component,但反之不一定成立。

时间: 2024-11-02 16:22:33

ADO.NET中的视图和过滤器的相关文章

ADO.NET 中的 XML 特性

ado|xml 毫无疑问,XML 及其一些相关技术(包括 XPath.XSL Transformation 和 XML Schema)是 ADO.NET 的基础.与 ADO 相比,ADO.NET 对象模型的互操作性得到很大的提高,而事实上,XML 正是为此发挥重要作用的关键元素.在 ADO 中,XML 只是一个用于保留断开连接的记录集的内容的(非默认)I/O 格式.而 XML 在 ADO.NET 的构建和交互方面的参与则深入得多.可以用以下几点来概括 ADO.NET 与 XML 的更强的交互和集

云计算设计模式(十五)——管道和过滤器模式

云计算设计模式(十五)--管道和过滤器模式 分解,执行复杂处理成一系列可重复使用分立元件的一个任务.这种模式可以允许执行的处理进行部署和独立缩放任务元素提高性能,可扩展性和可重用性. 背景和问题 一个应用程序可能需要执行各种关于它处理的信息不同复杂的任务.一个简单,但不灵活的方式来实施这个应用程序可以执行此处理为单一模块.然而,这种方法有可能减少用于重构代码,对其进行优化,或者重新使用它,如果是在应用程序中其他地方所需要的相同的处理的部件的机会. 图1通过使用单片式的方式示出了与处理数据的问题.

MFC框架下 单文档视图中多视图切换问题

问题描述 MFC框架下 单文档视图中多视图切换问题 在MainFrm.cpp 里对主视图进行了切分 BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs CCreateContext* pContext){ // TODO: Add your specialized code here and/or call the base class // CRect rc; // 获取框架窗口客户区的CRect对象 GetClientRect(&rc);

ADO.net中数据库连接方式

ado|数据|数据库|数据库连接   在MSDN中,.net的数据库连接字符串都有详细的说明,我这里以代码范例的方式罗列一些,具体的每一项代表的意义可以参看MSDN. ADO.net 中数据库连接方式(微软提供) 微软提供了以下四种数据库连接方式:System.Data.OleDb.OleDbConnectionSystem.Data.SqlClient.SqlConnectionSystem.Data.Odbc.OdbcConnectionSystem.Data.OracleClient.Or

ADO.NET中的多数据表操作浅析之读取

ado|数据 在开发基于.NET平台的数据库应用程序时,我们一般都会用到DataSet,作为ADO.NET的核心类它为我们提供了强大的功能,而整个看上去就像是放在内存内的一个小型数据库,内部包括了DataTable.DataView.DataRow.DataColumn.Constraint以及DataRelation.当初看到它时真的是有点兴奋. 下面根据我的一些经验来举例说明在ADO.NET中的多表填充.关联表更新以及多个Command对象执行过程中启用事务的操作.欢迎大家交流,或在Blog

在ado.net中使用ado recordset

ado 在ado.net中我们很少甚至不用recordset今天我就向大家展示如何在ado.net中使用recordset新建一个vb.net应用程序在窗体上添加一个datagrid控件然后,项目-->添加引用--〉com->选择Microsoft ActiveX Data Objects 2.7 Library这样在引用一栏我们就看到新加入一项ADODB我们将其与其他命名空间一起倒入Imports System.DataImports System.Data.OleDbImports ADO

ADO.NET中的多数据表操作浅析—修改

ado|数据 ADO.NET中的多数据表操作浅析-修改 作者:郑佐??????? 2004-8-5 三.更新数据集 首先需要说明的是我这里去掉了Order Details表,对两个表的操作只是其中的几个字段.下面是窗体界面: 图3-1 单选框用来选择不同的更新方法. 在DataAccess类中增加两个类成员变量: ???? private SqlDataAdapter _customerDataAdapter; //客户数据适配器 ???? private SqlDataAdapter _ord

在ADO.NET中使用事务保护数据的完整性(3)

ado|数据 事务在ADO.Net中 Ado.net 支持两种事务模型,这在.Net Framework 文档中作为指南有定义.事务指南手册介绍了通常应该知道的数据库事务, 它影响操作单个目标数据库.一个类通过由ado.net显示描述的事务边界使用事务类和方法能提供事务指南.在接下来的章节中,我将把重点放在事务指南上. 自动事务也是可行的,为了使用类来参与事务来协调跨多个数据源的改变.在这种情景下事务本身是在外层处理的,比如通过com+ 和 DTC. 需要了解更多自动事务的,可以参照相关自动事务

ADO.net 中数据库连接方式(微软提供)

ado|数据|数据库|数据库连接|微软 在MSDN中,.net的数据库连接字符串都有详细的说明,我这里以代码范例的方式罗列一些,具体的每一项代表的意义可以参看MSDN. ADO.net 中数据库连接方式(微软提供) 微软提供了以下四种数据库连接方式:System.Data.OleDb.OleDbConnectionSystem.Data.SqlClient.SqlConnectionSystem.Data.Odbc.OdbcConnectionSystem.Data.OracleClient.O