对象的筛选

对象的筛选

 

前面说了泛型和委托,说完筛选和排序之后会说LINQ,所以这段时间的知识会起到一个承上启下的作用.

主要是讲解一下.NET框架中最常用的接口之一:IComparable;还会说点在LINQ出现之前对象筛选和排序的方法.

 

对象的筛选

 

不知道大家接触过SQL语句没有,楼主是学过了,这里就当你学过了吧,如果我们要对数据进行筛选,首先想到的是”Where”子句,而不是List<T>.FindAll();当我们需要对数据进行排序的时候,我们会想到”Order By”子句,而不是List<T>.Sort();当我们需要对数据进行分页的时候,首先想到的存储过程,而不是List<T>.GetRange().

 

为啥呢?因为让数据库去完成这些东西在很多情况下效率高,尤其是在数据量比较大,这就是为啥会出现数据库的原因,一开始的数据量比较小,用的TXT就够了,但是随着数据的增大,TXT不够用了,出现了各种各样的数据库,现在数据库也不够用了,所以出现了分布式存储.在数据量不大的时候,一次将所有数据取出,然后缓存在服务器上,对于以后的排序,筛选,分页请求仅针对缓存进行,这样做绝对有好处,而且效率高,为啥呢?因为服务器的运算效率是很高的,而且由于数据不大,所以数据库在短时间内就能够完成相应的操作.

 

但是世事无绝对,没有哪种方法绝对的优秀,一种好的方法或者不好的方法仅仅适用于一种范围.

本节的内容就是说一下当数据量特别大的时候,可能不仅仅希望数据先用”where”子句进行筛选,还希望再一次筛选只返回当前页需要显示的数据条目.

 

基于拼装SQL的筛选

 

先思考这样一个案例:SQL Server 2000中的默认数据库North Wind中的Orders订单表中,如果要在一个Asp.NET WebForm页面上对它按年月日的任意组合进行筛选,咋办?我觉得步骤应该会是这样:

1.在页面上创建三个下拉框,分别用于对年月日进行选择.

2.当用户第一次访问页面时,显示所有数据.此时有一次对数据库的访问,返回全部数据,SQL语句为”select * from orders”

3.用户选择年月日中的任意一个,产生一个PostBack

4.根据用的选择拼装一个SQL语句,例如”where Year(OrderDate)=@Date and Month(OrderDate)=@Month”.

5.将SQl语句发送到数据库,数据库返回查询结果,显示到用户界面.

 

如果你对数据就不了解,上面的过程就是根据用户的选择,呈现不同的数据.

 

在上面的模式中,为了根据用户的选择显示不同的数据,每次操作(即每次产生一个PostBack)都要对数据进行一次访问.下面看一下具体的实现过程是咋样的.

 

先别管那些乱七八糟的,咱们要想实现前后台的交互,需要创建一个Orders类来表示业务对象Order(位于Order.cs).

先看这个Order.cs咋实现

    public class Order
    {
        //分别表示订单ID,用户ID,下单日期,国家
        private int orderId;
        private string customerId;
        private DateTime orderDate;
        private string country;
 
        public int OrderId
        {
            get
            {
                return orderId;
            }
 
            set
            {
                orderId = value;
            }
        }
 
        public string CustomerId
        {
            get
            {
                return customerId;
            }
 
            set
            {
                customerId = value;
            }
        }
 
        public string Country
        {
            get
            {
                return country;
            }
 
            set
            {
                country = value;
            }
        }
 
        public DateTime OrderDate
        {
            get
            {
                return orderDate;
            }
 
            set
            {
                orderDate = value;
            }
        }
    }


我就想问问还有比这个类还简单的吗?这个表就是表示关于Order的一些信息.对于集合数据,这里使用List<Order>进行存储.接下来需要再创建文件OrderManager.cs,用于从数据库返回结果,并填充List<Order>.OrderManager.cs中通常包含类似这样的代码:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
 
namespace WebApplication1
{
    public class OrderManager
    {
        public static List<Order> GetList(string query)
        {
            List<Order> list = null;
            SqlDataReader reader = ExecuteReader(query);
            if (reader.HasRows)
            {
                list = new List<Order>();
                while (reader.Read())
                {
                    list.Add(GetItem(reader));
                }
            }
            reader.Close();
            return list;
        }
        //获取一个SqlDataReader对象
        private static SqlDataReader ExecuteReader(string query)
        {
            string connString = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;
            SqlConnection conn = new SqlConnection(connString);
            SqlCommand cmd = new SqlCommand(query, conn);
            conn.Open();
            SqlDataReader reader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
            return reader;
 
        }
 
        //从一行获取一个Order对象.
        private static Order GetItem(IDataRecord record)
        {
            Order item = new Order();
            item.OrderId = Convert.ToInt32(record["orderId"]);
            item.CustomerId = record["CustomerId"].ToString();
            item.OrderDate = Convert.ToDateTime(record["OrderDate"]);
            item.Country = record["ShipCountry"].ToString();
            return item;
        }
    }
}


上面贴的这几段代码都没有,比完全可以不用看,为啥我想贴呢,因为楼主忘了,打一遍可以回复一下记忆.

上面的代码很好理解:GetList()方法接受一个查询语句,然后返回List<Order>列表.

ExecuteReader()方法,该方法根据传递进去的查询语句query创建并返回了一个SqlDataReader对象,该对象用于读取数据库返回的数据.While语句中,调用了GetItem()方法,该方法根据每一个数据创建一个Order对象.最后将Order对象添加到List<Order>列表中,并返回列表.

 

可见,需要在页面上调用的方法就是GetList(query)方法了.

 

一般的基于传统的拼装SQL语句的筛选我就不多了,为啥呢,因为很复杂,我需要做很多工作,接下来咱们重点说一声基于对象筛选是啥样的,又是怎么样提升性能.

(1)在页面上创建三个下拉框,分别用于对年,,日进行选择.

(2)用户第一次访问页面,显示所有数据.将对数据库进行一次访问,并获取全部数据,SQL语句类似于”select * from Orders”

(3)将返回的数据(已经转换成了List<Order>业务对象)全部进行缓存.

(4)根据用户的选择对缓存中的List<Order>进行筛选,返回筛选结果,显示在页面上.

(5)如此反复,用户每次用户请求都只针对缓存进行.

 

关于缓存,你只需要只用使用Cache.Insert(key,value)就行了.最后再说一点,当使用Cache.Insert(key,value)插入缓存时,虽然没有过期时间,但是当服务器内存空间不足时,依然会将缓存移除.

 

本例中,基于对象的筛选就是对List<Order>进行筛选.实现思路很简单,创建一个重载的GetList()方法,在这个GetList()中取回所有的Order并添加到缓存中.然后创建一个新的空List<Order>列表,从缓存中去除List<Order>进行遍历,将符合条件的项加入到刚刚创建的新列表中,最后返回新列表.

 

        public static List<Order> GetList()
        {
            List<Order> list = HttpContext.Current.Cache["fullList"] as List<Order>;
 
            if (list==null)
            {
                list = GetList("select orderId,CustomerId,ShipCountry,OrderDate from orders");
                //添加缓存,永不过期(可以再删除,更新操作时手动让缓存过期)
                HttpContext.Current.Cache.Insert("fullList",list);
            }
            return list;
        }

上面无参数的GetList()方法在没有缓存的情况下调用GetList(query)方法,返回全部列表,然后加入缓存;在有缓存的情况下直接使用缓存中的数据.

 

使用List<T>.FindAll(Predicate<T>match)进行筛选

List<T>上提供了一个FindAll(Predicate<T>match)方法来进行筛选工作,有方法的参数Predicate<T>封装筛选的规则.Predicate<T>是一个泛型委托,这意味着match参数是一个返回bool类型的方法,FindAll()呢部,将会调用传递进去的这个方法.

 

我写的这些例子应该都不能运行,因为还有好多工作没做,比如连接数据库,配置文件的修改,各种操作.我写代码的原因只是想让大家了解一下我想说的东西,因为楼主的资历尚浅,说也说不明白,我就说说楼主能明白的东西,也希望能用最简单的方式让你明白,那么楼主的作用就达到了.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值