学习三层结构心得(一)

    以前分析过Microsoft中另一个轻巧的三层结构的PetShop例子,发现PetShop还是比较好懂。这几天有空一直在看Duwamish的代码,参照了几篇分析Duwamish的文章。所以,这些天都会围绕这两个例子来学习,并写一些心得。

    首先,Duwamish分层为五层结构。Web层,业务外观层,业务规则层,业务实体层,数据访问层。

    业务实体层,里面实现的是各个实体的对象,用DataSet来表示,比如:Book对象,Custermer对象,Order对象等。建立该层以方便在其它各个层来传递数据(也就是说,各层传递数据是以DataSet来传递的)。另个,这个对象实体也与数据库中的库结构是对应的。

    抽取其中的一段代码来分析。以BookData.cs为例,在其中,就建立了Book这个类:

    
public   class  BookData : DataSet
ExpandedBlockStart.gifContractedBlock.gif
{
   
public const String BOOKS_TABLE            = "Books";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for PKId field in the Books table. </value>
        public const String PKID_FIELD             = "PKId";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for TypeId field in the Books table. </value>
        public const String TYPE_ID_FIELD          = "TypeId";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for PublisherId field in the Books table. </value>
        public const String PUBLISHER_ID_FIELD     = "PublisherId";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for PublicationYear field in the Books table. </value>
        public const String PUBLICATION_YEAR_FIELD = "PublicationYear";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for ISBN field in the Books table. </value>
        public const String ISBN_FIELD             = "ISBN";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for ImageFileSpec field in the Books table. </value>
        public const String IMAGE_FILE_SPEC_FIELD  = "ImageFileSpec";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for Title field in the Books table. </value>
        public const String TITLE_FIELD            = "Title";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for Title field in the Books table. </value>
        public const String DESCRIPTION_FIELD      = "Description";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for UnitPrice field in the Books table. </value>
        public const String UNIT_PRICE_FIELD       = "UnitPrice";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for UnitCost field in the Books table. </value>
        public const String UNIT_COST_FIELD        = "UnitCost";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for ItemType field in the Books table. </value>
        public const String ITEM_TYPE_FIELD        = "ItemType";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for PublisherName field in the Books table. </value>
        public const String PUBLISHER_NAME_FIELD   = "PublisherName";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <value>The constant used for Authors field in the Books table. </value>
        public const String AUTHORS_FIELD          = "Authors";


ExpandedSubBlockStart.gifContractedSubBlock.gif
/**////表示按什么来进行查找。有按title,isbn,author等查找方法
[SerializableAttribute]
        
public enum SearchTypeEnum
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
            
///     Title search.
            
/// </summary>

            Title = 0,
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
            
///     ISBN search.
            
/// </summary>

            ISBN = 1,
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
            
///     Author search.
            
/// </summary>

            Author = 2,
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
            
///     Subject search.
            
/// </summary>

            Subject = 3,
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
            
///     Id search.
            
/// </summary>

            ID = 4,
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
            
///     Id list search.
            
/// </summary>

            IdList = 5
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif
/**////这个函数没分析出它什么意思
private BookData(SerializationInfo info, StreamingContext context) : base(info, context) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{        
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif
/**////构造函数,在类对象中加入一张表
public BookData()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//
            
// Create the tables in the dataset
            
//
            BuildDataTables();
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif
/**////建立表结构,并加入DataSet
private void BuildDataTables()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//
            
// Create the Books table
            
//
            DataTable table   = new DataTable(BOOKS_TABLE);
            DataColumnCollection columns 
= table.Columns;
            
            columns.Add(PKID_FIELD, 
typeof(System.Int32));
            columns.Add(TYPE_ID_FIELD, 
typeof(System.Int32));
            columns.Add(PUBLISHER_ID_FIELD, 
typeof(System.Int32));
            columns.Add(PUBLICATION_YEAR_FIELD, 
typeof(System.Int16));
            columns.Add(ISBN_FIELD, 
typeof(System.String));
            columns.Add(IMAGE_FILE_SPEC_FIELD, 
typeof(System.String));
            columns.Add(TITLE_FIELD, 
typeof(System.String));
            columns.Add(DESCRIPTION_FIELD, 
typeof(System.String));
            columns.Add(UNIT_PRICE_FIELD, 
typeof(System.Decimal));
            columns.Add(UNIT_COST_FIELD, 
typeof(System.Decimal));
            columns.Add(ITEM_TYPE_FIELD, 
typeof(System.String));
            columns.Add(PUBLISHER_NAME_FIELD, 
typeof(System.String));
            
//
            
// [Authors] is an optional column that will get added dynamically to the table schema
            
// when the stored proc. GetBookById is used to fill the 'Books' table
            
//
            this.Tables.Add(table);
        }

}
    

    一旦对象实体建立好,其余层皆可创建该类的一个对象用它来作数据传递。



    数据访问层:功能很简单,与数据库进行交互。无非就是几种操作:Query,Update,Insert,Delete,当然,要根据数据库的设计,由程序应用提升出来的数据操作抽象来写出怎么与数据库进行哪些操作。还是看代码,看看DataAccess中的Book类怎么进行与数据库操作。

public   class  Books : IDisposable
    {

         private  SqlDataAdapter dsCommand;

        
public  Books()
        {

            dsCommand  =   new  SqlDataAdapter();

            dsCommand.SelectCommand  =   new  SqlCommand();
            dsCommand.SelectCommand.Connection  
=   new  SqlConnection(DuwamishConfiguration.ConnectionString);

            dsCommand.TableMappings.Add( " Table " , BookData.BOOKS_TABLE);
        }
        
        
///   <summary>
        
///      Dispose of this object's resources.
        
///   </summary>
         public   void  Dispose()
        {
            Dispose(
true );
            GC.SuppressFinalize(
true );  //  as a service to those who might inherit from us
        }

        
///   <summary>
        
///         Free the instance variables of this object.
        
///   </summary>
         protected   virtual   void  Dispose( bool  disposing)
        {
            
if  ( !  disposing)
                
return //  we're being collected, so let the GC take care of this object

            
if  (dsCommand  !=   null  )
            {
                
if  (dsCommand.SelectCommand  !=   null )
                {
                    
if ( dsCommand.SelectCommand.Connection  !=   null )
                        dsCommand.SelectCommand.Connection.Dispose();
                    dsCommand.SelectCommand.Dispose();
                }
                dsCommand.Dispose();
                dsCommand 
=   null ;
            }
        }
}


首先,book类继承自IDisposable,它可以派生Dispose函数来自主释放资源(在这里是指释放数据库的链接)。另外,它有一个SqlDataAdapter的成员,就是用来让SqlCommand与DataSet进行互通的,DataSet就是我们上面所提到的业务实体的对象。

不难看出,Book数据层应该对数据库的操作就是按照种类来查找书,按bookid来查找某本书,按作者来查找某些书,按书号来查找书,等等,于是我们在数据库中写入相应的存储过程(GetBooksByCategoryId,GetBookById,GetBooksByAuthor,GetBooksByISBN),然后,在源代码中调用如下:

public  BookData GetBooksByCategoryId( int  categoryId)
ExpandedBlockStart.gifContractedBlock.gif        
{
            
return FillBookData("GetBooksByCategoryId""@CategoryId", categoryId.ToString());
        }


public  BookData GetBookById( int  bookId)
ExpandedBlockStart.gifContractedBlock.gif        
{
            
return FillBookData("GetBookById""@BookId", bookId.ToString());
        }



public  BookData GetBooksByAuthor(String searchText)
ExpandedBlockStart.gifContractedBlock.gif        
{
            
return FillBookData("GetBooksByAuthor""@Author", searchText );
        }


public  BookData GetBooksByISBN(String searchText)
ExpandedBlockStart.gifContractedBlock.gif        
{
            
return FillBookData("GetBooksByISBN""@ISBN", searchText);
        }



private  BookData FillBookData(String commandText, String paramName, String paramValue)
ExpandedBlockStart.gifContractedBlock.gif        
{
            
if (dsCommand == null )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
throw new System.ObjectDisposedException( GetType().FullName );
            }
            
            BookData   data    
= new BookData();
            SqlCommand command 
= dsCommand.SelectCommand;

            command.CommandText 
= commandText;
            command.CommandType 
= CommandType.StoredProcedure; // use stored proc for perf
            SqlParameter param = new SqlParameter(paramName, SqlDbType.NVarChar, 255);
            param.Value 
= paramValue;
            command.Parameters.Add(param);            

            dsCommand.Fill(data);
            
return data;
        }


以上就是数据层做的事。

至于业务规则层与业务外观层,暂时没看到,续...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值