zoukankan      html  css  js  c++  java
  • 通过DataReader获取多个结果集

    我们知道,ado.net的DataReader提供一种从数据库读取行的只进流的方式。通常情况下,我们都是针对一个结果集进行处理。其实通过DataReader的NextResult方法,我们可以批处理T-SQL,也就是可以获取处理两个或者多个结果集。下面通过一个简单的示例,来简单说明一下这个功能。
    1、数据表
    我们还是沿用这一篇里的Person表。在Person表里,我们定义了自增长的Id,姓、名、身高和体重,它们对应的字段和实体里的属性命名是一样的。

    2、实体类


        
    public class Person
        {
            
    public int Id { getset; }
            
    public string FirstName { getset; }
            
    public string LastName { getset; }
            
    public double Weight { getset; }
            
    public double Height { getset; }

            
    /// <summary>
            
    /// 总记录数
            
    /// </summary>
            public long TotalCount { getset; }
        }

    需要说明的是,TotalCount属性是我们自己根据统计需要,添加的用来统计符合条件的人的总记录数,并不是Person表的一个实际字段。

    3、数据实体转换

    代码
     public class SqlHelper
        {
            
    private const string strSqlCon = @"Data Source=.\sqlexpress; Initial Catalog=TestDb; User Id=sa; Password=123456;";

            
    /// <summary>
            
    /// 数据表项转换为对应实体 (操作两个结果集 有总记录数)
            
    /// </summary>
            
    /// <typeparam name="T"></typeparam>
            
    /// <param name="objType"></param>
            
    /// <param name="strSelectSql"></param>
            
    /// <returns></returns>
            public static IList<T> Select<T>(Type objType, string strSelectSql) where T : classnew()
            {
                IList
    <T> listModels = new List<T>();
                
    using (SqlConnection sqlConn = new SqlConnection(strSqlCon))
                {
                    sqlConn.Open();
                    SqlCommand cmd 
    = new SqlCommand();
                    cmd.Connection 
    = sqlConn;
                    cmd.CommandText 
    = strSelectSql;
                    IDataReader rdr 
    = cmd.ExecuteReader();
                    Hashtable htColumns 
    = CreateHashColumnName(rdr);

                    
    while (rdr.Read())
                    {
                        Object obj 
    = Activator.CreateInstance(objType);
                        PropertyInfo[] properties 
    = objType.GetProperties();
                        
    foreach (PropertyInfo propInfo in properties)
                        {
                            
    if (htColumns.Contains(propInfo.Name.ToUpper()) == false)
                            {
                                
    continue;
                            }
                            
    int index = rdr.GetOrdinal(propInfo.Name);
                            
    if (index > -1 && rdr.GetValue(index) != System.DBNull.Value)
                                propInfo.SetValue(obj, rdr.GetValue(index), 
    null);
                        }
                        T model 
    = default(T);
                        model 
    = obj as T;
                        listModels.Add(model);
                    }

                    
    bool isNext = rdr.NextResult();//前进到下一个结果集
                    htColumns = CreateHashColumnName(rdr);//改变hashtable的对应列名
                    while (rdr.Read() && isNext)
                    {
                        
    for (int i = 0; i < listModels.Count; i++)
                        {
                            PropertyInfo[] props 
    = listModels[i].GetType().GetProperties();
                            
    foreach (PropertyInfo pi in props)
                            {
                                
    if (htColumns.Contains(pi.Name.ToUpper()))//取总记录数
                                {
                                    
    int index = rdr.GetOrdinal(pi.Name);
                                    
    if (index > -1 && rdr.GetValue(index) != System.DBNull.Value)
                                        pi.SetValue(listModels[i], rdr.GetValue(index), 
    null);
                                    
    break;//根据实际情况确定break需不需要注释掉
                                }
                            }
                        }
                    }
                }
                
    return listModels;
            }

            
    private static Hashtable CreateHashColumnName(IDataReader rdr)
            {
                
    int len = rdr.FieldCount;
                Hashtable ht 
    = new Hashtable(len);
                
    for (int i = 0; i < len; i++)
                {
                    
    string columnName = rdr.GetName(i).ToUpper(); //不区分大小写
                    string columnRealName = rdr.GetName(i);
                    
    if (ht.ContainsKey(columnName) == false)
                    {
                        ht.Add(columnName, columnRealName);
                    }
                }
                
    return ht;
            }

        }

    上面的代码中,注释写的很清楚,通过NextResult方法后,我们再次获取结果集的列(示例中保持在hashtable里),利用第一次获得结果集的方法和原理,给实体赋值。

    4、前台调用
    很简单,通过一个带分号的sql语句,获得一个实体集合。

    代码
        //批量sql语句 以;隔开
                string sql = "SELECT TOP 10 [Id] ,[FirstName],[LastName],[Weight],[Height] FROM Person (NOLOCK); SELECT COUNT(Id) AS TotalCount FROM Person (NOLOCK) ";
                IList
    <Person> listPersons = SqlHelper.Select<Person>(typeof(Person), sql);//操作两个结果集

    有图有真相:



    从图中我们可以清楚地看到,测试数据库里的总人数是1999918人。

    最后,请教最近使用linq2sql一点困扰我的地方:很多人津津乐道的Skip...Take分页(本质上据说就是二次top),好像无法直接取得总记录数(TotalCount),但是正常项目中都会通过总记录数确定分页效果。除了直接通过linq查询取Count之外,不知道大家有没有其他更好的方法,比如窗口函数row number,或者就像本文所表达的那样,批处理一次查询就搞定的那种?

  • 相关阅读:
    sizeof--返回一个数据类型或变量占用的字节数
    跳出循环break continue
    c-for循环
    while循环语句
    什么是Python中的套接字编程?
    详解Vue八大生命周期钩子函数
    你应该知道的数仓安全
    云图说|华为云自研云数据库GaussDB NoSQL,兼容多款NoSQL接口的数据库服务
    又到一年“粽子节”,快来测测你包的粽子颜值几分
    云小课 | 华为云KYON之私网NAT网关
  • 原文地址:https://www.cnblogs.com/jeffwongishandsome/p/1774904.html
Copyright © 2011-2022 走看看