【问题标题】:NHibernate - selecting data from referenced objects (traversing many-to-one relationship) in a queryNHibernate - 从查询中的引用对象(遍历多对一关系)中选择数据
【发布时间】:2014-04-09 12:44:15
【问题描述】:

我想构建一个查询,该查询将从连接表中选择一些列(我的数据模型中的多对一关系)。

var q = ses.QueryOver<Task>().Select(x => x.Id, x => x.CreatedDate, x => x.AssigneeGroup.Name, x => x.AssigneeGroup.IsProcessGroup);

在这里,我从 AssigneeGroup 检索属性,这是对另一个表的引用,在我的映射中指定。但是当我尝试运行这个查询时,我得到了

异常:无法解析属性:AssigneeGroup.Name of:Task

所以看起来 NHibernate 无法遵循我的映射中定义的关系,并且不知道为了解析 AssigneeGroup.Name 我们应该从“Task”连接到“Groups”表并检索 Group.Name柱子。 所以,我的问题是,如何构建这样的查询?我有这个表达式:x => x.AssigneeGroup.Name,如何将其转换为正确的标准、投影和别名?或者有没有办法自动做到这一点?这应该是可能的,因为 NHibernate 拥有所有的信息......

【问题讨论】:

  • 如果您将其编写为 Criteria 查询,则可以将 SetFetchMode 方法与 Join 结合使用,这样您就可以了。

标签: c# nhibernate criteria


【解决方案1】:

您的查询需要关联,应如下所示:

// firstly we need to get an alias for "AssigneeGroup", to be used later
AssigneeGroup assigneeGroup = null;

var q = ses
    .QueryOver<Task>()
    // now we will join the alias
    .JoinAlias(x => x.AssigneeGroup, () => assigneeGroup) 
    .Select(x => x.Id
          , x => x.CreatedDate

          // instead of these
          // , x => x.AssigneeGroup.Name
          // , x => x.AssigneeGroup.IsProcessGroup

          // use alias for SELECT/projection (i.e. ignore "x", use assigneeGroup)
          , x => assigneeGroup.Name
          , x => assigneeGroup.IsProcessGroup
     );

更多有趣的阅读:

【讨论】:

  • 这可能是正确的答案。不幸的是,NHIbernate 无法遵循 x.AssigneeGroup.Name 之类的属性链,您必须创建一个别名来告诉它 AssigneeGroup 是一个被引用的实体。但是 NH 有这些信息,它就在映射中,所以很遗憾你必须手动执行此操作。
  • 我知道你在说什么。我也错过了它......(如果这是“xyz”链的一部分......为什么NHibernate不创建关联?我同意......;)但这就是NHibernate现在的工作方式...... r
【解决方案2】:

如果您希望从根表/实体(在我们的例子中为Task)以外的其他内容中选择列,则必须连接这两个表。

这是一个例子:

IQueryOver<Cat,Kitten> catQuery =
    session.QueryOver<Cat>()
        .JoinQueryOver<Kitten>(c => c.Kittens)
            .Where(k => k.Name == "Tiddles");

Cat catAlias = null;
Kitten kittenAlias = null;

IQueryOver<Cat,Cat> catQuery =
    session.QueryOver<Cat>(() => catAlias)
        .JoinAlias(() => catAlias.Kittens, () => kittenAlias)
        .Where(() => catAlias.Age > 5)
        .And(() => kittenAlias.Name == "Tiddles");

您也可以使用 nhibernate linq 提供程序 (nh > 3.0):

var q = ses.Query<Task>()
           .Select(x => new 
           { 
               Id = x.Id, 
               CreatedDate = x.CreatedDate, 
               Name = x.AssigneeGroup.Name, 
               IsProcessGroup = x.AssigneeGroup.IsProcessGroup
           });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多