天天看點

Castle ActiveRecord架構學習(一)

一、Active Record(活動記錄)模式

  Active Record是業務邏輯層中(《企業應用架構模式》将該模式歸為資料源模式)常用的一種架構模式,尤其在底層資料庫模型比對業務模型時它特别有用,它是一種以資料庫驅動為主的架構模式。

  通常,資料庫中的每張表都對應一個業務對象。業務對象表示表中的一行,并且包含資料、行為以及持久化該對象的工具,此外還有添加新執行個體和查找對象集合所需的方法。

  在Active Record模式中,每個業務對象均負責自己的持久化和相關的業務邏輯。

  Active Record模式非常适用于在資料模型與業務模型之間具有 一對一映射關系的簡單應用程式,如部落格或論壇。

  因為業務對象與資料庫中的表具有一對一映射關系,而且均具有相同的CRUD方法,是以可以使用代碼生成器自動生成業務模型。

  Active Record模式中的對象通常會包含用來執行資料庫操作的CRUD操作,還有相關驗證及業務相關的計算和檢查功能。

  特别地,典型的Active Record類還包含一些表示資料表中的列的執行個體屬性和操作于目前對象上的執行個體方法。Active Record類中還可能包含一些靜态方法,用來操作資料表上的所有記錄。(下面的實戰操作可能會很好的幫助你了解這句話)

  1.Active Record的優勢

  Active Record的成功依賴于兩個因素:簡單和架構。Active Record概念上了解起來十分的簡單, 不過若手工實作,仍然需要很多代碼。

  編寫并維護每一個類都需要大量的代碼,不過這僅僅是最低的需求,因為你可能還要考慮為每個類或者資料表添加一個或多個資料遷移對象(DTO)。

  不可否認,活動記錄确實在簡單和最終系統的強大方面找到了良好的平衡。且該模式也等到了很多開發商的支援,例如,LINQ-to-SQL和我們今天的主角--Castle ActiveRecord。

  2.Active Record的劣勢

  理論上,開發中還需要一個額外的層存在于對象模型和資料模式之間,通常叫做資料映射層(Data Mapper)。在Active Record中,我們可以将該層直接內建在對象中,不過随着這一層越來越複雜,維護成本也在逐漸提高。

  Active Record的另外一個問題是對象和資料表設計之間的綁定。若你不得不修改資料庫,那麼要同時修改Active Record的對象模型以及所有的相關代碼。

  3.Active Record與表模式的差別

  表模式通常就是目前三層架構中流行的以DateTable和DateSet為載體在各層中傳遞資料,Active Record則是以對象模型、泛型(如IList<Post>)為載體在各層中傳遞資料。

二、Castle ActiveRecord介紹

  Castle ActiveRecord 是ActiveRecord 模式的一個實作,Castle ActiveRecord依賴Nhibernate來完成實際的映像。與單純的ActiveRecord 相比,Castle ActiveRecord具有以下特點:

  •  靈活開發(它盡可能多地處理了映射和推斷,是以,對你的方案而言,當一些東西發生變化的時候,你不必去鑽研文檔或者處理大量的xml文檔)
  • 預定了像Create, Update, Save, Delete這樣的公共方法。
  • 容易實作像Find, FindAll, FindByName等此類的方法。
  • 繪畫和事務範圍(Session and transaction scopes that abstracts the ISession and translates them to a more natural idiom )

  使用Nhibernate,你繁瑣的配置工作多于複雜的映射,而使用ActiveRecord卻是推進你的生産力的一個保證,你不必再為編寫繁冗複雜的映射檔案而頭疼,ActiveRecord封裝了NHibernate的操作,使用特性來代替映射檔案,無論何時你需要,ActiveRecord都能給你一個Isession執行個體,它提供的簡潔的O/R映射會讓你為實作持久化資料層是那麼簡單而驚歎!

  官方網址:http://www.castleproject.org/

三、Castle ActiveRecord入門實戰

  環境:Windows 8.1+Visual Stidio 2013+Sql Server 2008R2+.Net Framework 4.0

  版本:Castle.ActiveRecord-3.0.RC

  相關下載下傳:SDK下載下傳 源碼下載下傳

  資料庫: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      

  如圖:

  

Castle ActiveRecord架構學習(一)

  項目目錄:

Castle ActiveRecord架構學習(一)

  Model-->Castle.ActiveRecord.dll、NHibernate.dll

  Web-->Model、Castle.ActiveRecord-3.0.RC中的所有DLL

  Model中:

  Post類:

// 指定資料表
    [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);
        }
    }          

  Comment類:

[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; }
    }      

  Web中:

  NHibernate.config配置檔案:

<?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>      

  Global.asax:加載配置檔案

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;
            }

        }      

  Default.aspx:測試

  Add操作:

public void Add()
{
     Model.Post post = new Model.Post()
     {
         Subject = "測試2",
         Text = "測試内容2",
         DateAdded = DateTime.Now
      };
       post.Create();
}      

  Update操作:

public void Update()
{
      Model.Post post = new Model.Post();
      post = Model.Post.Find(1);
      post.Subject = "修改後1";
      post.Text = "修改後内容1";
      post.Update();
}      

  Delete操作:

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();
}      

  Find操作:

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");
       }
}      

源碼下載下傳:百度雲

繼續閱讀