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

  • 相关阅读:
    重新想象 Windows 8 Store Apps (15) 控件 UI: 字体继承, Style, ControlTemplate, SystemResource, VisualState, VisualStateManager
    重新想象 Windows 8 Store Apps (12) 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示
    返璞归真 asp.net mvc (10) asp.net mvc 4.0 新特性之 Web API
    与众不同 windows phone (29) Communication(通信)之与 OData 服务通信
    与众不同 windows phone (33) Communication(通信)之源特定组播 SSM(Source Specific Multicast)
    与众不同 windows phone (27) Feature(特性)之搜索的可扩展性, 程序的生命周期和页面的生命周期, 页面导航, 系统状态栏
    与众不同 windows phone (30) Communication(通信)之基于 Socket TCP 开发一个多人聊天室
    返璞归真 asp.net mvc (12) asp.net mvc 4.0 新特性之移动特性
    重新想象 Windows 8 Store Apps (2) 控件之按钮控件: Button, HyperlinkButton, RepeatButton, ToggleButton, RadioButton, CheckBox, ToggleSwitch
    重新想象 Windows 8 Store Apps (10) 控件之 ScrollViewer 特性: Chaining, Rail, Inertia, Snap, Zoom
  • 原文地址:https://www.cnblogs.com/Terrylee/p/371513.html
Copyright © 2011-2022 走看看