Bugnet学习总结(4)数据访问层

Post on by michaelyin

Bugnet由于功能比较简单,所以在系统的架构上也很简单,没什么过于复杂的地方。

DAL文件夹中的DataFactory文件通过读取Web.config中的Appsetting中的值反射生成生成数据库连接和操作对象。DataHelper,里面则是一些常用的Ado操作,进行了简单的封装,GenericDataAccessLayer是调用DataHelper里的函数完成数据CRUD操作的类。,需要提一下的是具体的数据库操作的代码是写在数据库的存储过程中的,而这一点也正是我不是很理解的地方,先前提到过的DataFactory和DataHelper特别是 DataFactory的存在是提供跨库操作的,而它将数据库操作又用存储过程写在数据库里面这不是有点矛盾么。。。想象一下如果要迁移的话那存储过程不是都还要改。。。。。:(

在看GenericDataAccessLayer的时候,刚开始我对其中一个语法结构不是很清楚,是到网上查了一些资料才弄懂的。该类在里面定义了一个静态对象,如果是别的对象我还可以理解,可是这个对象正式通过GenericDataAccessLayer实例化的。。

/// <summary>
/// BugNET Data Access Layer
/// </summary>
public class GenericDataAccessLayer
{
    private static GenericDataAccessLayer instance;
}

这个就是静态对象声明的地方

/// <summary>
/// Instances this instance.
/// </summary>
/// <returns></returns>
public static GenericDataAccessLayer Instance()
{
    if (instance == null)
    {
        instance = new GenericDataAccessLayer();
    }
    return instance;
}

在调用的时候如果为null会对对象进行初始化。

刚开始我的想法是GenericDataAccessLayer里包含instance这个对象,那初始化的时候会构成一个不断递归的过程,为什么会编译通过呢?后来在网上找了一下,找到了答案。原来类里面定义的静态对象是在类级别而不是在对象级别的。如果那种写法不是写的静态对象,即语句写成了public GenericDataAccessLayer Instance() ,那么肯定是有问题的,而如果你写在类这个级别的时候这个问题是不存在的。

这样来说吧 ...


Bugnet学习总结(3)项目文件结构

Post on by michaelyin

用VS打开Bugnet项目文件,可以看到四个Project,BugNET_WAP是Web项目,HttpModule.Authentication是自定义的认证模块,好像是可以在其中选择WindowsSAM和ActiveDirectory两种认证方式,这个模块我没怎么看,感兴趣的朋友请自己研究下,HttpModule.MailBoxReader是邮件读取的模块,UnitTests是单元测试Project.

另外的三个文件结构相对比较简单,就不在这里多做说明了,现在在这里主要对BugNET_WAP进行较详细的说明。

Bugnet使用的数据库是Sql server2005,如果你下载的是source代码,你是不需要Install过程的,建议使用Sql server将它附加到你本机数据库中(数据库在APP_Data文件夹中),然后将Web.config中的链接字符串修改成连接你本机数据库就OK。关于Bugnet安装版的安装过程,园子里面已经有人发了,大家自己去找找。

Administration文件夹里面主要是项目管理相关的页面和用户控件,关于Project创建和管理的页面都在这里面。

Bugs则主要是提交Issue和管理Issue的页面和用户控件。

Config文件夹中的Log4Net.config是log4net的配置文件。

Errors文件夹放的是显示错误的页面。

Install放的是Bugnet安装和升级需要的文件,如果下载的是发布版本的Bugnet,第一次需要运行Install.aspx来进行安装。

Report放的是报表文件和浏览报表的页面。

Shared放的是所用到的母版页。

UserControls放的是用户控件,需要提到的xslt文件,FCKeditor。

Old_App_Code中放的是需要用到的App_Code,UIL中放的是BugNET.UserInterfaceLayer下的类,Pop3Reader下放的是读取邮件时需要用到的类,DAL和BLL是干什么的就不用我多说了吧。。


Bugnet学习总结(2)数据库

Post on by michaelyin

由于Bugnet使用了Membership,所以数据库中会有aspnet_Applications这样以aspnet开头的表名,而这其中和user相关的权限的表诸如aspnet_UsersInRoles,aspnet_Roles,这些表在实际项目运行中是没有用到的,关于membership中的表的联系以及表的具体含义,请参考这篇文章。请猛击这里

接下来的就是具体的业务表了,在业务表中,比较重要的就是Project,Bug这两张表。

aspnet_Users和UserRoles,Roles,RolePermission,Permission,UserProjects组成了基于Project的权限管理模块所需要的表,表名所对应的意思看起来是一目了然的,在这里也就不多说了。。

在Bugnet里你创建一个Project的话,项目创建者可以在里面事先添加一些你自定义的属性,你可以决定项目成员在提交内容的时候是否必须填写这个自定义属性,这个自定义属性值你可以设定成Text,Dropdownlist,等等,关于这个功能,具体是在ProjectCustomFields,ProjectCustomFieldSelection,ProjectCustomFieldType,ProjectCustomFieldValues这几个表中实现的。

剩下的表基本上都是以Bug为中心,BugAttachment保存上传的附件,BugComment保存评论,BugHistory保存Issue的历史,BugNotification保存Issue相关的需要通知的User,Component保存Project的分类,RelatedBug保存相关Issue关系。另外的几个表都是比如Status,Type都是起着字典表的作用。标识着Issue的状态和类别。

HostSettings保存着Bugnet整体相关的设置。Log则是Log4net进行日志记录的地方。

表基本上介绍完了,Bugnet在数据操作上基本是使用Ado调用存储过程来完成数据操作的,在这一点上我也是有点不理解,如果说使用存储过程是为了性能,那它代码可以优化的地方不是没有,比如它使用的是自带的分页,而没有自己写分页,这样在数据量达到一定程度时性能肯定会首影响,而且更让我感到有点疑惑的是,代码里面使用了Datafaactory来生成需要的对象,那你为什么具体的数据操作代码要放到数据库里面去?不是要分离么?

视图的话只有BugsView一个,就是将Bug表有联系的表连接起来方便查询。。

数据库大致感觉要说的就这些。。


Bugnet学习总结(1) 前言&索引

Post on by michaelyin

Bugnet是一个简单的Bug管理系统,这个系统对于.Net语言有一定了解而想继续深入学习的朋友来说还是不错的,系统不大,实现的功能叶相对比简单,不会像某些NB源代码会让你在学习的过程中纠结不已。其中的一些控件使用的方法在某些情况下对于我们来说还是值得借鉴的,比如其中的Ajax的实现是使用了ajaxcontroltoolkit,方法比较简单,而效果还不错。

Bugnet系统中用到的若干的我觉得有必要提及的技术我先在这里先提一下,接下来的几篇Blog会按模块进行展开,有可能会有一些遗漏的地方,欢迎大家留言补充。

  1. Membership及其相关认证控件
  2. DataFactory
  3. Log4net记录日志
  4. 用户控件的使用
  5. Rss输出
  6. nunit单元测试
  7. 邮件的读取和发送

除了使用的技术外,Bugnet在层次架构方面的一些东西也是值得借鉴的,我以后会慢慢陈述,当然了,有些地方的处理我和项目人员所想也有所偏差,也希望大家多多讨论。。。

Bugnet学习总结(2)数据库

Bugnet学习总结(3)项目文件结构

Bugnet学习总结(4)数据访问层

Bugnet学习总结(5)逻辑层

Bugnet学习总结(6)用户控件

Bugnet学习总结(7)杂


有列表List的操作所学习到的

Post on by michaelyin

前几日coding的时候,需要实现在泛型列表中找到其中的一个对象并将其移除的功能,刚开始想的很简单,先上代码

foreach (AttachmentBox objAttachmentBox in lsAttachments)
{
    if (objAttachmentBox.AttachmentId == int.Parse(e.CommandArgument.ToString()))
    {
        lsAttachments.Remove(objAttachmentBox);
    }
}

这是我刚开始写的代码。。

运行时候VS提示错误 “集合已修改;可能无法执行枚举操作。”跑到博客园里面找了一番,发现使用foreach就会存在这个问题,因为foreach在遍历的时候只取只读的数据,如果用for的话,就能够比避免这个问题。

好吧,那就换成for循环吧。

for (int i = 0; i <= lsAttachments.Count(); i++)
{
    if (lsAttachments[i].AttachmentId == int.Parse(e.CommandArgument.ToString()))
    {
       lsAttachments.RemoveAt(i);
    }
}

运行程序显示成功,不过不小心瞄到了List的RemoveAll的方法,饿。。是虾米意思呢?打开vs帮助查了一下,原来是使用委托找到相应的对象,并移除

MSDN里面的代码是这样写的。。。。

private static bool EndsWithSaurus(String s)
{
    if ((s.Length > ...