• Castle ActiveRecord学习实践


    实现One-Many

      这里我采用上篇中将过(的)XML配置方式

    <?xml version="1.0" encoding="utf-8" ?>
    <activerecord>
      <config>
        <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
        <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
        <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
        <add key="hibernate.connection.connection_string" value="Data Source=.;Initial Catalog=test;Integrated Security=SSPI" />
      </config>
    </activerecord>

      四.编写测试代码

      1.级联增加:新增一个Blog,并同时添加相关(的)Post到数据表中

    [Test]
    public void TestCascadingSave()
    {
      //创建Blog对象
      Blog blog = new Blog();
      blog.Name="Terrylee's Tech Space";
      blog.Author = "Terrylee";
      
      //执行事务,持久化对象到数据库
      using(TransactionScope tran = new TransactionScope())
      {
        try
        {
          blog.Create();
          for(int i=1;i<11;i++)
          {
            //创建Post对象
            Post post = new Post();
            post.Title="This is my "+i.ToString()+" post";
            post.Category="Castle";
            post.Blog = blog;
            post.Save();
          }
      
          tran.VoteCommit();
        }
        catch
        {
          tran.VoteRollBack();
        }
      }// The changes will be sent to the DB when the session is disposed here
    }

      2.级联更新:

      首先我们为一个已经存在(的)Blog增加多个Post

    [Test]
    public void TestCascadingUpdate()
    { 
      //找到ID为5(的)Blog
      Blog blog = Blog.Find(5);
      
      //执行事务,持久化对象到数据库
      using(TransactionScope tran = new TransactionScope())
      {
        try
        {     
          for(int i=1;i<5;i++)
          {
            //创建Post对象
            Post post = new Post();
            post.Title="This is my "+i.ToString()+" post";
            post.Category="Castle";
            post.Save();
            //注意这句
            blog.Posts.Add(post);
          }
          blog.Update();
      
          tran.VoteCommit();
        }
        catch
        {
          tran.VoteRollBack();
        }
      }
    }

      当然上面(的)更新代码(也)可以这样去写:

    [Test]
    public void TestCascadingUpdate()
    { 
      //找到ID为5(的)Blog
      Blog blog = Blog.Find(5);
      
      //执行事务,持久化对象到数据库
      using(TransactionScope tran = new TransactionScope())
      {
        try
        {     
          for(int i=1;i<5;i++)
          {
            //创建Post对象
            Post post = new Post();
            post.Title="This is my "+i.ToString()+" post";
            post.Category="Castle";
      
            //在这儿指定它们(的)关联
            post.Blog = blog;
            post.Save();
          }
        tran.VoteCommit();
        }
        catch
        {
          tran.VoteRollBack();
        }
      }
    }

      但(是)如果我们去掉post.Save()这句话,(就)会发现Post并没有增加到库中:

    [Test]
    public void TestCascadingUpdate()
    { 
      //找到ID为5(的)Blog
      Blog blog = Blog.Find(5);
      
      //执行事务,持久化对象到数据库
      using(TransactionScope tran = new TransactionScope())
      {
        try
        {     
          for(int i=1;i<5;i++)
          {
            //创建Post对象
            Post post = new Post();
            post.Title="This is my "+i.ToString()+" post";
            post.Category="Castle";
            //注释掉这句
            //post.Save();
            blog.Posts.Add(post);
          }
      
          blog.Update();
        tran.VoteCommit();
        }
        catch
        {
          tran.VoteRollBack();
        }
      }
    }

      此时,必须修改我们(的)Blog类,设置级联操作为SaveUpdate,上面(的)代码才可以正常执行

    //
    [HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid",Cascade=ManyRelationCascadeEnum.SaveUpdate)]
    public IList Posts
    {
      get { return _posts; }
      set { _posts = value; }
    }

      下面再测试一个删除某一个Blog(的)某些Post后,再保存

    [Test]
    public void TestCascadingUpdateDel()
    { 
      //找到ID为7(的)Blog
      Blog blog = Blog.Find(7);
      int expectedCount = blog.Posts.Count;
      using(TransactionScope tran = new TransactionScope())
      {
        try
        {
          blog.Posts.RemoveAt(0);
          blog.Update();
      
          tran.VoteCommit();
        }
        catch
        {
          tran.VoteRollBack();
        }
      }
      int actualCount = Blog.Find(7).Posts.Count;
      
      Assert.AreEqual(expectedCount-1,actualCount);
    }

      上面这段代码测试可以通过,但(是)我们会发现表Posts中会有一些记录没有BlogId,修改Blog实体类重新设置级联操作,(就)可以正常删除了:

    //
    [HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid",Cascade=ManyRelationCascadeEnum.AllDeleteOrphan)]
    public IList Posts
    {
      get { return _posts; }
      set { _posts = value; }
    }

      3.级联删除

      删除一个Blog对象后,对应(的)Post对象应该全部删除

    [Test]
    public void TestCascadingDelete()
    {
      //找到ID为7(的)Blog对象
      Blog blog = Blog.Find(5);
      
      using(TransactionScope tran = new TransactionScope())
      {
        try
        {
          blog.Delete();
      
          tran.VoteCommit();
        }
        catch
        {
          tran.VoteRollBack();
        }
      }
    }

      同样要注意设置级联操作。

      关于One-Many关联映射(就)介绍这么多了,至于Many-One关联同One-Many,只不过对HasMany和BlongsTo设置(的)位置不一样而已,在下一篇文章中我会介绍在ActiveRecord中实现Many-Many关联映射。

    实现Many Many

    主要内容

      1.准备数据库表

      2.编写实体类

      3.编写测试代码

      一.准备数据库表

      接着在上篇文章中(的)例子,为了实现多对多(的)关系,我们引入Community,即每个Blog可以属于多个社区,每个社区(也)可以有多个Blog。

    CREATE TABLE Blogs (
      blog_id   int IDENTITY(1, 1) PRIMARY KEY,
      blog_name  varchar(50),
      blog_author varchar(50)
    )
      
    CREATE TABLE Blog_Community (
       blog_Id int NOT NULL ,
       community_Id int NOT NULL
    )
      
    CREATE TABLE Communities (
       community_Id int IDENTITY (1, 1) PRIMARY KEY,
       community_Name varchar (50) ,
       community_Intro varchar (500)
    )

      二.编写实体类代码

      为了实现多对多(的)关系,我们要在Blog、Community类中分别使用HasAndBelongsToMany特性,不需要编写Blog_Community类。示例代码:

    // Blog
    [HasAndBelongsToMany( typeof(Community),
        Table="Blog_Community",
        ColumnRef=" community_id ",
        ColumnKey=" blog_id " )]
    public IList Communitys
    {
      get { return _community; }
      set { _ community = value; }
    }
      
    // Community
    [HasAndBelongsToMany( typeof(Blog),
        Table="Blog_Community",
        ColumnRef="blog_id",
        ColumnKey="community_id" )]
    public IList Blogs
    {
      get { return _blog; }
      set { _ blog = value; }
    }

      HasAndBelongsToMany(的)参数相信大家都能够看明白,指定关联表名和关联(的)外键(就)可以了。

      注意:这三个参数必须指定,不可以省略!

      HasManyAttribute说明

    属性 说明 示例
    Cascade 指明哪些操作会从父对象级联到关联(的)对象,相关(的)操作见后面,如果不指定,则为None Cascade=ManyRelationCascadeEnum.All
    Inverse 指定(是)否级联操作 Inverse =true|false
    Schema 指定Schema(的)名字 Schema="ARDemo"
    Table 指定持久化类所关联(的)数据库表名,如果表名与类名相同,可以省略 Table="posts"
    ColumnKey 本实体类于另一个实体类关联(的)外键 ColumnKey="community_id"
    ColumnRef 另一实体类(的)外键 ColumnRef="blog_id"
    Where 指定一个附加SQL(的)Where子句 Where="IsPost = 0"
    Lazy 指定(是)否延迟加载关联对象 Lazy=true|false

      Cascade(的)类型值有如下几种

    类型 说明
    None 不进行级联操作
    SaveUpdate 进行级联Save/Update操作
    Delete 进行级联Delete操作
    All 进行级联Save/Update/Delete操作
    AllDeleteOrphan 进行级联Save/Update/Delete操作,并删除无相关父对象(的)子对象

      最后完整(的)实体类如下:

    /**//// <summary>
    /// Blog (的)摘要说明。
    /// </summary>
    [ActiveRecord("Blogs")]
    public class Blog : ActiveRecordBase
    {
      private int _id;
      
      private String _name;
      
      private String _author;
      
      private IList _community;
      
      [PrimaryKey(PrimaryKeyType.Identity, "blog_id")]
      public int Id
      {
        get { return _id; }
        set { _id = value; }
      }
      
      [Property("blog_name")]
      public String Name
      {
        get { return _name; }
        set { _name = value; }
      }
      
      [Property("blog_author")]
      public String Author
      {
        get { return _author; }
        set { _author = value; }
      }
      [HasAndBelongsToMany(typeof(Community),
          Table="Blog_Community",
          ColumnRef=" community_id ",
          ColumnKey=" blog_id " )]
      public IList Communities
      {
        get { return _community; }
        set { _community = value; }
      }
      
      public static void DeleteAll()
      {
        DeleteAll( typeof(Blog) );
      }
      
      public static Blog[] FindAll()
      {
        return (Blog[]) FindAll( typeof(Blog) );
      }
      
      public static Blog Find(int id)
      {
        return (Blog) FindByPrimaryKey( typeof(Blog), id );
      }
    }
      
    /**//// <summary>
    /// Community (的)摘要说明。
    /// </summary>
    [ActiveRecord("Communities")]
    public class Community : ActiveRecordBase
    {
      private int _id;
      
      private String _name;
      
      private String _intro;
      
      private IList _blog;
      
      [PrimaryKey(PrimaryKeyType.Identity, "Community_Id")]
      public int Id
      {
        get { return _id; }
        set { _id = value; }
      }
      
      [Property("Community_Name")]
      public String Name
      {
        get { return _name; }
        set { _name = value; }
      }
      
      [Property("Community_Intro")]
      public String Author
      {
        get { return _intro; }
        set { _intro = value; }
      }
      [HasAndBelongsToMany(typeof(Blog),
          Table="Blog_Community",
          ColumnRef="blog_id",
          ColumnKey="community_id" )]
      public IList Blogs
      {
        get { return _blog; }
        set { _blog = value; }
      }
      
      public static void DeleteAll()
      {
        DeleteAll( typeof(Community) );
      }
      
      public static Community[] FindAll()
      {
        return (Community[]) FindAll( typeof(Community) );
      }
      
      public static Community Find(int id)
      {
        return (Community) FindByPrimaryKey( typeof(Community), id );
      }
    }

      三.编写测试代码

      下面(是)我写(的)一些简单(的)测试代码,有兴趣(的)可以看一下。

      1.级联增加:新增一个Blog,让它同时属于好几个社区

    [Test]
    public void TestCascadingSave()
    {
      //新建一个Blog
      Blog blog = new Blog();
      blog.Name = "Tech Space";
      blog.Author = "Terrylee";
      //属于ID为1,2社区
      ArrayList list = new ArrayList();
      list.Add(Community.Find(1));
      list.Add(Community.Find(2));
      blog.Communities = list;
      //保存
      blog.Save();
    }

      2.级联更新:对一个已经存在Blog,更改它属于更多(的)社区

    [Test]
    public void TestCascadingUpdate()
    {
      //测试1:查找一个Blog
      Blog blog = Blog.Find(10);
      
      IList clist = blog.Communities;
      
      clist.Add(Community.Find(4));
      clist.Add(Community.Find(3));
      
      blog.Save();
      
      //测试2:查找一个Community
      Community community = Community.Find(3);
      
      IList blist = community.Blogs;
      
      blist.Add(Blog.Find(8));
      
      community.Save();
    }

      3.级联删除:删除一个Blog,级联表中对应(的)记录应该删除,但Community不能删除,因为还有别(的)Blog和它关联

    [Test]
    public void TestCascadingDelete()
    {
      //测试1:删除Blog
      Blog blog = Blog.Find(10);
      using(TransactionScope btran = new TransactionScope())
      {
        try
        {
          blog.Delete();
          btran.VoteCommit();
        }
        catch
        {
          btran.VoteRollBack();
        }
      }
      
      //测试2:删除Community
      Community community = Community.Find(3);
      
      using(TransactionScope ctran = new TransactionScope())
      {
        try
        {
          community.Delete();
          ctran.VoteCommit();
        }
        catch
        {
          ctran.VoteRollBack();
        }
      }
    }

      好了,关于Many-Many关联映射(就)写这么多了,内容比较简单。下篇文章我会介绍在ActiveRecord中实现延迟加载和使用Where子句。

    http://www.qzsou.cn/aWangLuo/aAspNet/47823.html

    http://www.qzsou.cn/Search.asp?searchtype=-1&searchword=Castle+ActiveRecord

    CastleProject非常庞大,ActiveRecord是其中一个非常适合用于DomainModel开发的O/RMapping框架。它使用.NET的反射特性无需配置文件,集成NHibernate完成数据层持久化功[阅读全文]
    主要内容  1.由实体类生成数据表  2.运行存在的SQL脚本  3.使用空属类型  4.使用枚举类型的属性  5.使用NHibernate中的日志记录  一.由实体类生成数据表  在前面所用到的例子中我们都是先有数据表结构,然后才有实体类,然而这会让很多朋友[阅读全文]
    主要内容  1.HQL概述  2.SimpleQuery查询  3.ScalarQuery查询  4.自定义查询  5.使用CallBack  一.HQL简单介绍  HQL全名是HibernateQueryLangua[阅读全文]
    摘要:写这篇文章缘于昨天跟Linkin的一段聊天。我在使用ActiveRecord的一些技巧一文中的由实体类生成数据库表提到了这样一句话:生成数据库表时只有当该表不存在时ActiveRecord才会生成,否则表如果存在ActiveRecord不会做任何事情,也[阅读全文]
    主要内容  1.概述  2.使用Validation  3.如何扩展  4.深入分析验证  一.概述  在录入数据时,对数据有效性的验证是必不可少的,很多时候我们在UI层上就会做一层验证,但有时也需要在底层做一些必要的处理[阅读全文]
    摘要:在ActiveRecord中把数据库表之间的关联关系采用对象间的聚合关系来表现,然而这却带来一系列的性能上的问题。就像我在One-Many中用到的例子Blog,使用Blog.Find(1)查找了一个Blog对象,也许[阅读全文]
    主要内容  1.准备数据库表  2.编写实体类  3.编写测试代码  一.准备数据库表  接着在上篇文章中的例子,为了实现多对多的关系,我们引入Community,即每个Blog可以属于多个社区,每个社区也可以有多个Blog。CREATETABLEBlog[阅读全文]
    主要内容  1.准备数据表结构  2.编写实体类并介绍HasMany和BlongsTo特性  3.构建配置信息  4.编写测试代码  一.准备数据表结构  在这个例子中,我们引入了两个对象Blog、Post,它们之间的关系是一对多,即一个Blog有多篇Post[阅读全文]
    主要内容  简单映射  1.ActiveRecordAttribute  2.PrimaryKeyAttribute  3.CompositeKeyAttribute  4.PropertyAttribute  5.FieldAttribute  一.Act[阅读全文]
    主要内容  1.需要配置什么  2.如何去配置  3.常见的配置示例  一.需要配置什么  在第一篇大家都已经看到了,其实我们的配置信息跟用NHibernate时的配置是一样的,这是因为ActiveRecord在底层封装了NHibernate。为了没有用过NH[阅读全文]
    摘要:最近几天有时间看了一下Castle,原来它的功能是如此的强大,从数据访问框架到IOC容器,再到WEB框架,基本包括了整个开发过程中的所有东西,看来得好好学习研究一下了,并且打算把自己学习过程的一些东西记录下来。先从A[阅读全文]
  • 相关阅读:
    解决首次访问网上邻居密码错误,而造成的以后都无权访问的解决方案。
    MapX开发日记(二)
    对于一个网卡绑定多个IP的问题。
    .net VS 全角问题
    DotnetBar MapX中动态生成可以查询地图数据的弹出菜单问题
    sqlServer 字符型字段默认为空字符串
    MapX开发日记(一)
    ASP.NET Dbtype属性无效 与系统自带控件为英文
    原创 c# 封装的带CheckBox的DataGridViewColumnHeaderCell 源码部分 实现DataGridView列头带CheckBox控件实现全选功能,支持列头带标题
    关于去共享锁获取脏数据
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1894392.html
Copyright © 2020-2023  润新知