程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Castle ActiveRecord學習實踐(6) 延遲加載和使用Where子句

Castle ActiveRecord學習實踐(6) 延遲加載和使用Where子句

編輯:關於.NET

摘要:在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; }
}

注意:在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得到的就是Category為Castle的Posts。關於延遲加載和使用Where子句就介紹到這兒了。下篇文章介紹如何在RectiveRecord中驗證輸入數據的有效性。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved