所以,这里我将会介绍一个真实的,非常小的,用 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
未完待续……