打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
一个分层架构设计的例子(2)
接着上一篇关于分层架构的讨论,一个分层架构设计的例子(1)
上篇介绍了实体类(Entity)、数据库访问类(DAL)、数据访问接口(IDAL)的相关设计,本篇主要讨论下面几个部分内容:业务逻辑层、缓存机制、界面层等方面。
业务逻辑层,主要是业务逻辑基类的设计,由于数据库访问类(DAL)的基类封装了大量的操作实现,因此,业务逻辑层的主要工作是进一步封装对底层访问接口的实现,如下所示。
    public class BaseBLL<T> where T : BaseEntity, new
()
    
{
        
#region 构造函数

        
private string dalName = "";
        
protected IBaseDAL<T> baseDal = null
;

        
public
 BaseBLL()
            : 
this(""
)
        
{
        }


        
public BaseBLL(string dalName)
        
{
            
this.dalName =
 dalName;
            
if (string
.IsNullOrEmpty(dalName))
            
{
                
this.dalName =
 GetType().Name;
            }


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

        
#endregion


        
#region 对象添加、修改、删除等接口

        
/// <summary>
        
/// 插入指定对象到数据库中
        
/// </summary>

        
/// <param name="obj">指定的对象</param>
        
/// <returns>执行成功返回新增记录的自增长ID。</returns>

        public virtual bool
 Insert(T obj)
        
{
            
return
 baseDal.Insert(obj);
        }


        
/// <summary>
        
/// 更新对象属性到数据库中
        
/// </summary>

        
/// <param name="obj">指定的对象</param>
        
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c></returns>

        public virtual bool Update(T obj, string
 primaryKeyValue)
        
{
            
return
 baseDal.Update(obj, primaryKeyValue);
        }


        
/// <summary>
        
/// 查询数据库,检查是否存在指定ID的对象(用于字符型主键)
        
/// </summary>

        
/// <param name="key">对象的ID值</param>
        
/// <returns>存在则返回指定的对象,否则返回Null</returns>

        public virtual T FindByID(string
 key)
        
{
            
return
 baseDal.FindByID(key);
        }


        
/// <summary>
        
/// 查询数据库,检查是否存在指定键值的对象
        
/// </summary>

        
/// <param name="fieldName">指定的属性名</param>
        
/// <param name="key">指定的值</param>
        
/// <returns>存在则返回<c>true</c>,否则为<c>false</c></returns>

        public virtual bool IsExistKey(string fieldName, object
 key)
        
{
            
return
 baseDal.IsExistKey(fieldName, key);
        }


        
/// <summary>
        
/// 根据指定对象的ID,从数据库中删除指定对象(用于整型主键)
        
/// </summary>

        
/// <param name="key">指定对象的ID</param>
        
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c></returns>

        public virtual bool Delete(string
 key)
        
{
            
return
 baseDal.DeleteByKey(key);
        }


        
/// <summary>
        
/// 根据指定条件,从数据库中删除指定对象
        
/// </summary>

        
/// <param name="condition">删除记录的条件语句</param>
        
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c></returns>

        public virtual bool DeleteByCondition(string
 condition)
        
{
            
return
 baseDal.DeleteByCondition(condition);
        }


        
#endregion


        
#region 返回集合的接口

        
/// <summary>
        
/// 根据ID字符串(逗号分隔)获取对象列表
        
/// </summary>

        
/// <param name="idString">ID字符串(逗号分隔)</param>
        
/// <returns>符合条件的对象列表</returns>

        public virtual List<T> FindByIDs(string
 idString)
        
{
            
return
 baseDal.FindByIDs(idString);
        }


        
/// <summary>
        
/// 根据条件查询数据库,并返回对象集合
        
/// </summary>

        
/// <param name="condition">查询的条件</param>
        
/// <returns>指定对象的集合</returns>

        public virtual List<T> Find(string
 condition)
        
{
            
return
 Find(condition);
        }


        
/// <summary>
        
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
        
/// </summary>

        
/// <param name="condition">查询的条件</param>
        
/// <param name="info">分页实体</param>
        
/// <returns>指定对象的集合</returns>

        public virtual List<T> Find(string
 condition, PagerInfo info)
        
{
            
return
 baseDal.Find(condition, info);
        }


        
/// <summary>
        
/// 返回数据库所有的对象集合
        
/// </summary>

        
/// <returns>指定对象的集合</returns>

        public virtual List<T>
 GetAll()
        
{
            
return
 baseDal.GetAll();
        }


        
/// <summary>
        
/// 返回数据库所有的对象集合(用于分页数据显示)
        
/// </summary>

        
/// <param name="info">分页实体信息</param>
        
/// <returns>指定对象的集合</returns>

        public virtual List<T>
 GetAll(PagerInfo info)
        
{
            
return
 baseDal.GetAll(info);
        }


        
public virtual DataSet GetAllToDataSet(PagerInfo info)
        
{
            
return
 baseDal.GetAllToDataSet(info);
        }


        
#endregion

    }

业务层基类封装了大量的调用,那么对于业务层的具体操作类,它的工作就很简单了,基本上只需要继承一下基类就可以了,这就是有一个优秀父亲的好处,呵呵
    public class Equipment : BaseBLL<EquipmentInfo>

    
{
        
public Equipment() : base
()
        
{
        }

    }

基本上,业务层的设计到此应该收尾了,可是我们注意到,很多开发都使用了缓存的机制来进一步提高程序的性能,下面对这方面进行讨论。缓存的机制,一般是把创建过的对象资源放到一个集合中,需要的时候,调出来,如下业务层的工厂类所示。
    public class BLLFactory<T> where T : class

    
{
        
private static Hashtable objCache = new
 Hashtable();
        
public static
 T Instance
        
{
            
get

            
{
                
string CacheKey = typeof
(T).FullName;
                T bll 
= (T)objCache[CacheKey];  //从缓存读取  

                if (bll == null)
                
{
                    bll 
= Reflect<T>.Create(typeof(T).Name, "HuaweiSoftware.IPSPBD.BLL"); //反射创建,并缓存

                }

                
return bll;
            }

        }

    }
  

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

在上面的BaseBLL和BLLFactory类中,有一个Reflect的操作类,这是反射缓存的具体实现所在,我们探讨一下它的实现。
    public class Reflect<T> where T : class
 
    
{
        
private static Hashtable m_objCache = null
;
        
public static
 Hashtable ObjCache
        
{
            
get

            
{
                
if (m_objCache == null
)
                
{
                    m_objCache 
= new
 Hashtable();
                }

                
return m_objCache;
            }

        }


        
public static T Create(string sName, string sFilePath)
        
{
            
return Create(sName, sFilePath, true
);
        }

        
public static T Create(string sName, string sFilePath, bool bCache)
        
{
            
string CacheKey = sFilePath + "." +
 sName;
            T objType 
= null
;
            
if
 (bCache)
            
{
                objType 
= (T)ObjCache[CacheKey];    //从缓存读取 

                if (!ObjCache.ContainsKey(CacheKey))
                
{
                    Assembly assObj 
=
 CreateAssembly(sFilePath);
                    
object obj =
 assObj.CreateInstance(CacheKey);
                    objType 
=
 (T)obj;

                    ObjCache.Add(CacheKey, objType);
// 写入缓存 将DAL内某个对象装入缓存

                }

            }

            
else
            
{
                objType 
= (T)CreateAssembly(sFilePath).CreateInstance(CacheKey); //反射创建 

            }


            
return objType;
        }


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

            }

            
return assObj;
        }

    }


另外,如果你在业务层需要实现更加复杂的功能,而数据库访问基类BaseDAL提供的函数不能满足你的需要,可以扩展数据访问层的接口和实现,如下所示。
    public interface ICustomer : IBaseDAL<CustomerInfo>

    
{
        List
<string>
 GetAllCustomerNumber();

        CustomerInfo GetByCustomerNumber(
string
 number);
    }



    
public class Customer : BaseDAL<CustomerInfo>, ICustomer
    
{
        
#region 对象实例及构造函数

        
public static Customer Instance
        
{
            
get

            
{
                
return new
 Customer();
            }

        }

        
public Customer() : base("All_Customer","ID")
        
{
        }


        
#endregion


        


        
#region ICustomer 成员

        
public List<string> GetAllCustomerNumber()
        
{
            
string sql = string.Format("Select Number From dbo.{0}"
, tableName);

            List
<string> list = new List<string>
();

            Database db 
=
 DatabaseFactory.CreateDatabase();
            DbCommand command 
=
 db.GetSqlStringCommand(sql);

            
string number = string
.Empty;
            
using (IDataReader dr =
 db.ExecuteReader(command))
            
{
                
while
 (dr.Read())
                
{
                    number 
= dr["Number"
].ToString();
                    
if (!string
.IsNullOrEmpty(number))
                    
{
                        list.Add(number);
                    }

                }

            }

            
return list;
        }

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

            
else
            
{
                
return null
;
            }

        }


        
#endregion

    }


那么在业务层的类修改如下
    public class Customer : BaseBLL<CustomerInfo>

    
{
        
public Customer() : base
()
        
{
        }


        
public List<string> GetAllCustomerNumber()
        
{
            ICustomer customerDAL 
= baseDal as
 ICustomer;
            
return
 customerDAL.GetAllCustomerNumber();
        }


        
public CustomerInfo GetByCustomerNumber(string number)
        
{
            ICustomer customerDAL 
= baseDal as
 ICustomer;
            
return
 customerDAL.GetByCustomerNumber(number);
        }

    }

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


Winform分页控件设计视图


可以选择列进行打印


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



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

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



修改内容时候的编辑控件



查看内容时候的编辑控件



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

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C# 数据缓存操作Cache
ASP.NET缓存全解析4:应用程序数据缓存
DataCache.GetCache是什么?-搜索墙
dsoframer控件学习小结(打开WORD,EXCEL等文件)
Java Dreams
C# 中利用反射机制拷贝类的字段和属性(拷贝一个类对象的所有东西付给另一个类对象,而不是付给引用地址)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服