Active Record是业务逻辑层中(《企业应用架构模式》将该模式归为数据源模式)经常使用的一种框架模式,尤为在底层数据库模型匹配业务模型时它特别有用,它是一种以数据库驱动为主的框架模式。git
一般,数据库中的每张表都对应一个业务对象。业务对象表示表中的一行,而且包含数据、行为以及持久化该对象的工具,此外还有添加新实例和查找对象集合所需的方法。github
在Active Record模式中,每一个业务对象均负责本身的持久化和相关的业务逻辑。数据库
Active Record模式很是适用于在数据模型与业务模型之间具备 一对一映射关系的简单应用程序,如博客或论坛。session
由于业务对象与数据库中的表具备一对一映射关系,并且均具备相同的CRUD方法,因此可使用代码生成器自动生成业务模型。架构
Active Record模式中的对象一般会包含用来执行数据库操做的CRUD操做,还有相关验证及业务相关的计算和检查功能。app
特别地,典型的Active Record类还包含一些表示数据表中的列的实例属性和操做于当前对象上的实例方法。Active Record类中还可能包含一些静态方法,用来操做数据表上的全部记录。(下面的实战操做可能会很好的帮助你理解这句话)框架
Active Record的成功依赖于两个因素:简单和框架。Active Record概念上理解起来十分的简单, 不过若手工实现,仍然须要不少代码。ide
编写并维护每个类都须要大量的代码,不过这仅仅是最低的需求,由于你可能还要考虑为每一个类或者数据表添加一个或多个数据迁移对象(DTO)。工具
不能否认,活动记录确实在简单和最终系统的强大方面找到了良好的平衡。且该模式也等到了不少开发商的支持,例如,LINQ-to-SQL和咱们今天的主角--Castle ActiveRecord。post
理论上,开发中还须要一个额外的层存在于对象模型和数据模式之间,一般叫作数据映射层(Data Mapper)。在Active Record中,咱们能够将该层直接集成在对象中,不过随着这一层愈来愈复杂,维护成本也在逐渐提升。
Active Record的另一个问题是对象和数据表设计之间的绑定。若你不得不修改数据库,那么要同时修改Active Record的对象模型以及全部的相关代码。
表模式一般就是目前三层框架中流行的以DateTable和DateSet为载体在各层中传递数据,Active Record则是以对象模型、泛型(如IList<Post>)为载体在各层中传递数据。
Castle ActiveRecord 是ActiveRecord 模式的一个实现,Castle ActiveRecord依赖Nhibernate来完成实际的映像。与单纯的ActiveRecord 相比,Castle ActiveRecord具备如下特色:
使用Nhibernate,你繁琐的配置工做多于复杂的映射,而使用ActiveRecord倒是推动你的生产力的一个保证,你没必要再为编写繁冗复杂的映射文件而头疼,ActiveRecord封装了NHibernate的操做,使用特性来代替映射文件,不管什么时候你须要,ActiveRecord都能给你一个Isession实例,它提供的简洁的O/R映射会让你为实现持久化数据层是那么简单而惊叹!
官方网址:http://www.castleproject.org/
环境:Windows 8.1+Visual Stidio 2013+Sql Server 2008R2+.Net Framework 4.0
版本:Castle.ActiveRecord-3.0.RC
数据库:ActiveRecord_Blog
数据表:Post
USE [ActiveRecord_Blog] GO /****** Object: Table [dbo].[Post] Script Date: 11/08/2014 11:12:03 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Post]( [Id] [int] IDENTITY(1,1) NOT NULL, [Subject] [nvarchar](64) NULL, [Text] [nvarchar](1024) NULL, [DateAdded] [datetime] NULL, CONSTRAINT [PK_Posts] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
数据表:Comment
USE [ActiveRecord_Blog] GO /****** Object: Table [dbo].[Comment] Script Date: 11/08/2014 11:11:22 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Comment]( [Id] [int] IDENTITY(1,1) NOT NULL, [Text] [nvarchar](1024) NULL, [Author] [nvarchar](64) NULL, [DateAdded] [datetime] NULL, [PostId] [int] NULL, CONSTRAINT [PK_Comment] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO ALTER TABLE [dbo].[Comment] WITH CHECK ADD CONSTRAINT [FK_Comment_Post] FOREIGN KEY([PostId]) REFERENCES [dbo].[Post] ([Id]) GO ALTER TABLE [dbo].[Comment] CHECK CONSTRAINT [FK_Comment_Post] GO
如图:
Model-->Castle.ActiveRecord.dll、NHibernate.dll
Web-->Model、Castle.ActiveRecord-3.0.RC中的全部DLL
// 指定数据表 [ActiveRecord("Post")] public class Post : ActiveRecordBase<Post> { // 指定数据表中的主键 [PrimaryKey(PrimaryKeyType.Identity, "Id")] public int Id { get; set; } // 指定数据表中的列 [Property("Subject")] public string Subject { get; set; } [Property("Text")] public string Text { get; set; } [Property("DateAdded")] public DateTime DateAdded { get; set; } //一对多 [HasMany(typeof(Comment), Table = "Comment", ColumnKey = "PostId")] public IList<Comment> Comments { get; set; } // 静态方法,经过主键ID查找 public static Post Find(int id) { return FindByPrimaryKey(id); } }
[ActiveRecord("Comment")] public class Comment : ActiveRecordBase<Comment> { [PrimaryKey("Id")] public int Id { get; set; } [Property("Author")] public string Author { get; set; } [Property("Text")] public string Text { get; set; } [Property("DateAdded")] public DateTime DateAdded { get; set; } [Property("PostId")] public int PostId { get; set; } // 多对一,对应Post的的Comments属性 [BelongsTo(Column = "PostId")] public Post Post { get; set; } }
<?xml version="1.0" encoding="utf-8"?> <activerecord isWeb="true"> <config> <add key="connection.driver_class" value="NHibernate.Driver.SqlClientDriver" /> <add key="dialect" value="NHibernate.Dialect.MsSql2005Dialect" /> <add key="connection.connection_string" value="UID=sa;Password=123456;Initial Catalog=ActiveRecord_Blog;Data Source=." /> <add key="connection.provider" value="NHibernate.Connection.DriverConnectionProvider" /> <add key="proxyfactory.factory_class" value="NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle" /> </config> </activerecord>
void Application_Start(object sender, EventArgs e) { // 在应用程序启动时运行的代码 AuthConfig.RegisterOpenAuth(); RouteConfig.RegisterRoutes(RouteTable.Routes); InitActiveRecord(); } private void InitActiveRecord() { try { string NHibernateFilePath = Server.MapPath("~/NHibernate.config"); XmlConfigurationSource source = new XmlConfigurationSource(NHibernateFilePath); ActiveRecordStarter.Initialize(source, typeof(Model.Post), typeof(Model.Comment)); } catch (Exception) { throw; } }
public void Add() { Model.Post post = new Model.Post() { Subject = "测试2", Text = "测试内容2", DateAdded = DateTime.Now }; post.Create(); }
public void Update() { Model.Post post = new Model.Post(); post = Model.Post.Find(1); post.Subject = "修改后1"; post.Text = "修改后内容1"; post.Update(); }
public void Delete(int id) { Model.Post post = new Model.Post(); post.Id = 1; post.Delete(); Response.Write("删除了ID:" + id + "\n\r"); } public void DeleteAll() { Model.Post.DeleteAll(); }
public void Find(int id) { using (new SessionScope()) { Model.Post post = new Model.Post(); post = Model.Post.Find(id); Response.Write(post.Id.ToString() + "\n\r"); Response.Write(post.Subject + "\n\r"); Response.Write(post.Text + "\n\r"); Response.Write(post.DateAdded.ToString() + "\n\r"); Response.Write(post.Comments.FirstOrDefault().Id); } } public void FindAll() { IList<Model.Post> postList = Model.Post.FindAll(); foreach (var post in postList) { Response.Write(post.Id.ToString() + "\n\r"); Response.Write(post.Subject + "\n\r"); Response.Write(post.Text + "\n\r"); Response.Write(post.DateAdded.ToString() + "\n\r"); } }
源码下载:百度云