zoukankan      html  css  js  c++  java
  • Castle ActiveRecord学习实践(6):延迟加载和使用Where子句

    摘要:在ActiveRecord中把数据库表之间的关联关系采用对象间的聚合关系来表现,然而这却带来一系列的性能上的问题。就像我在One-Many中用到的例子Blog,使用Blog.Find(1)查找了一个Blog对象,也许我们只用到它,但事实它却把该Blog所关联的Post对象也读取出来放在了内存中,于是我们就需要有一种方法来实现只在需要Post对象的时候框架再自动读取。另外ActiveRecord只提供了Find(id),FindAll()这样两个静态的查询方法,在我们查询中还远远不够,这方面ActiveRecord为我们提供了HQL语言的支持,同时也可以通过设置Where子句来实现一些简单的查询。

     

    主要内容

    1.实现延迟加载

    2.使用Where子句

     

    一.实现延迟加载

    要实现延迟加载,其实只要在HasMany特性中使用Lazy=true就可以了。来看我们的Blog类是如何声明的:

    [ActiveRecord("Blogs")]

    public class Blog : ActiveRecordBase

    {

        
    private int _id;

     

        
    private String _name;

     

        
    private String _author;

     

        
    private IList _posts;

     

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

        }


        

     

        [HasMany(
    typeof(Post), Table="posts", ColumnKey="post_blogid",Lazy=true)]

        
    public IList Posts

        
    {

            
    get return _posts; }

            
    set { _posts = 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 );

        }


    }


    可以看到唯一与我们前面声明的Blog类不同的地方就在于下面这句话:

    [HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid",Lazy=true)]

    现在我们来写一个简单的测试代码:

    [Test]

    public void TestLazyLoad()

    {

        
    //找到Blog对象

        Blog blog 
    = Blog.Find(8);

        
    string resultName = blog.Name;

     

        
    //执行这句话的时候才载入Post对象

        
    int resultCount = blog.Posts.Count;

     

        
    string expectedName = "Terrylee";

        
    int expectedCount = 2;

     

        Assert.IsNotNull(blog);

        Assert.AreEqual(expectedName,resultName);

        Assert.AreEqual(expectedCount,resultCount);

    }


    测试,红灯!?报出了下面的错误:

    ARDemo.OneManyFixture.TestLazyLoad : NHibernate.LazyInitializationException : Failed to lazily initialize a collection - no session

    问题出在了我们得到Blog对象后,并没有把当前的Session保存下来,ActiveRecord在实现延迟载入时找不到一个NHibernateISession。为了保存当前的Session我们必须使用new SessionScope(),重新修改我们的测试代码之后:

    [Test]

    public void TestLazyLoad()

    {

        
    using(new SessionScope())

        
    {

            
    //找到Blog对象

            Blog blog 
    = Blog.Find(8);

            
    string resultName = blog.Name;

     

            
    //执行这句话的时候才载入Post对象

            
    int resultCount = blog.Posts.Count;

     

            
    string expectedName = "Tech Space";

            
    int expectedCount = 2;

     

            Assert.IsNotNull(blog);

            Assert.AreEqual(expectedName,resultName);

            Assert.AreEqual(expectedCount,resultCount);

        }
       

    }


    现在测试可以正常通过了,大家在使用延迟载入的时候不要忘了new SessionScope()

     

    二.使用Where子句

    ActiveRecord中实现稍微复杂的一点的查询,我们就不能用使用Find(id)FindAll()这两个静态的方法了,这时就需要使用HQL语句来实现,这个在后续文章中我会专门用一篇文章来介绍。我们也可以使用ActiveRecord来实现一些简单的查询,个人认为,这种查询把条件写在了特性里面,以一种硬编码的方式来实现,灵活性变得很差,使用的情况不是很多。看一个简单的例子,比如我们要查询某人发表的Category为“Castle”的Posts,可以在Blog实体类中添加一个CastlePosts的特性:

    [HasMany(typeof(Post),Table="posts", ColumnKey="post_blogid",Where="post_categories='Castle'")]

    public IList CastlePosts

    {

        
    get return _posts; }

        
    set { _posts = value; }

    }


    注意:在Where中写条件时所用的Posts表的字段名,而不是Post实体类对应的属性

    编写一个简单的测试代码:

    [Test]

    public void TestCondWhere()

    {

        
    //找到Blog对象

        Blog blog 
    = Blog.Find(8);

        

        
    //获取Castle的Posts数量

        
    int resultCount = blog.CastlePosts.Count;

     

        
    int expectedCount = 2;

     

        Assert.IsNotNull(blog);

        Assert.AreEqual(expectedCount,resultCount); 

    }

     

    这里我们调用CastlePosts得到的就是CategoryCastlePosts。关于延迟加载和使用Where子句就介绍到这儿了。下篇文章介绍如何在RectiveRecord中验证输入数据的有效性。

     

     

    参考资料

    Castle的官方网站http://www.castleproject.org

  • 相关阅读:
    英文综述如何写6
    英文综述如何写5
    英文综述如何写4
    英文综述如何写3
    英文综述如何写2
    英文综述如何写
    Python开发【第三篇】:Python基本数据类型
    Python开发【第二篇】:初识Python
    Python开发【第一篇】:目录
    第二十单元 计划任务crond服务
  • 原文地址:https://www.cnblogs.com/Terrylee/p/371513.html
Copyright © 2011-2022 走看看