Castle ActiveRecord学习实践(6):延迟加载和使用Where子句
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://terrylee.blog.51cto.com/342737/67664 |
摘要:在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在实现延迟载入时找不到一个NHibernate的ISession。为了保存当前的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; }![]() }编写一个简单的测试代码:
[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得到的就是Category为Castle的Posts。关于延迟加载和使用Where子句就介绍到这儿了。下篇文章介绍如何在RectiveRecord中验证输入数据的有效性。 本文出自 “TerryLee技术专栏” 博客,请务必保留此出处http://terrylee.blog.51cto.com/342737/67664 本文出自 51CTO.COM技术博客 |









}
}
lihuijun
博客统计信息
热门文章
最新评论
友情链接
