标签:code tde back 传递 cat font 数据库 public 讲解
经过实验二的改造之后,我们代码有一点结构的概念了:
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开发比这里演示的复杂得多。
标签:code tde back 传递 cat font 数据库 public 讲解
原文地址:http://www.cnblogs.com/bayes/p/6030503.html