• 数据库ADONET排序、搜索和筛选


     

    排序、搜索和筛选

    如何使用一个值或一组值来查找DataTable中的特定行?

    如何使用筛选程序是只有满足条件的行可见?

    如何控制要访问或者显示的行的排序顺序?

    可以使用:

    DataRowCollection类的Find方法,DataTable类是Select方法,DataView对象和DataRowView对象。

    1           使用DataTable对象的搜索和筛选功能

    DataTable对象公开了两个方法,它们可以用来根据搜索标准查找数据。

    Find方法,根据主键值来查找数据。

    Select方法,类似于筛选程序,根据更灵活的搜索标准返回多行数据。

    1.1         根据主键值查找行

    查询数据库以获取信息时,通常都会希望,根据其主键列的值,来获取特定行的数据。

    可以使用以下查询:

    Select CustomerID,CompanyName,ContactName,Phone from Customers where CustomerID=”ALFKI”

    还可以根据行的主键值,在DataTable中查找DataRow

    尽管Find方法是为DataTable对象设计的,但是,它实际上是由DataRowCollection类公开的。

    Find方法接受一个包含要查询的行的主键值作为参数,因为主键值是惟一的,所以Find方法只能返回一行DataRow

    Dim strConn, strSql as string

    strConn=”Provider=SQLOLEDB;Data Source=(local)"NetSDK; Initial Catalog=Northwind;
    Trusted_Connection=Yes;”

    strSql=”select CustomerID,CompanyName,ContactName,Phone from Customers”

    Dim da as New Oledb.OledbDataAdapter(strSql,strConn)

    Dim tbl as new DataTable

    Da.fill(tbl)

    Tbl.PrimaryKey=new DataColumn(){tbl.Columns(“CustomerID”)}

    Dim row as DataRow=tbl.Rows.Find(“ALFKI”)

    If row Is Nothing then

         Console.WriteLine(“Row Not Found.”)

    Else

         Console.WriteLine(Row(“CompanyName”))

    End IF

    注意:

    从技术角度来说,DataTable可以包含拥有相同主键值的多个行。

    如果,将DataSetEnforceConstraints属性设置为假False,那么即使违反了主键约束,DataTable也不会抛出异常。

    Find方法将返回找到的所有目标主键值的行。

    Find方法,针对DataTable的主键包含多个DataColumn对象的场景,进行了重载。(组合主键)

    例如:对于【Order Details】表,主键是OrderID/ProductID,查找演示如下:

    Dim strConn,strSql as string

    strConn=”...”

    strSql=”select OrderID,ProductID,Quantity,UnitPrice from [Order Details]”

    dim da as New OleDbDataAdapter(strSql,strConn)

    dim tbl as new DataTable()

    da.Fill(tbl)

    tbl.PrimaryKey=new DataColumn(){tbl.Column(“OrderID”),tbl.Columns(“ProductID”)}

    Dim objCriteria as new Object(){10643,28}

    Dim row as DataRow=tbl.Rows.Find(objCriteria)

    If row Is Nothing Then

         Console.WriteLine(“Row Not Found”)

    Else

         Console.WriteLine(“row(“Quantity”) & “ – “ & row(“UnitPrice”))

    End If

    1.2         执行更动态的搜索

    根据主键值查找行,是很高效的。

    但是,并非所有搜索都是如此直观。

    如果希望查找“位于美国而不在西雅图市的客户”,该怎么办?可以使用Where子句向查询添加一个条件,如下:

    Select CustomerID,CompanyName,ContactName,Phone,City,Country from Customers
    where Country=”USA” AND City <> “Seattle”

    ADONET中,还可以用DataTable对象的Select方法来实现类似的条件查询。

    Dim strConn as string=”Provider=SQLOLEDB;Data Source=(local)"NETSDK;Initial Catalog=Northwind;
    Trusted_Connection=Yes;”

    Dim strSql as String=”select CustomerID,CompanyName,ContactName,Phone,City,Country
    from Customers”

    Dim da as New OleDbDataAdapter(strSql,strConn)

    Dim tbl as new DataTable()

    Da.Fill(tbl)

    Dim arows as DataRow()

    Dim row as DataRow

    Arows=tbl.select(“Country=’USA’ AND City <> ‘Seattle”)

    For Each row in arows

         Console.WriteLine(row(“CompanyName”) & “ – “ & row(“City”) & “ – “ & row(“Country”))

    Next row

    1.3         执行通配符搜索

    ADONET允许使用通配符进行搜索。

    SQL语句中查询CustomerID列是以字母A开始的客户,

    Select CustomerID,CompanyName from Customers where CustomerID LIKE ‘A%’

    可以在字符串的开始或者结尾使用“%*”作为通配符。

    strFilter=”State LIKE ‘New %’” – 将返回在以New开头地区的客户

    strFilter=”State LIKE ‘% Dakota ‘” – 将返回北Dakota和南Dakota的客户

    ADONET不能使用单字母通配符(如:“?”、“_”等)

    1.4         使用分隔符

    在搜索条件中,不能简单的使用“单引号”括住一个字符串,就拉倒了。

    如果是动态构建搜索条件,其中可能会包含“单引号”,那么搜索条件就必须重复它(就是替换成’’),这可以用String类的Replace方法处理。

    strCriteria=”LastName=’” & strLastName.Replace(“ ’ ”, ” ’’ ”) & “’”

    以上是对于“字符串”的处理,那么怎么分隔日期?

    使用pound号(就是#号)括住日期。

    strCriteria=”OrderData>= #01/02/2002# AND OrderDate < #02/02/2002#”

    在某些情况下,需要在搜索条件中分隔列名,原因可能是:

    列名中有空格或其他非字母字符

    列名是保留单词,如LIKESUM等等

    ADONET中,可以使用方括号来作为“列分隔符”。

    strCriteria=”[Space In Name]=3”

    如果在列名中有列分隔符,又怎么办?

    可以在条件字符串的结束分隔符“)”之前用转移字符“"”。比如:列名为Bad]Column[Name,可以这样写:strCriteria=”[Bad"]Column[Name]=5”

    需要特别注意的是,对于C#来说,由于“"”是转义字符,所以实际的字符串应该这样写:

    “[Bad""]Column[Name]=5”

    1.5         使用附加Select方法

    Select方法有一些重载方法,其中的参数包括:

    只提供搜索字符串

    包括排序顺序以及控制要搜索的行的状态参数(例如:仅搜索添加的行或仅搜索被修改的行)

    1.5.1   包括“排序顺序”

    可以通过使用Select重载方法之一,来空值返回的DataRow对象的顺序。

    Sql查询中,可以使用ORDER BY子句,来控制有查询返回的数据的排序顺序。

    例如:

    Select CustomerID,CompanyName,Phone,City from Customers ORDER BY City

    如果是City按照降序排序,则改为ORDER BY City DESC

    DataTableSelect方法,使用示例如下:

    Dim strConn,strSql as String

    strConn=”Provider=SQLOLEDB;Data Source=...;Initial Catalog=Northwind;
    Trusted_Connection=Yes;”

    strSql=”select CustomerID,CompanyName,Phone,City,Country from Customers”

    Dim da as New Oledb.OleDBDataAdapter(strSql,strConn)

    Dim tbl as New DataTable()

    Da.Fill(tbl)

    Dim strCriteria As String=”Country=’USA’ AND City <> ‘Seattle’”

    Dim strSortOrder as string=”City DESC”

    Dim arows as DataRow()=tbl.select(strCriteria,strSortOrder)

    Dim row as DataRow

    For each row in arows

        Console.WriteLine(row(“CompanyName”) & “ – “ & row(“City”) & “ – “ & row(“Country”))

    Next Row

    1.5.2   指定要搜索的行的状态RowState

    使用Select方法的重载版本之一,指定DataViewRowState枚举值作为参数,可以只对特殊状态的行进行搜索。

    举例:希望只检查DataTable中被修改的和被删除的行,使用DataViewRowState枚举类型中的ModifiedOriginalDeleted,将筛选和排序参数使用空串,具体如下:

    Dim dvrs as DataViewRowState

    Dvrs=DataViewRowState.ModifiedOriginal Or DataViewRowState.Deleted

    Dim arows() as DataRow=tbl.Select(“”,””,dvrs)

    Dim row as DataRow

    For Each row in arows

        Console.WriteLine(row(“CompanyName”,DataRowVersion.Original))

    Next Row

    这里要注意的是,被删除的行只能检查行的“原始值Original”。

    2          DataView对象

    DataTableSelect方法,它有两方面的局限性。

    第一:因为它接受动态的搜索条件,所以效率不高;

    第二:WindowsWEB窗体都不支持“绑定”到Select方法的返回值(DataRow数组)

    ADONET针对此问题,提供的解决方案是“DataView”对象。

    ADONET体系中DataTable对象基本等价于数据库中的表,所以可以假设DataView对象类似于视图。

    2.1         DataView对象从DataTable中返回数据

    DataView对象不维护自己的数据副本。

    当通过DataView访问数据时,DataView将返回存储在相应DataTable中的数据。

    类似的,数据库中的视图也是一样,查询一个视图时,数据库会从视图所引用的一个或多个表中返回数据。

    2.2         DataView对象不是SQL查询

    数据库的视图实际上就是一个查询。

    在数据库中创建视图时,要提供数据库将要执行的,返回视图的数据查询:

    CREATE VIEW ViewCustomersAndOrders AS

                SELECT c.CustomerID,c.CompanyName,c.ContactName,c.Phone,o.OrderID,o.EmployeeID,
                o.OrderDate

                FROM Customers c,Orders o WHERE c.CustomerID=o.CustomerID

    而,ADONETDataView对象可以,筛选、排序、搜索DataTable的内容,但——它们并非SQL查询。

    不能用DataView在两个DataTable间联结Join数据。

    不能用DataView查看DataTable中的部分列。

    DataView确实支持基于动态标准的行筛选,但是,它们只能访问一个DataTable,而且,DataTable中所有列都可通过DataView得到。

    DataRelation来模拟连接

    可以用DataRelation配合一个基于表达式的列模拟联结。

    比如说:有一个客户DataTable和一个订单DataTable,可以在两个表之间创建关系,然后在订单表中添加基于表达式的列(用来显示客户表的列):

    Ds.Relations.Add(“CustomersOrders”,ds.Tables(“Customers”).Columns(“CustomerID”),
    ds.Tables(“Orders”).Columns(“CustomerID”))

    Ds.Tables(“Orders”).Columns.Add(“CompanyName”,GetType(String),
    “Parent(CustomersOrders).CompanyName”)

    3          在代码中使用DataView对象

    DataView对象提供了与DataTable对象的Select方法类似的功能。

    3.1         创建DataView对象

    要使用DataView对象查看DataTable中数据,必须【将它与DataTable关联】。

    可以——使用DataViewTable属性;或者在DataView构造函数中——指定所要使用的DataTable

    Dim tbl as New DataTable(“TableName”)

    Dim vue as DataView

    Vue=new DataView()

    Vue.Table=tbl

    Vue=new DataView(tbl)

    注意:如果使用DataView属性Table来设置关联的DataTable时,一定要保证DataTableTableName不能是默认值(就是空字符串)。

    这个限制在使用DataView的构造函数是就没有。

    DataView的另一个构造函数,签名与DataTable.Select方法极为接近。

    在其中,需要设置(DataViewTableRowFilterSortRowStateFilter

    Dim tbl as New DataTable(“Customers”)

    Dim dvrs as DataViewRowState

    Dvrs=DataViewRowState.ModifiedOriginal or DataViewRowState.Deleted

    Dim vue as newDataView()

    Vue.Table=tbl

    Vue.RowFilter=”Country=’USA’”

    Vue.Sort=”City DESC”

    Vue.RowStateFile=dvrs

    Vue=new DataView(tbl,”Country=’USA’”,”City DESC”, dvrs)

    3.2         使用RowStateFilter属性

    RowStateFilter属性接受DataViewRowState枚举类型值。

    RowStateFilter属性,能起到双重筛选程序的作用。比如:值ModifiedOriginal,表示修改过的行,会显示原始值。

    DataViewRowState枚举值表

    说明

    Added

    包括新添加的行

    CurrentRows

    包括未删除的行(这是默认值)

    Deleted

    包括被删除的行。

    ModifiedCurrent

    包括被修改的行,且显示“当前值”

    modifiedOriginal

    包括被修改的行,且显示“原始值”

    None

    不包括任何行

    OriginalRows

    所有的行(被删除的、被修改的、未被删除的),都显示“原始值”

    Unchanged

    包括未被修改的行

    3.3         使用DataRowView对象

    在使用DataTable.Select方法时,存在以下问题:如果指定了ModifiedOriginal,那么返回的是被修改过的行,对于返回的DataRow对象,需要调用过程才能得到行的原始值。

    因为DataView对象返回数据使用的是专门的“DataRowView对象”。

    DataRowView提供了与DataRow类似的功能,它公开了默认的Item属性,使用该属性,通过提供列名或者列索引来访问列的内容。DataRowViewItem属性,可以用来检查和修改行的内容;但是,“通过DataRowView只能使用一个版本的行数据”,也就是说,在DataView对象的DataRowVersion属性中指定哪个版本的数据,DataRowView就只能显示这个版本数据。

    Dim tbl As New DataTable(“Customers”)

    ...

    Dim vue As DataView

    Vue=New DataView(tbl)

    Dim row as DataRowView=vue(0)

    Console.WriteLine(vue(“CompanyName”)

    如果发现DataRowView对象的功能不足以满足要求,可以使用DataRowViewRow属性访问相应的DataRow对象。

    3.4         通过DataView检查所有可用数据各行

    DataView访问数据与直接访问DataTable数据略有不同。

    DataTable通过Row属性公开了自己的数据行(你可以用For Each遍历内容);

    DataView则没有此种可枚举的集合来公开数据。

    DataView对象公开了一个Count属性,该属性返回DataView可见行的数量。通过它可以构造一个For循环检查各行。

    DataView还公开了一个返回IEnumerator对象的方法(GetEnumerator)。IEnumerator对象属于System.Collections命名空间,提供了与DataReaderMoveNext方法类似的导航功能。

    Dim tbl as New DataTable(“Customers”)

    ...

    Dim vue as DataView

    Vue=New DataView(tbl,””,””,DataViewRowState.ModifiedOriginal)

    Dim rowView as DataRowView

     

    Dim intCounter as Integer

    For intCounter=0 to vue.count-1

         RowView=vue(intCounter)

         Console.WriteLine(rowView(“CompanyName”))

    Next intcounter

     

    Dim objEnum as IEnumerator=vue.GetEnumerator()

    Do While objEnum.MoveNext()

         Row=Ctype(objEnum.Current,DataRowView)

         Console.WriteLine(row(“Companyname”))

    Loop

    3.5         DataView中搜索数据

    DataView对象使用:RowFilterRowStateFilter——支持“筛选”。

    它还使用:FindFindRows方法——支持“搜索”。

    3.5.1   Find方法

    使用Find方法,首先要设置DataViewSort属性。Find方法根据Sort属性中指定的列来查找,可以 提供一个或多个值。

    不过,DataViewFind方法的返回值:不是DataRow或者DataRowView对象;它返回一个整数值,对应所需行在DataView中的索引。如果没找到,返回值为-1

    Dim strConn As String =”Providor=SQLOLEDB;Data Source=...;Initial Catalog=Northwind;
    Trusted_Connection=Yes;”

    Dim strSql As String=”Select ComstomerID,CompanyName,ContactName,Phone,City,Country
    from Customers”

    Dim da As New OleDBDataAdapter(strSql,strConn)

    Dim tbl As new DataTable()

    Da.Fill(tbl,”Customers”)

     

    Dim vue as New DataView(tb)

    Vue.Sort=“ContactName”

    Dim i As Integer=vue.Find(“Fran Wilson”)

    If i=-1 Then

        Console.WriteLine(“Row Not Found”)

    Else

        Console.WriteLine(vue(i)(“CompanyName”))

    End IF

    3.5.2   FindRows方法

    DataRowCollection对象中,其Find方法会根据DataTable对象的“PrimaryKey属性”,进行搜索,因为(主键也与惟一键约束相关联),所以最多只能有一行满足
    DataRowCollection.Find
    方法所指定的条件。

    然而,DataView对象的Find方法是根据(其Sort属性中指定的列)来进行搜索,DataView中的数据在此排序列可能有多行数据是相同值,此时不能用DataView.Find定位所有的【相同值数据行】,因为Find方法返回值是一个整数。

    DataView对象的另一个方法【FindRows】可以完成这种功能,调用方法跟Find一样,但它返回满足条件的DataRowView对象数组。

    ...

    Dim vue As New DataView(tbl)

    Vue.Sort=”Country”

    Dim arows as DataRowView()=vue.FindRows(“Spain”)

    If arows.Length=0 Then

        Console.WriteLine(“没找到”)

    Else

        Dim row As DataRowView

        For Each row in arows

               Console.WriteLine(row(“City”))

        Next Row

    End If

    3.6         修改DataRowView对象

    DataRowView对象修改一行数据,类似于修改DataRow的内容。

    DataRowView对象也公开了BeginEditEndEditCancelEditDelete方法。

    创建新数据行时,DataRowViewDataRow有点不同:

    DataView有一个AddNew方法,它返回一个新DataRowView,在返回的DataRowView调用EndEdit方法之后,新行才真正被添加到底层的DataTable

    Dim tbl as New DataTable(“Customers”)

    ...

    Dim vue as New DataView(tbl)

    Dim row as DataRowView=vue.AddNew()

    Row(“CustomerID”)=”ABCDE”

    Row(“CompanyName”)=”New Company”

    Row(“ContactName”)=”New Contact”

    Row(“Phone”)=”(617) 555-1212”)

    Row.EndEdit()

    修改一行

    Row.BeginEdit()

    Row(“CompanyName”)=”Modified”

    Row.EndEdit()

    删除一行

    Row.Delete()

     

  • 相关阅读:
    餐饮点菜控件
    数据模块池
    关于sqlite数据库
    PHP使用DateTime类做时间日期到字符串转换
    php字符串比较函数
    Xdebug开源PHP程序调试器
    ubuntu chmod 无法更改 文件夹权限 系统提示“不允许的操作 2、linux 如何修改只读文件 3、ubuntu安装
    ubuntu的命令day1
    linux用终端上传文件和文件家到远程的服务器
    Symfony学习--原创。。。。
  • 原文地址:https://www.cnblogs.com/lizunicon/p/1344631.html
Copyright © 2020-2023  润新知