Petshop4

 

一、Petshop4解决方案

 

 

 

Petshop4代码和数据库:下载

Petshop4详解:下载

 

安装要求:

Operating System: Windows XP SP2 or Windows Server 2003
Microsoft.NET Framework 2.0
Microsoft SQL Server 2005, SQL Server Express, or Oracle 10g
Microsoft Internet Explorer 6 or greater
Microsoft Visual Studio® .NET 2005

 

后续步骤:

1、手动编译:运行<Pet Shop 4 Install Folder>\Build.bat,将编译整个解决方案。

 

2、用VisualStudio自带的浏览器运行:

(1)打开解决方案。Start Menu | All Programs | Microsoft .NET Pet Shop 4 | Petshop.sln

(2)设置Web项目为启动项目

(3)右键单击“解决方案”节点,点“构建”

(4)打开Web项目,右键单击“Default.aspx”,点“在浏览器中查看”

(5)如果安装了Membership/Profile数据库,系统会创建12个帐号,即demo, AdamBarr, KimAbercrombie,RobYoung, TomYoutsey, GaryWYukish, RobCaron, KarinZimprich, RandallBoseman, KevinKennedy, DianeTibbott, 或GarrettYoung。密码是pass@word1

 

 

3、运行在windows server 2003的IIS上

(1)先解密web.config文件中的连接串。

   点击<Pet Shop 4 Install Folder>\DecryptWebConfig.bat解密连接串。不解密的话IIS会报错。

 

(2)由于2003IIS的.net版本最高为2.0。笔者在编译Petshop的Web项目时,需要设置属性页的“目标Framework”为2.0。如下图:

 

(3)视情况修改web.config中的数据库连接串,确保能正确连上数据库。

(4)将Web文件夹实施到IIS中。

    

 

     运行效果如下:

    

 

 

二、Petshop4体系结构

 

 

 

三、Petshop三层结构总结

 

1、表记录 --> 实体类

    将Category数据库表中的单个记录定义为一个类(叫产品实体),类的属性就是数据库表中每个记录的字段。产品实体承载数据表的记录。所有实体类的集合形成了Petshop中Model模块。Category实体的代码如下所示:

 

using System;

namespace PetShop.Model {

     public  class CategoryInfo {
         //属性
         private  string id;
         private  string name;
         private  string description;

         public CategoryInfo() { }

         public CategoryInfo( string id,  string name,  string description) {
             this.id = id;
             this.name = name;
             this.description = description;
        }

         //  属性的get操作
         public  string Id {
             get {  return id; }
        }
         public  string Name {
             get {  return name; }
        }
         public  string Description {
             get {  return description; }
        }
    }
}

 

 

2、记录的删改增查等操作 -> 转换成访问数据库的函数 -> 函数组织到一起形成类

 

3、-> 由于数据库多样性&访库操作的一致性(不外乎删改增查操作) -> 抽象出一个接口

    数据访问层采用“面向接口编程”思想,抽象出来的IDAL模块,脱离了与具体数据库的依赖,从而使得整个数据访问层利于数据库迁移。SQLServerDAL和OracleDAL模块均实现IDAL模块的接口,其中包含的逻辑就是对数据库的Select,Insert,Update和Delete操作。因为数据库类型的不同,对数据库的操作也有所不同,代码也会因此有所区别。

 

using System;
using PetShop.Model;
using System.Collections.Generic;

namespace PetShop.IDAL{

     ///   <summary>
    
///  类别数据访问层的接口
    
///   </summary>
     public  interface ICategory {

         ///   <summary>
        
///  此方法用于获得所有宠物类别
        
///   </summary>         
        
///   <returns> 此接口用于生成普通类别的模型集合 </returns>
        IList<CategoryInfo> GetCategories();

         ///   <summary>
        
///  获取某个宠物类别的信息
        
///   </summary>
        
///   <param name="categoryId"> 宠物的唯一标示符 </param>
        
///   <returns> 描述一个宠物业务逻辑的实体类 </returns>
        CategoryInfo GetCategory( string categoryId);
    }
}

 

针对SQLServer数据库的实现

using System;
using System.Data;
using System.Data.SqlClient;
using PetShop.Model;
using PetShop.IDAL;
using System.Collections.Generic;
using PetShop.DBUtility;

namespace PetShop.SQLServerDAL {

     public  class Category : ICategory {

         //  声明静态变量
         private  const  string SQL_SELECT_CATEGORIES =  " SELECT CategoryId, Name, Descn FROM Category ";
         private  const  string SQL_SELECT_CATEGORY =  " SELECT CategoryId, Name, Descn FROM Category WHERE CategoryId = @CategoryId ";
         private  const  string PARM_CATEGORY_ID =  " @CategoryId ";


         ///   <summary>
        
///  此方法用于获得所有宠物类别信息
        
///   </summary>              
         public IList<CategoryInfo> GetCategories() {

            IList<CategoryInfo> categories =  new List<CategoryInfo>();

             // 执行获取所有宠物类别的SQL语句
             using(SqlDataReader rdr = SqlHelper.ExecuteReader(SqlHelper.ConnectionStringLocalTransaction, CommandType.Text, SQL_SELECT_CATEGORIES,  null)) {
                 while (rdr.Read()) {
                    CategoryInfo cat =  new CategoryInfo(rdr.GetString( 0), rdr.GetString( 1), rdr.GetString( 2));
                    categories.Add(cat);
                }
            }  
             return categories;
        }

         ///   <summary>
        
///  根据提供的id ,获取指定的单个宠物类别信息
        
///   </summary>
        
///   <param name="categoryId"> 宠物类别标识码d </param>
        
///   <returns> 单个宠物类别的详细资料 </returns>
         public CategoryInfo GetCategory( string categoryId) {

             // 设置一个返回值
            CategoryInfo category =  null;

             // 创建一个参数
            SqlParameter parm =  new SqlParameter(PARM_CATEGORY_ID, SqlDbType.VarChar,  10);
             // 绑定参数
            parm.Value = categoryId;

             // 执行查询
             using (SqlDataReader rdr = SqlHelper.ExecuteReader(SqlHelper.ConnectionStringLocalTransaction, CommandType.Text, SQL_SELECT_CATEGORY, parm)) {
                 if (rdr.Read())

                    category =  new CategoryInfo(rdr.GetString( 0), rdr.GetString( 1), rdr.GetString( 2));
                 else
                    category =  new CategoryInfo();
            }
             return category;
        }

         ///   <summary>
        
///  为创建宠物类别创建一个SqlCommand对象
        
///   </summary>
        
///   <param name="id"> 宠物类别码 </param>
        
///   <returns> 用于找回宠物类别的sql命令 </returns>
         public  static SqlCommand GetCommand() {
             return  new SqlCommand(SQL_SELECT_CATEGORIES);               
        }
    }
}

 

针对Oracle数据库的实现

using System;
using System.Data;
using System.Data.OracleClient;
using PetShop.Model;
using PetShop.IDAL;
using System.Collections.Generic;
using PetShop.DBUtility;

namespace PetShop.OracleDAL {

     public  class Category : ICategory {

         //  Static constants
         private  const  string SQL_SELECT_CATEGORIES =  " SELECT CategoryId, Name, Descn FROM Category ";
         private  const  string SQL_SELECT_CATEGORY =  " SELECT CategoryId, Name, Descn FROM Category WHERE CategoryId = :CategoryId ";
         private  const  string PARM_CATEGORY_ID =  " :CategoryId ";


         ///   <summary>
        
///  Method to get all categories
        
///   </summary>
         public IList<CategoryInfo> GetCategories() {

            IList<CategoryInfo> categories =  new List<CategoryInfo>();

             // Execute a query to read the categories
             using(OracleDataReader rdr = OracleHelper.ExecuteReader(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, SQL_SELECT_CATEGORIES,  null)) {
                 while (rdr.Read()) {
                    CategoryInfo cat =  new CategoryInfo(rdr.GetString( 0), rdr.GetString( 1), rdr.GetString( 2));
                    categories.Add(cat);
                }
            }

             return categories;
        }

         ///   <summary>
        
///  Get an individual category based on a provided id
        
///   </summary>
        
///   <param name="categoryId"> Category id </param>
        
///   <returns> Details about the Category </returns>
         public CategoryInfo GetCategory( string categoryId) {

             // Set up a return value
            CategoryInfo category =  null;

             // Create a parameter
            OracleParameter parm =  new OracleParameter(PARM_CATEGORY_ID, OracleType.Char,  10);
             // Bind the parameter
            parm.Value = categoryId;

             // Execute the query    
             using (OracleDataReader rdr = OracleHelper.ExecuteReader(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, SQL_SELECT_CATEGORY, parm)) {
                 if (rdr.Read())

                    category =  new CategoryInfo(rdr.GetString( 0), rdr.GetString( 1), rdr.GetString( 2));
                 else
                    category =  new CategoryInfo();
            }
             return category;
        }
    }
}

 

4、到配置文件中做“决定”

     用户如何决定用哪种访问数据的类来访问数据库?用户不必关心。因为这个决定写在配置文件web.config中了。迁移到另一种数据时,只需修改web.config,而不需要修改代码。 为了做到这一点,.NET用反射。代码如下:

web.config如下:

<?xml version= " 1.0 "?>
<configuration xmlns= " http://schemas.microsoft.com/.NetConfiguration/v2.0 ">
    <connectionStrings>
        <!-- SQL connection  string  for Profile database -->
        <add name= " SQLProfileConnString " connectionString= " server=(local);user id=sa;password=jazzking;database=MSPetShop4Profile;min pool size=4;max pool size=4;packet size=3072 " providerName= " System.Data.SqlClient "/>
        <!-- SQL connection  string  for Membership database -->
        <add name= " SQLMembershipConnString " connectionString= " server=(local);user id=sa;password=jazzking;database=MSPetShop4Services;min pool size=4;max pool size=4;packet size=3072 " providerName= " System.Data.SqlClient "/>
        <!-- SQL connection  string  for Inventory database lookup -->
        <add name= " SQLConnString1 " connectionString= " server=(local);user id=sa;password=jazzking;database=MSPetShop4;min pool size=4;max pool size=4;packet size=3072 " providerName= " System.Data.SqlClient "/>
        <!-- SQL connection  string  for handling transactions on the Inventory database-->
        <add name= " SQLConnString2 " connectionString= " server=(local);user id=sa;password=jazzking;database=MSPetShop4;min pool size=4;max pool size=4;packet size=1024 " providerName= " System.Data.SqlClient "/>
        <!-- SQL connection  string  for Orders database-->
        <add name= " SQLConnString3 " connectionString= " server=(local);user id=sa;password=jazzking;database=MSPetShop4Orders;min pool size=4;max pool size=4;packet size=1024 " providerName= " System.Data.SqlClient "/>
        <!-- Oracle connection strings-->
        <add name= " OraProfileConnString " connectionString= " Data Source=localhost;user id=MSPETSHOPPROFILE;password=pass@word1;min pool size=4;max pool size=4 " providerName= " System.Data.OracleClient "/>
        <add name= " OraMembershipConnString " connectionString= " Data Source=localhost;user id=MSPETSHOPMEMBERSHIP;password=pass@word1;min pool size=4;max pool size=4 " providerName= " System.Data.OracleClient "/>
        <add name= " OraConnString1 " connectionString= " Data Source=localhost;user id=MSPETSHOP;password=pass@word1;min pool size=4;max pool size=4 " providerName= " System.Data.OracleClient "></add>
        <add name= " OraConnString2 " connectionString= " Data Source=localhost;user id=MSPETSHOP;password=pass@word1;min pool size=4;max pool size=4 " providerName= " System.Data.OracleClient "></add>
        <add name= " OraConnString3 " connectionString= " Data Source=localhost;user id=MSPETSHOPORDERS;password=pass@word1;min pool size=4;max pool size=4 " providerName= " System.Data.OracleClient "></add>
    </connectionStrings>
    <appSettings>
        <!-- Pet Shop DAL configuration settings -->
        <!--设置数据库连接类型  value 此数据库联接类 -->
        <add key="WebDAL" value="PetShop.SQLServerDAL"/>
        <add key="OrdersDAL" value="PetShop.SQLServerDAL"/>

        <add key= " ProfileDAL " value= " PetShop.SQLProfileDAL "/>

 

对数据库中所有表的操作接口打成包方便统一访问,Petshop中叫数据库访问层工厂。如下:

using System.Reflection;
using System.Configuration;

namespace PetShop.DALFactory {

     public  sealed  class DataAccess {

         //  查找我们将要使用的数据访问层
         private  static  readonly  string path = ConfigurationManager.AppSettings[ " WebDAL "]; //对照web.config,此时path的值为“PetShop.SQLServerDAL ”。表示该系统使用了SQLServer数据库。
         private  static  readonly  string orderPath = ConfigurationManager.AppSettings[ " OrdersDAL "];
        
         private DataAccess() { }
         // 实现 CreateCategory 方法,用于创建Category类实例
         public  static PetShop.IDAL.ICategory CreateCategory() {
             string className = path +  " .Category ";
             // 利用反射技术,动态加载指定类型
             return (PetShop.IDAL.ICategory)Assembly.Load(path).CreateInstance(className);
        }
         // 实现 CreateInventory 方法,用于创建Inventory类实例  
         public  static PetShop.IDAL.IInventory CreateInventory() {
             string className = path +  " .Inventory ";
             return (PetShop.IDAL.IInventory)Assembly.Load(path).CreateInstance(className);
        }
         // 实现 CreateItem 方法,用于创建Item类实例  
         public  static PetShop.IDAL.IItem CreateItem() {
             string className = path +  " .Item ";
             return (PetShop.IDAL.IItem)Assembly.Load(path).CreateInstance(className);
        }
         // 实现 CreateOrder 方法,用于创建Order类实例  
         public  static PetShop.IDAL.IOrder CreateOrder() {
             string className = orderPath +  " .Order ";
             return (PetShop.IDAL.IOrder)Assembly.Load(orderPath).CreateInstance(className);
        }
         // 实现 CreateProduct 方法,用于创建Product类实例  
         public  static PetShop.IDAL.IProduct CreateProduct() {
             string className = path +  " .Product ";
             return (PetShop.IDAL.IProduct)Assembly.Load(path).CreateInstance(className);
        }
    }
}

 

以上是数据库访问层的内容

 

5、业务逻辑层必须独立

既然是逻辑,那么该层处理的内容可以说基本上是一些if...else等等。另外,业务逻辑层需要访问数据库时,是通过“数据库访问层工厂”进行的,不再是直接在里面傻傻的写sql语句。

using System.Collections.Generic;
using PetShop.Model;
using PetShop.IDAL;

namespace PetShop.BLL 
{
     ///   <summary>
    
///  实现有关宠物类别的业务逻辑类
    
///   </summary>
     public  class Category 
    {
         // 从数据访问层工厂类得到一个种类的数据访问层的实例
        
// 确保这个静态可以在初始化后缓存数据访问层
         private static readonly ICategory dal = PetShop.DALFactory.DataAccess.CreateCategory(); 通过数据访问层工厂访问数据库
          
         public IList<CategoryInfo> GetCategories() 
        {
             return dal.GetCategories();
        }

         public CategoryInfo GetCategory( string c ategoryId) 
        {

             //  确认输入参数
             if  ( string .IsNullOrEmpty(catego ryId)) ///逻辑层的if语句
                 return  null;

             // 通过类别ID到数据访问层去查询
             return dal.GetCategory(categoryId);
        }
    }
}

 

 

 

四、Global.asax和web.config

 

 

Global.asax:http://hi.baidu.com/mycolorwind/blog/item/45384980228cbfdf9023d960.html

global.asax详解:http://club.topsage.com/thread-485397-1-1.html

global.asax介绍:http://blog.csdn.net/suntanyong88/article/details/6009278

关于global.asax总结经验:http://hi.baidu.com/chinadaima/blog/item/32e0c9ef53b81f32adafd566.html

 

web.config详解:http://blog.csdn.net/zhoufoxcn/article/details/3265141

 

数据连接串:http://www.cnblogs.com/zlytu/archive/2011/11/22/2258364.html

 

Petshop分析:http://www.cnblogs.com/sunfishlu/archive/2008/02/02/1062049.html

走进.net架构:http://www.cnblogs.com/yanyangtian/category/265762.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、Model主要功能: 1、 将每一个“业务实体”抽象成“(瘦数据)”,可以很好地“划分”各个“对象”,操作更加清晰 2、 用于在应用程序各层之间传递数据,被用做传输数据的“容器” 3、 这就是所谓的“建模”过程! 4、 Model各个(Model文件夹中的各个文件)划分或者说编制的原则,更趋向于模拟整个系统中的业务实体 二、实现细节: 1、 PetShop中Model的规划与数据库表的关系: (1) AccountInfo——Account表 (2) AddressInfo——无直接对应关系(对应Account表中一部分字段) (3) CartItemInfo——无直接对应关系 (4) CreditCardInfo——无直接对应关系 (5) ItemInfo——Item表 (6) LineItemInfo——无直接对应关系 (7) OrderInfo——Orders表 (8) ProductInfo——Product表 2、 为每一个Model中的都标记了[Serializable],说明这些可以被传行化,但是不能被继承! 3、 AccountInfo.cs文件:用户在网站注册的信息,及喜好选择情况 4、 使用构造函数可以初始化私有字段;使用属性可以读取私有字段(但使用属性不能设置私有字段的值) 5、 其中包含一个AddressInfo的私有变量,和一个AddressInfo的属性 6、 命名空间为PetShop.Model 7、 AddressInfo.cs文件:用户真实的个人姓名、住址和电话号码等信息 8、 与AccountInfo不同的是,AddressInfo允许使用属性设置私有变量的值 9、 CartItemInfo.cs文件:描述购物车中每一种所选商品的信息的 10、 该“”对象的某些信息(如这里的Subtotal属性)可能并不是此的“自然信息”,而需要经过简单计算而得到!这些简单但必要的信息也要在的设计中体现出来! 11、 CreditCardInfo.cs文件:表示特定一张信用卡的信息 12、 ItemInfo.cs文件:一个Item指的是category"product"item,如猫"波斯猫"成年男波斯猫(或成年女波斯猫)。这个文件表示一个Item的所有信息 13、 productDesc字段的作用? 14、 LineItemInfo.cs文件:注意与CartItemInfo的区别!LineItemInfo是用来描述用户最终确认的订单当中的某一种的产品的信息的 15、 同样包括了Subtotal属性 16、 OrderInfo.cs文件:用于显示用户某一个订单具体信息的,在此一个订单当中,可能包括多个商品种,即包括多个LineItemInfo对象(实际上在OrderInfo中也确实存在LineItemInfo型对象的一个数组!) 17、 ProductInfo.cs文件:包括一个特定Product的信息,如波斯猫 三、启发: 1、 来自Directory项目结束后的启发,以后做设计的时候,要将每个实体抽象为一个,在整个系统中进行操作。 2、 在任意一个当中,可能不只包括此实体的自然信息,也可以包括一些对其他地方数据调用有用的属性信息,如根据数量和单价计算出来的总价属性,或者标志此实体的直属上级实体的属性 四、问题: 1、 忽然发现在MSDN上有文章,关于数据实体的:浏览 2、 抽象这些业务实体模型为瘦数据的原则是什么?什么样的业务实体可以被抽象,或者说进行抽象后更有意义? 3、 ItemInfo中,productDesc字段的作用? 一、IDAL主要功能: 1、 这完全是“工厂模式”的一部分实现而已 2、 这是一组接口,其中包括了每个要公开的数据访问方法。为每个数据库产品单独编写的DAL(数据访问层)都要实现这组接口所定义的方法 3、 也就是规定了在DAL中编写的“对用户账号进行操作的”所必须执行的方法! 4、 IDAL要达到的目的是:实现业务逻辑(BLL)与数据库访问(DAL)的完全分离!!! 5、 IDAL各个(IDAL文件夹中的各个文件)划分或者说编制的原则,更趋向于“将对数据库的不同操作进行归”,考虑的主要方面是数据库操作!!!例如,有对用户账号进行的一系列数据库操作,则将这一系列操作统一放置于IAccount接口(将来实现后的Account)文件当中 二、实现细节: 1、 IAccount.cs文件:为针对不同数据库产品编写的“操作用户账号的”所必须实现的一系列方法定义契约 2、 IInventory.cs文件:定义“操作库存量的”所必须实现的一系列方法;或者说将操作库存量的一系列(所有)方法做一个汇总 3、 IItem.cs文件:定义“操作某一Item的”所必须实现的一系列方法。(Item在Model中定义了,是指具体某一别的Product,如男猫或女猫) 4、 对于其中的GetItemsByProduct()方法,返回的是一个ArrayList的接口型(IList)的对象(见问题部分!) 5、 IOrder.cs文件:定义了一组DAL层中“操作用户订单的”必须执行的方法。其中包括“添加一张新订单”的方法Insert()和根据一个已有的订单号取得此订单详细信息的方法GetOrder(),此方法返回的是一个OrderInfo对象。(Model中的OrderInfo模型定义了用户的某一张Order中相关的信息,如发货地点,总价,信用卡号码等等) 6、 IProduct.cs文件:定义一组在DAL层中编写的“对Product进行操作的” 7、 IProfile.cs文件:定义一组在DAL层编写的“对用户Profile进行操作的” 三、启发: 1、 这样就可以让在BLL层只针对IDAL层定义的接口进行编程(使用IDAL接口定义的这些方法)就可以了!!!无论在底层使用了什么厂家的数据库产品,有区别的只是针对此数据库产品编写的DAL层(相同的方法,如SignIn()方法,对于不同的数据库产品,可能有不同的实现方式!),而不会影响到上层的BLL层已经编写好的内容! 2、 从这里可以看到软件架构师和程序员工作上的区别!架构师要负责的是搭建系统的层次结构,定义接口;而程序员要负责的是针对接口的具体代码实现过程! 3、 这个IDAL接口的使用,主要是为了保证在底层数据库实现,甚至数据库产品发生变化的时候,不需要对上层BLL层的业务逻辑进行大量的修改!BLL层针对IDAL接口编程即可!!! 4、 IDAL文件夹中定义的所有的接口中的所有的方法,包括了整个程序要对数据库进行操作的所有方法 5、 由于PetShop只是一个演示程序,所以若对数据库操作的某一别(如对Account进行操作)中定义的“操作”不够用(如除了接口中定义的几个方法外还需要其他Account操作),还可以在接口中追加其他的方法,用以约束DAL层的实现(如Account)必须执行这些新增加的方法! 四、问题: 1、 定义这组接口后,如何保证为每个单独的数据库产品编写的DAL都执行这组接口所定义的方法?(答案:编写DAL的时候必须刻意保证,否则就失去了定义IDAL层分割BLL和DAL层的意义!!!) 2、 既然在实现GetItemsByProduct()方法的时候,也是要把返回的所有Item对象添加到一个ArrayList当中去,但为什么GetItemsByProduct()方法返回的不是一个ArrayList对象,而是一个IList接口的对象呢?仅仅是基引用的方法吗?这里的基引用有什么用呢?是否是由于为了不限制使用的数组形式?执行IList则可以使用ArrayList,也可以使用其他形式的数组??? 3、 IProduct.cs文件中为何要将查询条件参数定义为一个string型的数组?
关键是系统架构和代码学习两方面,对初学和提高有很大帮助 petshop5.0比较大,代码已经解压出来 4.0和3.0没有解压出来,自行安装解压(需要SqlServer数据做连接或者在安装到数据库连接时直接拷贝出来) petshop5.0 基于.NET Framework 3.5 ------------ 使用LINQ to SQL改进数据访问层 PetShop.Model.DataContext.MSPetShop4DataContext 继承System.Data.Linq.DataContext PetShop.Model.ProductInfo与PetShop.Model.CategoryInfo实体分别映射数据库PetShop.Model.ProductInfo其中的Category属性存在一对一的关系 PetShop.Model.CategoryInfo中的Products属性存在一对多的关系 使用WCF来提供RSS, web/FeedService.svc目录下 PetShop.SyndicationFeeds 并在UI层上做一些改进,如使用ASP.NET AJAX,ListView控件等。 在PetShop 5.0中引入了异步处理机制。 插入订单的策略可以分为同步和异步,两者的插入策略明显不同,但对于调用者而言,插入订单的接口是完全一样的,所以PetShop 5.0中设计了IBLLStrategy模块。 虽然在IBLLStrategy模块中,仅仅是简单的IOrderStategy,但同时也给出了一个范例和信息,那就是在业务逻辑的处理中,如果存在业务操作的多样化,或者是今后可能的变化,均应利用抽象的原理。或者使用接口,或者使用抽象,从而脱离对具体业务的依赖。 不过在PetShop中,由于业务逻辑相对简单,这种思想体现得不够明显。 也正因为此,PetShop将核心的业务逻辑都放到了一个模块BLL中,并没有将具体的实现和抽象严格的按照模块分开。所以表示层和业务逻辑层之间的调用关系,其耦合度相对较高: PetShop4.0源代码 .NET Pet Shop4 应用程序的设计说明了构建企业 n 层 .NET 2.0 应用程序的最佳做法,这种应用程序可能需要支持各种数据库平台和部署方案。 .NET Pet Shop 4 项目的目标是: 工作效率:减少了 .NET Pet Shop 3 的代码数量 - 我们减少了近 25% 的代码。 利用 ASP.NET 2.0 的新功能 - 我们利用母版页、成员身份和配置文件,并设计出一个新的、吸引人的用户界面。 企业体系结构:构建一个灵活的最佳做法应用程序 - 我们实现了设计模式,以及表示层、业务层和数据层的分离。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值