DbEntry 开发实践:Wiki 系统(一)
有人在网站给我发短消息,希望我多写一些 DbEntry 开发的文章,我想,关于细节问题,还是看 DbEntry 的主页的文档比较好,如果真的要写,我倒觉得,以一个真实系统的开发实践作为题目更有意义些。
所以,这里我将会介绍一个真实的,非常小的,用 DbEntry 开发的 Wiki 系统的流程,其中不止涉及 DbEntry,还会包括其它一些开发流程中的问题、方法、工具等。
在开始项目前,先介绍几个我目前使用的 Visual Studio 2008 集成工具:
好的,这个 Wiki 系统的需求如下:
关于可视化编辑,我认为是必需的,因为我实在不愿意去记忆那些 Wiki 语法,相信其他人也一样。但是,见到的很多 Wiki 系统都使用 Wiki 的特殊语法,所以我称这个 Wiki 系统为 Visual Wiki。SharePoint 倒是提供了一个可视化编辑的 Wiki,只是如果只想要一个 Wiki 而去安装 SharePoint 的话,有点儿小题大作了。可视化编辑部分,使用 FckEditor 来实现,它有 .net 控件版本,所以我们不需要太关心它是怎么实现的。
好,基础的准备工作做完了,我们开始建立 VisualWiki 解决方案,其中有 3 个项目,VisualWiki 是 WebSite,VisualWiki.Models 是 Models 和一些辅助类,VisualWiki.UnitTests 是单元测试,3个项目都基于.Net Framework 3.5,3个项目都引用4个DbEntry.Net 的 DLL,另外,VisualWiki需要添加FredCK.FCKeditorV2.dll以及VisualWiki.Models的引用,VisualWiki.Models需要添加System.Web的引用,VisualWiki.UnitTests需要添加nunit.framework.dll以及VisualWiki.Models的引用,建好的项目目录如下:
我在以前的留言里说过,DbEntry鼓励使用Sqlite作为开发数据库,而部署使用其他大型数据库,这里我们就使用Sqlite。打开web.config,Visual Studio已经为我们生成了一大堆垃圾代码,在开始的configSections段里,添加:
然后在configSections段后,添加Lephone.Settings段,其中,我希望可以在Debug窗口看到生成的SQL,希望数据库表名使用复数形式,希望使用自动生成表功能,希望可以简单的切换Sqlite和Sql Server,所以,设置如下:
这里使用的是Sqlite .net provider 的1.0.60.0版本,你需要先安装它,另外,你的版本如果不同,修改其中的版本号部分。
为了方便,同时找到pages段,修改它,这个修改可以为以后节省一些页面里的声明:
首先在VisualWiki.Models里建立Article类,它应该有标题,内容和保存时间,并且为它添加一个静态的FindByTitle方法:
然后添加一个不使用代码分离的母板页Main.master,添加一个使用它,而且不使用分离代码的页面Show.aspx,这个aspx页面接受一个title参数,用以取得相应的Article,其中需要添加一个Label用于显示Wiki的内容,所以修改此aspx的代码如下:
现在,运行程序,Show.aspx页面将会显示一个异常:The Parameter title can't be empty。所以,我们在url后面添加参数?title=Home,然后回车,页面显示:The wiki page does not exist. The page will be created the first time you edit it。修改参数为Hello,回车,则显示:this is home page of whole world。在Visual Studio的View菜单里打开Output窗口,可以在其中看到ORM系统生成的SQL语句。VisualWiki的App_Data目录下也已经生成了Sqlite的数据库wiki.db,我们可以用SqlQuerier打开此数据库,检查articles表中的记录。
未完待续……
所以,这里我将会介绍一个真实的,非常小的,用 DbEntry 开发的 Wiki 系统的流程,其中不止涉及 DbEntry,还会包括其它一些开发流程中的问题、方法、工具等。
在开始项目前,先介绍几个我目前使用的 Visual Studio 2008 集成工具:
- Resharper,这个工具目前对我几乎是必不可少了,它提供了很多方便的功能、直观的提示、重构能力以及对于单元测试的支持。因为它提供了对单元测试的支持,我也放弃了另外一个很好的的单元测试工具 TestDriven.Net。不过,TestDriven.Net 提供更强大的单元测试支持,比如覆盖率工具,所以也是一个值得安装的工具。
- VisualSVN,是的,我使用 SVN,所以可以用 VisualSVN Server 在 Windows 上方便的安装一个 SVN 服务器,而且,codeplex也支持SVN客户端,相比之下,TFS 的安装可谓繁琐、资源占用也多得多。对于单机用户,TortoiseGit 也许是个不错的选择,不过,我的测试发现,其成熟度还有待提高,比如在 Git Bash 里可以输入用户名和密码的地方,TortoiseGit 的 GUI 却直接显示失败,另外,对于中文文件名的支持也不好。
- 在 DbEntry 的源码目录内,有一些 snippet 文件,建议安装到 Visual Studio 里,之后,可以输入 dbmodel 然后按 tab 键生成 Model 的基础架构,输入 aprop 然后按 tab 键生成抽象属性,输入 test 然后按 tab 键生成单元测试函数框架等。
好的,这个 Wiki 系统的需求如下:
- 要是一个可视化编辑的系统;
- 要有历史浏览功能;
- 它的 Url 必须是可以被加入收藏夹的;
- 它应该有一个导航条;
- 它需要有一个登录管理系统。
关于可视化编辑,我认为是必需的,因为我实在不愿意去记忆那些 Wiki 语法,相信其他人也一样。但是,见到的很多 Wiki 系统都使用 Wiki 的特殊语法,所以我称这个 Wiki 系统为 Visual Wiki。SharePoint 倒是提供了一个可视化编辑的 Wiki,只是如果只想要一个 Wiki 而去安装 SharePoint 的话,有点儿小题大作了。可视化编辑部分,使用 FckEditor 来实现,它有 .net 控件版本,所以我们不需要太关心它是怎么实现的。
好,基础的准备工作做完了,我们开始建立 VisualWiki 解决方案,其中有 3 个项目,VisualWiki 是 WebSite,VisualWiki.Models 是 Models 和一些辅助类,VisualWiki.UnitTests 是单元测试,3个项目都基于.Net Framework 3.5,3个项目都引用4个DbEntry.Net 的 DLL,另外,VisualWiki需要添加FredCK.FCKeditorV2.dll以及VisualWiki.Models的引用,VisualWiki.Models需要添加System.Web的引用,VisualWiki.UnitTests需要添加nunit.framework.dll以及VisualWiki.Models的引用,建好的项目目录如下:
我在以前的留言里说过,DbEntry鼓励使用Sqlite作为开发数据库,而部署使用其他大型数据库,这里我们就使用Sqlite。打开web.config,Visual Studio已经为我们生成了一大堆垃圾代码,在开始的configSections段里,添加:
<section name="Lephone.Settings" type="Lephone.Util.Setting.NameValueSectionHandler, Lephone.Util" />
然后在configSections段后,添加Lephone.Settings段,其中,我希望可以在Debug窗口看到生成的SQL,希望数据库表名使用复数形式,希望使用自动生成表功能,希望可以简单的切换Sqlite和Sql Server,所以,设置如下:
<Lephone.Settings>
<add key="SqlLogRecorder" value="Lephone.Util.Logging.DebugLogRecorder, Lephone.Util" />
<add key="NameMapper" value="Lephone.Util.Text.InflectionNameMapper, Lephone.Util" />
<!-- database defination -->
<add key="DefaultContext" value="Development"/>
<add key="Development.AutoCreateTable" value="true" />
<add key="Development.DataBase" value="@SQLite : @~App_Data\wiki.db"/>
<add key="Development.DbProviderFactory" value="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.60.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139"/>
<add key="Deployment.AutoCreateTable" value="true" />
<add key="Deployment.DataBase" value="@SqlServer2005 : data source=localhost;initial catalog=VisualWiki;user id=sa;password=123" />
</Lephone.Settings>
<add key="NameMapper" value="Lephone.Util.Text.InflectionNameMapper, Lephone.Util" />
<!-- database defination -->
<add key="DefaultContext" value="Development"/>
<add key="Development.AutoCreateTable" value="true" />
<add key="Development.DataBase" value="@SQLite : @~App_Data\wiki.db"/>
<add key="Development.DbProviderFactory" value="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.60.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139"/>
<add key="Deployment.AutoCreateTable" value="true" />
<add key="Deployment.DataBase" value="@SqlServer2005 : data source=localhost;initial catalog=VisualWiki;user id=sa;password=123" />
</Lephone.Settings>
这里使用的是Sqlite .net provider 的1.0.60.0版本,你需要先安装它,另外,你的版本如果不同,修改其中的版本号部分。
为了方便,同时找到pages段,修改它,这个修改可以为以后节省一些页面里的声明:
<pages pageBaseType="Lephone.Web.SmartPageBase, Lephone.Web">
<namespaces>
<add namespace="Lephone.Web" />
<add namespace="Lephone.Data" />
<add namespace="VisualWiki.Models" />
</namespaces>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add tagPrefix="fck" namespace="FredCK.FCKeditorV2" assembly="FredCK.FCKeditorV2, Version=2.6.3.23450, Culture=neutral, PublicKeyToken=4f86767c9b519a06"/>
<add tagPrefix="biz" namespace="VisualWiki.Models.DataSources" assembly="VisualWiki.Models" />
<add tagPrefix="biz" namespace="Lephone.Web.Common" assembly="Lephone.Web" />
</controls>
</pages>
<add namespace="Lephone.Web" />
<add namespace="Lephone.Data" />
<add namespace="VisualWiki.Models" />
</namespaces>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add tagPrefix="fck" namespace="FredCK.FCKeditorV2" assembly="FredCK.FCKeditorV2, Version=2.6.3.23450, Culture=neutral, PublicKeyToken=4f86767c9b519a06"/>
<add tagPrefix="biz" namespace="VisualWiki.Models.DataSources" assembly="VisualWiki.Models" />
<add tagPrefix="biz" namespace="Lephone.Web.Common" assembly="Lephone.Web" />
</controls>
</pages>
首先在VisualWiki.Models里建立Article类,它应该有标题,内容和保存时间,并且为它添加一个静态的FindByTitle方法:
namespace VisualWiki.Models
{
public abstract class Article : LinqObjectModel<Article>
{
[Length(1, 255), Index(UNIQUE = true)]
public abstract string Title { get; set; }
public abstract string Content { get; set; }
[SpecialName]
public abstract DateTime SavedOn { get; set; }
public abstract Article Init(string title, string content);
public static Article FindByTitle(string title)
{
return FindOne(p => p.Title == title);
}
}
}
public abstract class Article : LinqObjectModel<Article>
{
[Length(1, 255), Index(UNIQUE = true)]
public abstract string Title { get; set; }
public abstract string Content { get; set; }
[SpecialName]
public abstract DateTime SavedOn { get; set; }
public abstract Article Init(string title, string content);
public static Article FindByTitle(string title)
{
return FindOne(p => p.Title == title);
}
}
}
然后删除WebSite里的Default.aspx,增加一个Global.asax,并修改其中的Application_Start函数,用来初始化一篇Article:
void Application_Start(object sender, EventArgs e)
{
if(Article.GetCount(null) == 0)
{
Article.New.Init("Hello", "this is home page of whole world.").Save();
}
}
if(Article.GetCount(null) == 0)
{
Article.New.Init("Hello", "this is home page of whole world.").Save();
}
}
然后添加一个不使用代码分离的母板页Main.master,添加一个使用它,而且不使用分离代码的页面Show.aspx,这个aspx页面接受一个title参数,用以取得相应的Article,其中需要添加一个Label用于显示Wiki的内容,所以修改此aspx的代码如下:
<%@ Page Title="" Language="C#" MasterPageFile="~/Main.master" %>
<script runat="server">
[HttpParameter] public string title;
protected void Page_Load(object sender, EventArgs e)
{
var article = Article.FindByTitle(title);
ContextHolder.Text
= article != null
? article.Content
: "The wiki page does not exist. The page will be created the first time you edit it. ";
}
</script>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<asp:Label ID="ContextHolder" runat="server" Text=""></asp:Label>
</asp:Content>
<script runat="server">
[HttpParameter] public string title;
protected void Page_Load(object sender, EventArgs e)
{
var article = Article.FindByTitle(title);
ContextHolder.Text
= article != null
? article.Content
: "The wiki page does not exist. The page will be created the first time you edit it. ";
}
</script>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<asp:Label ID="ContextHolder" runat="server" Text=""></asp:Label>
</asp:Content>
现在,运行程序,Show.aspx页面将会显示一个异常:The Parameter title can't be empty。所以,我们在url后面添加参数?title=Home,然后回车,页面显示:The wiki page does not exist. The page will be created the first time you edit it。修改参数为Hello,回车,则显示:this is home page of whole world。在Visual Studio的View菜单里打开Output窗口,可以在其中看到ORM系统生成的SQL语句。VisualWiki的App_Data目录下也已经生成了Sqlite的数据库wiki.db,我们可以用SqlQuerier打开此数据库,检查articles表中的记录。
至此,我们的程序第一次可以运行,而且自动建立了数据库及表articles,并生成了一条记录,我们的Show.aspx也可以初步的根据title参数显示相应的wiki内容了。当然,后续还有很多工作要做,我们将会不断的强化和重构这个程序,最终达到需求中的各项要求。目前的代码可以在这里下载:VisualWiki.zip
未完待续……