实验三:将读取数据功能从Repository中分离

先理解下面这段话之后再开始做实验

经过实验二的改造之后,我们代码有一点结构的概念了:

Listing.aspx:向Repository要Products,然后将得到的Products在页面中显示出来。

Repository:负责从数据库中读取数据,并将数据转换成对象集合。

代码结构的改造之路还没完,请看下面的情况。

如果数据库中多了一张表:订单表(Orders)。订单表中的所有订单当然也需要读出来显示在页面上。参考读取产品的做法,我们需要在Repository中增加一个像Products类似的属性:Orders。Repository类的代码如下:

 1 using System.Collections.Generic;
 2 using System.Data.SqlClient;
 3
 4 namespace SportStoreEx
 5 {
 6     public class Repository
 7     {
 8         public IEnumerable<Product> Products
 9         {
10             get
11             {
12                 IList<Product> products = new List<Product>();
13
14                 var sql = "select ProductID,Name,Description,Category,Price from Products";
15                 var con = new SqlConnection("Data Source=.;Initial Catalog=SportsStore;Integrated Security=True");
16                 var cmd = new SqlCommand(sql, con);
17                 SqlDataReader dr;
18
19                 con.Open();
20                 dr = cmd.ExecuteReader();
21                 while (dr.Read())
22                 {
23                     var prod = new Product
24                     {
25                         ProductID = dr.GetInt32(0),
26                         Name = dr.GetString(1),
27                         Description = dr.GetString(2),
28                         Category = dr.GetString(3),
29                         Price = dr.GetDecimal(4)
30                     };
31                     products.Add(prod);
32                 }
33                 return products;
34             }
35         }
36
37         public IEnumerable<Order> Orders
38         {
39             get
40             {
41                 IList<Order> Orders = new List<Order>();
42
43                 var sql = "select OrderID,ProductID,Count from Orders";
44                 var con = new SqlConnection("Data Source=.;Initial Catalog=SportsStore;Integrated Security=True");
45                 var cmd = new SqlCommand(sql, con);
46                 SqlDataReader dr;
47
48                 con.Open();
49                 dr = cmd.ExecuteReader();
50                 while (dr.Read())
51                 {
52                     var ord = new Order
53                     {
54                         //OrderID = dr.GetInt32(0),
55                         //ProductID = dr.GetInt32(1),
56                         //Count = dr.GetInt32(2)
57                     };
58                     Orders.Add(ord);
59                 }
60                 return Orders;
61             }
62         }
63     }
64 }

比较一下第8-35行与第37-62行代码,除了第23-31行与第52-57行不一样之外,其它部分是不是都差不多,都是连接数据库、执行查询之类的语句?每当读取一张数据表,都需要重复这些代码,从这个角度来说,我们的代码就有进一步改造的必要。(还有很多其它更复杂的原因,在这里没办法一一演示出来,对于初学者,只要知道目前这种程序结构只符合做一些小型、不复杂的应用,企业级应用是没法用这种结构的)

好了,解释完进一步改造的原因,下面来看看如何改造。

再分析一下Repository类的Products属性的get访问器里面的代码,从逻辑功能上来看,它由两部分组成,一个部分是负责访问数据库,另一部分是负责将从数据库读到的记录转换成Product对象,即完成“记录->对象”的转换。

对于每一张数据表来说,读取的过程是一样的(都是建立连接SqlConnection对象,建立指令操作SqlCommand对象,打开数据库,开始读数据),但转换成实体对象的过程不一样(因为每个实体对象的属性不一样)。

所以,我们改造的目标是将读取数据库的过程提取出来,做成一个公用的功能,留下“记录->对象”转换过程在Repository中。

具体步骤

1.在SportStoreEx项目中添加一个新类:SqlHelper,

SqlHelper类代码如下:

using System.Data;
using System.Data.SqlClient;

namespace SportStoreEx
{
    public class SqlHelper
    {
        public static SqlDataReader ExecuteDataReader(string connectionString, string sql)
        {
            SqlConnection con = new SqlConnection(connectionString);
            SqlCommand command = new SqlCommand(sql, con);
            con.Open();
            //当调用ExecuteReader()方法的时候,如果传递一个CommandBehavior.CloseConnection参数,则表示将来当用户关闭reader的时候,系统会自动将Connection也关闭掉。
            return command.ExecuteReader(CommandBehavior.CloseConnection);
        }
    }
}

2.修改Repository类代码

Repository.cs文件代码如下:

 1 using System.Collections.Generic;
 2 using System.Data.SqlClient;
 3
 4 namespace SportStoreEx
 5 {
 6     public class Repository
 7     {
 8         string conString = "Data Source=.;Initial Catalog=SportsStore;Integrated Security=True";
 9         public IEnumerable<Product> Products
10         {
11             get
12             {
13                 IList<Product> products = new List<Product>();
14
15                 var sql = "select ProductID,Name,Description,Category,Price from Products";
16
17                 using (SqlDataReader dr = SqlHelper.ExecuteDataReader(conString, sql))
18                 {
19                     while (dr.Read())
20                     {
21                         var prod = new Product
22                         {
23                             ProductID = (int)dr["ProductID"],
24                             Name = (string)dr["Name"],
25                             Description = (string)dr["Description"],
26                             Category = (string)dr["Category"],
27                             Price = (decimal)dr["Price"]
28                         };
29                         products.Add(prod);
30                     }
31                 }
32                 return products;
33             }
34         }
35     }
36 }

解释:

(1)第8行:因为Repository类中,不管是Products属性还是将要添加的Orders属性,它们使用的数据库连接字是一样的,所以将这个连接字conTxt从Products属性里面拿出来,放在Repository类中,作为类一级的成员,这样Repository类中所有属性或方法中都可以使用这个公共的conTxt了,各个属性内部没必要重新再定义一次连接字。

(2)第17行:这里调用了第1步中创建的SqlHelper类的ExecuteDataReader()方法,让它去读数据库,ExecuteDataReader()方法返回数据库结果,交给dr变量。看看,读数据库的过程对于Repository来说是不是变简单了,只需要调用一个类的方法就有数据了有木有?

本行代码使用了using语句,该语句的语法知识不是本篇重点讲解的内容,为了使本篇重点突出,内容紧凑,这里不做详细解释,请大家参考:c# using作用

(3)第21-28行:负责将dr中的一行记录转换成一个Product类对象。

看到了吧,通过以上2步改造,我们获得了如下好处:

(1)从数据库读取数据的任务由SqlHelper类的ExecuteDataReader方法负责,不管是读取哪个数据库、哪个数据表,都可以让它去干,只要告诉他数据库连接字和sql语句就行了。

(2)将已经得到Products数据表的记录转换成Product对象的事情交给Repository的Products属性负责。

程序结构更加清晰了有木有?各个类各司其职了有木有?想一想我们实际生活中是不是也是这么回事?习大大负责国家大政方针,强哥负责经济发展,正因为他们每个老大有负责自己的事情,所以国家机器才能够正常运转。不像一个夫妻小店,啥事都夫妻两干,干累死也没法将店面干大,最后实在太累不得不倒闭关门。

注意:以上代码仅仅是向初学者演示怎样分模块编程,旨在帮助初学者理解《精通ASP.NET4.5编程》书籍中SportStore网站代码,本实验中演示的代码并不能当做实际开发方法来使用。实际的ADO.NET开发比这里演示的复杂得多。

时间: 2024-10-12 19:57:28

实验三:将读取数据功能从Repository中分离的相关文章

通过jquery,从json中读取数据追加到html中

1.下载安装jquery 可通过下面的方法引入在线版本的js: <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> 参考安装文档:http://www.runoob.com/jquery/jquery-install.html 2.准备一个json格式的文件,后缀可以不是.json 例如下面是result.json的格式 {    "title&q

34)PHP,PHP从数据库读取数据并在html中显示

首先是我的数据库截图: 然后展示我的php文件: 1 b.php文件: 2 <?php 3 4 5 $link= mysqli_connect('localhost','root','root'); 6 // mysqli_character_set_name(); 7 mysqli_query($link,"set names utf8"); 8 mysqli_select_db($link,'thkphp5'); 9 $sql='select * from zixun'; 1

flink 从mysql 读取数据 放入kafka中 用于搜索全量

接着上一篇,将mysql的数据导入kafka中 public static void main(String[] arg) throws Exception { TypeInformation[] fieldTypes = new TypeInformation[] { BasicTypeInfo.STRING_TYPE_INFO }; RowTypeInfo rowTypeInfo = new RowTypeInfo(fieldTypes); JDBCInputFormat jdbcInput

sas数据读取详解 四种读取数据方式以及数据指针的位置 、读取mess data的两个小工具、特殊的读取技巧、infile语句及其选项(dsd dlm missover truncover obs firstobs)、proc import、自定义缺失值

(The record length is the number of characters, including spaces, in a data line.) If your data lines are long, and it looks like SAS is not reading all your data, then use the LRECL= option in the INFILE statement to specify a record length at least

实验三( 实时系统的移植)问题总结

实验三问题总结 问题链接:20145327 <信息安全系统设计基础>实验三 实时系统的移植 开发板是怎样进入linux和vv模式在成功连接开发板后,如果键入回车Enter键,就进入linux模式,键入其他任何键,进入vv模式 Exp11编译失败这是因为代码文件夹中有Exp11_Data文件夹,删除后即可编译成功 安装ADS(安装文件在00-ads1.2目录下,破解方法00-ads1.2\Crack目录下)安装时注意先将原安装的ADS卸载,然后再重新安装方可以成功 在两台机器上做最后一步都未能成

Hibernate上传数据到数据库,从数据库读取数据到本地模板代码

Hibernate上传数据到数据库: 1 //创建一个session对象 2 Session session1=HibernateTools.getSession(); 3 //Fenciresult数据库表所对应的实体类,生成实体类对象,操作数据库表 4 Fenciresult fenciresult=new Fenciresult(); 5 //设置数据库对应字段的值,主键若是自增模式,无需人为设置 6 fenciresult.setWord("@"); 7 fenciresult

Java基础知识强化之IO流笔记45:IO流练习之 把文本文件中数据存储到集合中的案例

1.  把文本文件中数据存储到集合中      需求:从文本文件中读取数据(每一行为一个字符串数据)到集合中,并遍历集合. 分析:      通过题目的意思我们可以知道如下的一些内容,      数据源是一个文本文件.      目的地是一个集合.      而且元素是字符串.      数据源:   b.txt -- FileReader -- BufferedReader  目的地:  ArrayList<String> 2. 代码示例: 1 package cn.itcast_02; 2

10天学会phpWeChat——第三天:从数据库读取数据到视图

在第二天,我们创建了我们的第一个phpWeChat功能模块,但是比较简单.实际生产环境中,我们不可能有如此简单的需求.更多的情况是数据存储在MySql数据库中,我们开发功能模块的作用就是将这些数据从MySql读取并通过视图多样化的呈现给用户. 今天我们进入<10天学会phpWeChat>系列教程的第三天:从数据库读取数据到视图. 一.首先,我们创建一个MySql数据文章表(pw_wechat_hello_article)用来存储要显示给用户的数据. 为了简单明了,这个表我们只保留3个字段: I

关于oracle数据库读取数据的三种方式

打开oracle sqldeveloper,连接到HR模式下的数据库,在SQL工作表中,执行如下语句: CREATE TABLE WANG( Name  varchar2(6), ID     number        ); 然后向表中插入如下语句: INSERT INTO WANG VALUES('WANG',1): INSERT INTO WANG VALUES('CHENG',2); INSERT INTO WANG VALUES('ZHOU',3); INSERT INTO WANG