Castle ActiveRecord框架学习(二):快速搭建简单博客网站
一、数据库
1.数据表
Category:类别标签表(字段Type=1为类别,Type=2为标签)
Category_Post:类别标签与文章中间表
Post:文章表
Comment:评论表
2.数据库关系图
3.简单说明
Category和Post表为多对多关系
Post和Comment表 为一对多关系
二、实体类
1.Category类:

// 指定数据表,Lazy为延迟加载 [ActiveRecord("Category",Lazy=true)] public class Category : ActiveRecordBase<Category> { // 指定数据表中的主键 [PrimaryKey("Id")] public virtual int Id { get; set; } // 指定数据表中的列 [Property("Title")] public virtual string Title { get; set; } [Property("Description")] public virtual string Description { get; set; } [Property("DateAdded")] public virtual DateTime DateAdded { get; set; } [Property("Type")] public virtual int Type { get; set; } // 多对多 // typeof(Post):对方表的实体类,Table:关联中间表,ColumnRef:关联中间表中与对方实体相关的列,ColumnKey:关联中间表中与本实体相关的列,Lazy:延迟加载,通过本实体获取对方实体信息时,才会去数据库查询 [HasAndBelongsToMany(typeof(Post),Table = "Category_Post", ColumnRef = "Post_Id", ColumnKey = "Category_Id",Lazy=true)] public virtual IList<Post> Posts { get; set; } public static IList<Category> FindAllForTopCategory() { SimpleQuery<Category> query = new SimpleQuery<Category>(@" from Category c where c.Type=1"); return query.Execute(); } public static Category Find(int id) { return FindByPrimaryKey(id); } }
2.Post类:

// 指定数据表 [ActiveRecord("Post",Lazy=true)] public class Post : ActiveRecordBase<Post> { // 指定数据表中的主键 [PrimaryKey(PrimaryKeyType.Identity, "Id")] public virtual int Id { get; set; } // 指定数据表中的列 [Property("Subject")] public virtual string Subject { get; set; } [Property("Text")] public virtual string Text { get; set; } [Property("DateAdded")] public virtual DateTime DateAdded { get; set; } // 一对多 // typeof(Comment):对方的实体类,Table:对方表名,ColumnKey:对方表的外键,Lazy:延迟加载 [HasMany(typeof(Comment), Table = "Comment", ColumnKey = "PostId",Lazy=true)] public virtual IList<Comment> Comments { get; set; } // 多对多 [HasAndBelongsToMany(typeof(Category),Table="Category_Post",ColumnRef="Category_Id",ColumnKey="Post_Id",Lazy=true)] public virtual IList<Category> Categorys { get; set; } public static Post Find(int id) { return FindByPrimaryKey(id); } }
3.Comment类:

// 指定数据表 [ActiveRecord("Comment",Lazy=true)] public class Comment : ActiveRecordBase<Comment> { // 指定数据表中的主键 [PrimaryKey("Id")] public virtual int Id { get; set; } // 指定数据表中的列 [Property("Author")] public virtual string Author { get; set; } [Property("Text")] public virtual string Text { get; set; } [Property("DateAdded")] public virtual DateTime DateAdded { get; set; } // 多对一,对应Post的的Comments属性 [BelongsTo(Column = "PostId")] public virtual Post Post { get; set; } }
说明:
1.Category和Post在数据库中是多对多关系,由一张中间表Category_Post互相关联,但在C#实体类中则不需要为Category_Post建立实体模型 。
2.多对多在Castle ActiveRecord中通过HasAndBelongsToMany特性进行关联,具体的使用在代码注释中以说明,见Category类和Post类中的代注释。(官网,中文)
3.一对多在Castle ActiveRecord中通过HasAndBelongsToMany特性进行关联,具体的使用在代码注释中以说明,见Post类中的代注释。(中文)
4.多对一在Castle ActiveRecord中通过BelongsTo特性进行关联,具体的使用在代码注释中以说明,见Comment类中的代注释。(中文)
5.Lazy代表延迟加载,可以为实体类本身进行添加,也可以为多对多和一对多等关系字段进行添加,具体效果可以自行查看。(官网,中文)
6.启动Lazy模式时,实例类中的上述必须为virtual。
三、页面展示
首页:
主要代码:

private void LoadIndexPost() { StringBuilder sb = new StringBuilder(); using (new SessionScope()) { IList<Model.Post> PostListForIndex = Model.Post.FindAll(); foreach (Model.Post post in PostListForIndex) { sb.Append("<h3><a href=\"Post.aspx?id=" + post.Id + "\">" + post.Subject + "</a></h3>"); sb.Append("<figure><img src=\"images/ex03.png\"></figure>"); sb.Append("<ul><p><a href=\"Post.aspx?id=" + post.Id + "\">" + post.Text + "</a></p></ul>"); sb.Append("<div class=\"dateview\"><a title=\"/\" href=\"/\" target=\"_blank\" class=\"readmore\">阅读全文>></a><span>" + post.DateAdded.ToString("yyy-MM-dd") + "</span>"); sb.Append("<span><a href=\"Post.aspx?id=" + post.Id + "#Comment\">评论数:" + post.Comments.Count() + "</a></span>"); sb.Append("<span>标签:"); post.Categorys.ForEach(c => sb.Append("[<a href=\"Category.aspx?id=" + c.Id + "\">" + c.Title + "</a>]")); sb.Append("</span></div>"); } PostContent = sb.ToString(); } }
说明 :
当在实体类中启用Lazy模式时,通过关联从一个实体获取另一个实体的信息时,必须使用new SessionScope(),开始时使用Model.Post.FindAll()只获取需要的文章数据,由于启用了Lazy模式,没有获取与 Post表相关联的所有数据,但是在后续代码中发现需要评论表中的数据和类别标签表中的数据,那就要保存当前的Session,以便后续的数据库操作。
四、参考资料
官方资料:http://docs.castleproject.org/
中文资料:TerryLee
模版提供:杨清
五、演示代码
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?