2011-05-26 81 views
0

請原諒我的無知屬性Flitering對象子集,我是新來NHibernate和我有一個概念性的問題試圖與NHibernate的查詢過濾的子集使用功能NHibernate

我的對象模型包含兩個實體:用戶和任務設置這樣

public class User 
{ 
    public User() 
    { 
     this.Tasks = new List<Task>(); 
    } 

    public User(int id): this() 
    { 
     this.Id = id; 
    } 

    public virtual int Id { get; private set; } 

    public virtual IList<Task> Tasks { get; set; } 
} 

public class Task 
{ 
    public Task() { } 

    public Task(int id, bool active): this() 
    { 
     this.Id = id; 
     this.Active = active; 
    } 

    public virtual int Id { get; set; } 

    public virtual bool Active { get; set; } 
} 

我NHibernate的映射現報告如下

public class UserMap: ClassMap<User> 
{ 
    public UserMap() 
    { 
     Table("user"); 
     Id(x => x.Id); 
     HasMany(x => x.Tasks); 
    } 
} 

public class TaskMap : ClassMap<Task> 
{ 
    public TaskMap() 
    { 
     Table("task"); 
     Id(x => x.Id); 
     Map(x => x.Active); 
    } 
} 

我的數據庫中具有T WO表「任務」和我所正是如此充滿

SELECT * FROM task; 
+----+--------+---------+ 
| Id | Active | User_id | 
+----+--------+---------+ 
| 1 |  1 |  3 | 
| 2 |  1 |  3 | 
| 3 |  1 |  3 | 
| 4 |  0 |  3 | 
| 5 |  0 |  3 | 
| 6 |  1 |  1 | 
| 7 |  1 |  1 | 
| 8 |  1 |  1 | 
| 9 |  0 |  1 | 
| 10 |  0 |  1 | 
+----+--------+---------+ 
10 rows in set 

SELECT * FROM user; 
+----+ 
| Id | 
+----+ 
| 1 | 
| 2 | 
| 3 | 
| 4 | 
| 5 | 
+----+ 
5 rows in set 

「用戶」什麼,我試圖做的是運行返回一個特定的用戶只用它的「任務」收集

在活動任務查詢
var query = QueryOver.Of<User>() 
    .Where(u => u.Id == 3) 
    .JoinQueryOver<Task>(x => x.Tasks) 
    .Where(t => t.Active == true); 

var results = dataProvider.ExcecuteQuery<User>(query); 

當我執行此查詢時,我期望在其Tasks集合中取回帶有3個Task對象的單個用戶對象,而我得到的是相同任務對象(task.Id = 3)的3個副本,所有這些對象都有所有5個任務在他們各自的集合中。

是我正在嘗試做的事實上可能或者我應該只是查詢任務實體呢?

我希望事實並非如此,因爲只要能夠看到用戶的活動任務而不必亂搞手動過濾就好了。

+0

這個問題的http://計算器。 com/questions/5790153/nhibernate-filtering-out-results-based-child-property看起來表面上相似,但我似乎看不到我能夠理解的問題的答案 – Willbill 2011-05-26 14:28:58

回答

0

首先,我想我會分解成兩個查詢。在製作主細節時,獲取用戶實體可能更有意義,然後獲取用戶的任務...

我不是很好,但使用QueryOver.Of<T>(),但使用session.QueryOver<T>()可以這樣做:

 var users = session.QueryOver<User>() 
      .Where(u => u.Id == 3) 
      .Fetch(o => o.Tasks) 
      .Lazy() 
      .SingleOrDefault(); 

     users.Tasks.TakeWhile(o => o.Active); 

我想你也可以使用過濾器,但它聽起來不像你想要做的。我不認爲QueryOver.Of<T>()做你想做的,因爲斷開連接的查詢將需要一個過濾器正確拉回子元素。

0

您可以在List()方法之前申請.TransformUsing(Transformers.DistinctRootEntity)以獲得僅1個用戶對象。 之後,你所看到的是發出另一個查詢到數據庫來獲取該用戶的任務列表(沒有過濾活動的),這就是延遲加載的含義。 在您的db config部分添加.ShowSql().FormatSql()以查看發生了什麼。

你也可以將此屬性添加到您的Task

public virtual User User { set; get; } 

爲有這樣的疑問:(你首先想要什麼)

var list = session.QueryOver<Task>()               
          .Fetch(t=>t.User).Eager 
          .Where(t => t.Active && t.User.Id==3) 
          .TransformUsing(Transformers.DistinctRootEntity) 
          .List(); 
+0

將User實體添加到Tasks實體中一個不錯的主意。 – cloggins 2011-05-27 10:01:22