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

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

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

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

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

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

 using System.Collections.Generic;
using System.Data.SqlClient; namespace SportStoreEx
{
public class Repository
{
public IEnumerable<Product> Products
{
get
{
IList<Product> products = new List<Product>(); var sql = "select ProductID,Name,Description,Category,Price from Products";
var con = new SqlConnection("Data Source=.;Initial Catalog=SportsStore;Integrated Security=True");
var cmd = new SqlCommand(sql, con);
SqlDataReader dr; con.Open();
dr = cmd.ExecuteReader();
while (dr.Read())
{
var prod = new Product
{
ProductID = dr.GetInt32(),
Name = dr.GetString(),
Description = dr.GetString(),
Category = dr.GetString(),
Price = dr.GetDecimal()
};
products.Add(prod);
}
return products;
}
} public IEnumerable<Order> Orders
{
get
{
IList<Order> Orders = new List<Order>(); var sql = "select OrderID,ProductID,Count from Orders";
var con = new SqlConnection("Data Source=.;Initial Catalog=SportsStore;Integrated Security=True");
var cmd = new SqlCommand(sql, con);
SqlDataReader dr; con.Open();
dr = cmd.ExecuteReader();
while (dr.Read())
{
var ord = new Order
{
//OrderID = dr.GetInt32(0),
//ProductID = dr.GetInt32(1),
//Count = dr.GetInt32(2)
};
Orders.Add(ord);
}
return Orders;
}
}
}
}

比较一下第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文件代码如下:

 using System.Collections.Generic;
using System.Data.SqlClient; namespace SportStoreEx
{
public class Repository
{
string conString = "Data Source=.;Initial Catalog=SportsStore;Integrated Security=True";
public IEnumerable<Product> Products
{
get
{
IList<Product> products = new List<Product>(); var sql = "select ProductID,Name,Description,Category,Price from Products"; using (SqlDataReader dr = SqlHelper.ExecuteDataReader(conString, sql))
{
while (dr.Read())
{
var prod = new Product
{
ProductID = (int)dr["ProductID"],
Name = (string)dr["Name"],
Description = (string)dr["Description"],
Category = (string)dr["Category"],
Price = (decimal)dr["Price"]
};
products.Add(prod);
}
}
return products;
}
}
}
}

解释:

(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开发比这里演示的复杂得多。

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

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

    1.下载安装jquery   可通过下面的方法引入在线版本的js: <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jque ...

  2. Python学习笔记_从CSV读取数据写入Excel文件中

    本示例特点: 1.读取CSV,写入Excel 2.读取CSV里具体行.具体列,具体行列的值 一.系统环境 1. OS:Win10 64位英文版 2. Python 3.7 3. 使用第三方库:csv. ...

  3. Flink 使用(一)——从kafka中读取数据写入到HBASE中

    1.前言 本文是在<如何计算实时热门商品>[1]一文上做的扩展,仅在功能上验证了利用Flink消费Kafka数据,把处理后的数据写入到HBase的流程,其具体性能未做调优.此外,文中并未就 ...

  4. 从JSON中读取数据追加到HTML中

    本文来自https://www.jianshu.com/p/04127d74d88c,并非本人原创,只是作为自己学习使用的资料,如有浏览者请点击地址自行到原作者页面浏览 有时候我们需要将json数据直 ...

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

    首先是我的数据库截图: 然后展示我的php文件: b.php文件: <?php $link= mysqli_connect('localhost','root','root'); // mysq ...

  6. TensorFlow读取数据的三种方法

    tensortlfow数据读取有三种方式 placehold feed_dict:从内存中读取数据,占位符填充数据 queue队列:从硬盘读取数据 Dataset:同时支持内存和硬盘读取数据 plac ...

  7. 201871030132-熊文婷 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告

    项目 内容 课程班级博客链接 https://edu.cnblogs.com/campus/xbsf/2018CST 这个作业要求链接 https://www.cnblogs.com/nwnu-dai ...

  8. 201871030139-于泽浩 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告

    201871030139-于泽浩 实验三 结对项目-<D{0-1}KP 实例数据集算法实验平台>项目报告 项目 内容 课程班级博客链接 2018级卓越班 这个作业要求链接 软件工程结对项目 ...

  9. c和c++中读取数据的方式总结

    目录 c 输出 printf() 输入 scanf getchar(), putchar() gets(), puts() c++ 输入 cin() getline() get() 输出 cout 最 ...

随机推荐

  1. 随手记录-linux-Shellinabox插件

    Shellinabox 是一个利用 Ajax 技术构建的基于 Web 的远程Terminal 模拟器,也就是说安装了该软件之后,不需要开启 ssh服务,通过 Web 网页就可以对远程主机进行维护操作了 ...

  2. crontab任务不生效

    新建php脚本ctTest.php,代码如下: <?php /****************************************************************** ...

  3. 20162314 《Program Design & Data Structures》Learning Summary Of The First Week

    20162314 2017-2018-1 <Program Design & Data Structures>Learning Summary Of The First Week ...

  4. 手机端学习助手的说明书需求以及团队PM选择

    1.产品的背景 课堂上知识容量大.密度高,学生不能立刻掌握所学知识点,同时,网上资料冗杂繁复,指向性不强,导致学生不能高效的学习,为了充分利用学生的课余时间,培养学生自学能力,辅助老师教学,我们小组希 ...

  5. angularJS1笔记-(20)-模块化加载机制seajs

    SeaJS是一个遵循CMD规范的JavaScript模块加载框架,可以实现JavaScript的模块化开发及加载机制. 与jQuery等JavaScript框架不同,SeaJS不会扩展封装语言特性,而 ...

  6. Alpha冲刺阶段博客汇总

    第一篇(冲刺前安排):http://www.cnblogs.com/Aragaki-Yui/p/8893752.html 第二篇(冲刺第一天):http://www.cnblogs.com/Araga ...

  7. Oculus VR眼镜调研

    VR眼镜 oculus 软件安装 最详细的Oculus Rift VR/3D眼镜安装设置教程(多图) 在线安装Oculus rift驱动[非VPN方法] Rift,Go,Gear VR,Quest: ...

  8. Beta阶段——第二篇 Scrum 冲刺博客

    i. 提供当天站立式会议照片一张: ii. 每个人的工作 (有work item 的ID) (1) 昨天已完成的工作: 账单收支分明,剩余舍费关联成功 (2) 今天计划完成的工作: 账单删除功能,排序 ...

  9. jmeter body 中文显示为乱码解决

    这种情况在jmeter3.0的版本中才会产生,注意:这不是乱码,而是由于3.0中优化body data后,使用默认的字体(Consolas)不支持汉字的显示.这样的情况可以这样调整:进入jmeter. ...

  10. Java中split的对象被特殊字符(.或|)分隔

    在Java中,一个String对象被一些特殊字符分隔时,可以使用split()方法,生成一个String[],然后进行其他的操作,就像下面这样: String str = "a1_b1_c1 ...