2011-05-26 89 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