2014-09-12 77 views
2

我有两个实体:QueryOver使用忽略属性

public class Parent 
{ 
    public virtual int Id { get; set; } 
} 

public class Child 
{ 
    public virtual int Id { get; set; } 
    public virtual int ParentId 
    { 
     get 
     { 
      if (Parent != null) 
       return Parent.Id; 
      return -1; 
     } 

     set 
     { 
      if (Parent != null) 
       Parent = new Parent(); 
      Parent.Id = value; 
     } 
    } 

    protected virtual Parent Parent 
    { 
     get; 
     set; 
    } 
} 

Parent属性设置像这样简化API的一面,我不想改变它公开揭露这个属性。我有映射的重写为Child类,以适应这一点:

public class ChildMappingOverrides : IAutoMappingOverride<Child> 
{ 
    public void Override(AutoMapping<Child> mapping) 
    { 
     mapping.References<Parent>(Reveal.Member<Child>("Parent")).Column("Parent_id"); 
     mapping.IgnoreProperty(x => x.ParentId); 
    } 
} 

现在,如果我想查询所有Child对象对于一个给定父ID,我会执行此:

session.QueryOver<Child>().Where(c => c.ParentId == 1); 

然而,这将引发一个QueryException

无法解析属性:的的ParentId:My.Namespace.Child

如何检索具有特定Parent ID的一组Child对象?

回答

2

未经检验的,但你可以试试这个:

session.QueryOver<Child>() 
    .Where(Restrictions.Eq(
     Projections.SqlProjection(
      "{alias}.Parent_id as ParentId", 
      new[] { "ParentId" }, 
      new[] { NHibernateUtil.Int32 }), 1)) 
    .List<Child>(); 

你不会要能够在任何NHibernate的查询上映射的关联查询,但这次至少最大限度地减少编译时检查的损失。

这与我所能说的有些有限。 {alias}将始终替换为实体的别名,这意味着如果您希望对不是以Child开头的更复杂的查询执行此操作,那么您可能会失败。

+0

我更喜欢这个:)谢谢安德鲁,它与我做的一个小小的调整,只是为了匹配我的例子中的列名称。 – 2014-09-12 19:31:50

+0

@PatrickQuirk:没问题 - 我希望有一种更坚实的方式来做你以后的事情 – 2014-09-12 19:32:29

0

我用CreateSQLQuery代替QueryOver解决它:

session.CreateSQLQuery("SELECT C.* FROM CHILD C WHERE C.Parent_id = (:id)") 
     .AddEntity(typeof(Child)) 
     .SetInt32("id", parentId) 
     .List<Child>(); 

我想看到一个更好的方式,如果可能的话,失去编译时检查是一种令人沮丧的。