一个分层架构设计的例子(2)

接着上一篇关于分层架构的讨论, 一个分层架构设计的例子(1)
上篇介绍了实体类(Entity)、数据库访问类(DAL)、数据访问接口(IDAL)的相关设计,本篇主要讨论下面几个部分内容:业务逻辑层、缓存机制、界面层等方面。
业务逻辑层,主要是业务逻辑基类的设计,由于数据库访问类(DAL)的基类封装了大量的操作实现,因此,业务逻辑层的主要工作是进一步封装对底层访问接口的实现,如下所示。
None.gif      public   class  BaseBLL < T >   where  T : BaseEntity,  new ()
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
ContractedSubBlock.gifExpandedSubBlockStart.gif        
构造函数#region 构造函数
InBlock.gif
InBlock.gif        
private string dalName = "";
InBlock.gif        
protected IBaseDAL<T> baseDal = null;
InBlock.gif
InBlock.gif        
public BaseBLL()
InBlock.gif            : 
this("")
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public BaseBLL(string dalName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.dalName = dalName;
InBlock.gif            
if (string.IsNullOrEmpty(dalName))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.dalName = GetType().Name;
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            baseDal 
= Reflect<IBaseDAL<T>>.Create(this.dalName, "HuaweiSoftware.IPSPBD.DAL");
ExpandedSubBlockEnd.gif        }
 
InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
对象添加、修改、删除等接口#region 对象添加、修改、删除等接口
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 插入指定对象到数据库中
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="obj">指定的对象</param>
ExpandedSubBlockEnd.gif        
/// <returns>执行成功返回新增记录的自增长ID。</returns>

InBlock.gif        public virtual bool Insert(T obj)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return baseDal.Insert(obj);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 更新对象属性到数据库中
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="obj">指定的对象</param>
ExpandedSubBlockEnd.gif        
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c></returns>

InBlock.gif        public virtual bool Update(T obj, string primaryKeyValue)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return baseDal.Update(obj, primaryKeyValue);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 查询数据库,检查是否存在指定ID的对象(用于字符型主键)
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="key">对象的ID值</param>
ExpandedSubBlockEnd.gif        
/// <returns>存在则返回指定的对象,否则返回Null</returns>

InBlock.gif        public virtual T FindByID(string key)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return baseDal.FindByID(key);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 查询数据库,检查是否存在指定键值的对象
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="fieldName">指定的属性名</param>
InBlock.gif        
/// <param name="key">指定的值</param>
ExpandedSubBlockEnd.gif        
/// <returns>存在则返回<c>true</c>,否则为<c>false</c></returns>

InBlock.gif        public virtual bool IsExistKey(string fieldName, object key)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return baseDal.IsExistKey(fieldName, key);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 根据指定对象的ID,从数据库中删除指定对象(用于整型主键)
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="key">指定对象的ID</param>
ExpandedSubBlockEnd.gif        
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c></returns>

InBlock.gif        public virtual bool Delete(string key)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return baseDal.DeleteByKey(key);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 根据指定条件,从数据库中删除指定对象
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="condition">删除记录的条件语句</param>
ExpandedSubBlockEnd.gif        
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c></returns>

InBlock.gif        public virtual bool DeleteByCondition(string condition)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return baseDal.DeleteByCondition(condition);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
返回集合的接口#region 返回集合的接口
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 根据ID字符串(逗号分隔)获取对象列表
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="idString">ID字符串(逗号分隔)</param>
ExpandedSubBlockEnd.gif        
/// <returns>符合条件的对象列表</returns>

InBlock.gif        public virtual List<T> FindByIDs(string idString)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return baseDal.FindByIDs(idString);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 根据条件查询数据库,并返回对象集合
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="condition">查询的条件</param>
ExpandedSubBlockEnd.gif        
/// <returns>指定对象的集合</returns>

InBlock.gif        public virtual List<T> Find(string condition)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return Find(condition);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="condition">查询的条件</param>
InBlock.gif        
/// <param name="info">分页实体</param>
ExpandedSubBlockEnd.gif        
/// <returns>指定对象的集合</returns>

InBlock.gif        public virtual List<T> Find(string condition, PagerInfo info)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return baseDal.Find(condition, info);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 返回数据库所有的对象集合
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <returns>指定对象的集合</returns>

InBlock.gif        public virtual List<T> GetAll()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return baseDal.GetAll();
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 返回数据库所有的对象集合(用于分页数据显示)
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="info">分页实体信息</param>
ExpandedSubBlockEnd.gif        
/// <returns>指定对象的集合</returns>

InBlock.gif        public virtual List<T> GetAll(PagerInfo info)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return baseDal.GetAll(info);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public virtual DataSet GetAllToDataSet(PagerInfo info)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return baseDal.GetAllToDataSet(info);
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

ExpandedBlockEnd.gif    }

业务层基类封装了大量的调用,那么对于业务层的具体操作类,它的工作就很简单了,基本上只需要继承一下基类就可以了,这就是有一个优秀父亲的好处,呵呵
None.gif      public   class  Equipment : BaseBLL < EquipmentInfo >
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
public Equipment() : base()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }

基本上,业务层的设计到此应该收尾了,可是我们注意到,很多开发都使用了缓存的机制来进一步提高程序的性能,下面对这方面进行讨论。缓存的机制,一般是把创建过的对象资源放到一个集合中,需要的时候,调出来,如下业务层的工厂类所示。
None.gif      public   class  BLLFactory < T >   where  T :  class
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
private static Hashtable objCache = new Hashtable();
InBlock.gif        
public static T Instance
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
string CacheKey = typeof(T).FullName;
InBlock.gif                T bll 
= (T)objCache[CacheKey];  //从缓存读取  
InBlock.gif
                if (bll == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    bll 
= Reflect<T>.Create(typeof(T).Name, "HuaweiSoftware.IPSPBD.BLL"); //反射创建,并缓存
ExpandedSubBlockEnd.gif
                }

InBlock.gif                
return bll;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }
  

这是一个业务逻辑类工厂创建类,我们在界面层只需要如下调用即可构造一个(利用了缓存)具体的业务类出来
None.gif CustomerInfo info  =  BLLFactory < Customer > .Instance.FindByID(ID);

在上面的BaseBLL和BLLFactory类中,有一个Reflect的操作类,这是反射缓存的具体实现所在,我们探讨一下它的实现。
None.gif      public   class  Reflect < T >   where  T :  class  
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
private static Hashtable m_objCache = null;
InBlock.gif        
public static Hashtable ObjCache
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (m_objCache == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    m_objCache 
= new Hashtable();
ExpandedSubBlockEnd.gif                }

InBlock.gif                
return m_objCache;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public static T Create(string sName, string sFilePath)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return Create(sName, sFilePath, true);
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public static T Create(string sName, string sFilePath, bool bCache)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
string CacheKey = sFilePath + "." + sName;
InBlock.gif            T objType 
= null;
InBlock.gif            
if (bCache)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                objType 
= (T)ObjCache[CacheKey];    //从缓存读取 
InBlock.gif
                if (!ObjCache.ContainsKey(CacheKey))
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    Assembly assObj 
= CreateAssembly(sFilePath);
InBlock.gif                    
object obj = assObj.CreateInstance(CacheKey);
InBlock.gif                    objType 
= (T)obj;
InBlock.gif
InBlock.gif                    ObjCache.Add(CacheKey, objType);
// 写入缓存 将DAL内某个对象装入缓存
ExpandedSubBlockEnd.gif
                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                objType 
= (T)CreateAssembly(sFilePath).CreateInstance(CacheKey); //反射创建 
ExpandedSubBlockEnd.gif
            }

InBlock.gif
InBlock.gif            
return objType;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public static Assembly CreateAssembly(string sFilePath)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Assembly assObj 
= (Assembly)ObjCache[sFilePath];
InBlock.gif            
if (assObj == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                assObj 
= Assembly.Load(sFilePath);
InBlock.gif                ObjCache.Add(sFilePath, assObj);
//将整个DLL装入缓存
ExpandedSubBlockEnd.gif
            }

InBlock.gif            
return assObj;
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }


另外,如果你在业务层需要实现更加复杂的功能,而数据库访问基类BaseDAL提供的函数不能满足你的需要,可以扩展数据访问层的接口和实现,如下所示。
None.gif      public   interface  ICustomer : IBaseDAL < CustomerInfo >
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        List
<string> GetAllCustomerNumber();
InBlock.gif
InBlock.gif        CustomerInfo GetByCustomerNumber(
string number);
ExpandedBlockEnd.gif    }

None.gif
None.gif
None.gif    
public   class  Customer : BaseDAL < CustomerInfo > , ICustomer
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
ContractedSubBlock.gifExpandedSubBlockStart.gif        
对象实例及构造函数#region 对象实例及构造函数
InBlock.gif
InBlock.gif        
public static Customer Instance
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return new Customer();
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
public Customer() : base("All_Customer","ID")
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

InBlock.gif
InBlock.gif        dot.gifdot.gifdot.gifdot.gifdot.gifdot.gif
InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
ICustomer 成员#region ICustomer 成员
InBlock.gif
InBlock.gif        
public List<string> GetAllCustomerNumber()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
string sql = string.Format("Select Number From dbo.{0}", tableName);
InBlock.gif
InBlock.gif            List
<string> list = new List<string>();
InBlock.gif
InBlock.gif            Database db 
= DatabaseFactory.CreateDatabase();
InBlock.gif            DbCommand command 
= db.GetSqlStringCommand(sql);
InBlock.gif
InBlock.gif            
string number = string.Empty;
InBlock.gif            
using (IDataReader dr = db.ExecuteReader(command))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
while (dr.Read())
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    number 
= dr["Number"].ToString();
InBlock.gif                    
if (!string.IsNullOrEmpty(number))
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        list.Add(number);
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
return list;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
InBlock.gif        
public CustomerInfo GetByCustomerNumber(string number)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
string condition = string.Format("Number = '{0}'", number);
InBlock.gif            List
<CustomerInfo> list = base.Find(condition);
InBlock.gif            
if (list.Count > 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return list[0];
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return null;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

ExpandedBlockEnd.gif    }


那么在业务层的类修改如下
None.gif      public   class  Customer : BaseBLL < CustomerInfo >
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
public Customer() : base()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public List<string> GetAllCustomerNumber()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            ICustomer customerDAL 
= baseDal as ICustomer;
InBlock.gif            
return customerDAL.GetAllCustomerNumber();
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public CustomerInfo GetByCustomerNumber(string number)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            ICustomer customerDAL 
= baseDal as ICustomer;
InBlock.gif            
return customerDAL.GetByCustomerNumber(number);
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }

最后,界面方面的设计是见仁见智,但根本一条是利用一些控件,可以统一风格,减少劳动,给出几个界面的设计截图供大家参考
WinForm方面的(颜色标明的是使用了特定的界面控件,其中红色部分为和整个架构整合起来的分页控件,集成了一些基本的右键菜单操作,包括打印功能、数据导出功能等):
WinForm_UI1.jpg

Winform分页控件设计视图
GridViewPager.jpg

可以选择列进行打印
GridViewPager_PrintOption.jpg

在实际运用过程中的界面效果
GridViewPager_Product.jpg


WebForm方面的(可以使用之前文章介绍的查询控件、分页控件、内容编辑控件):

下图是查询控件和分页控件的一起运用:

WebForm_UI1.jpg

修改内容时候的编辑控件
WebForm_UI2.jpg


查看内容时候的编辑控件
WebForm_UI3.jpg


以上所引用的代码是通过代码生成工具Database2Sharp自动生成( http://www.iqidi.com/Database2Sharp.htm),选择EnterpriseLibrary架构即可。
Database2Sharp_Enterprise.jpg
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值