Nhibernate自联接读取连接字段值

时间:2014-02-03 00:50:22

标签: nhibernate fluent-nhibernate hql fluent-nhibernate-mapping self-join

我打算读取自我连接映射的引用字段(ParentMenu)值。类和映射如下;

public class MenuSetup
{
    public virtual int MenuId { get; set; }
    public virtual string DisplayText { get; set; }
    public virtual int MenuOrder { get; set; }
    public virtual bool MenuStatus { get; set; }
    public virtual bool HasKids { get; set; }

    public virtual MenuSetup Parent { get; set; }
    public virtual ICollection<MenuSetup> SubMenu { get; set; }
 }

下面的映射;

public MenuSetupMap()
    {
        Id(x => x.MenuId).GeneratedBy.Identity();
        Map(x => x.DisplayText);
        Map(x => x.MenuStatus);
        Map(x => x.MenuOrder);
        Map(x => x.HasKids);
        HasMany(x => x.SubMenu).KeyColumn("ParentMenu"); 
        References(x => x.Parent).Column("ParentMenu"); 
            .Cascade.AllDeleteOrphan()
            .Fetch.Join().Inverse().KeyColumn("MenuId");
    }

ParentMenu 字段我想这样读到我的视图模型HomeMenuViewModel中。

var session = MvcApplication.SessionFactory.GetCurrentSession();
string qry = @"select p.MenuId,p.DisplayText,p.MenuStatus,p.MenuOrder,
m from MenuSetup as p left join p.Parent m";
var vm=session.CreateQuery(qry).List<object[]>()
            .Select(x=>new HomeMenuViewModel()
            {
                 MenuId=(int)x[0], 
                 DisplayText=(string)x[1], 
                 MenuStatus=(Boolean)x[2], 
                 MenuOrder=(int)x[3],
                 ParentMenu = x[10] == null ? 0 : (int)x[10]
            }).ToList();

抛出错误“System.IndexOutOfRangeException未被用户代码处理”。我被困了,真的需要帮助。

从NHProf生成的查询如下所示;

   select menusetup0_.MenuId      as col_0_0_,
   menusetup0_.DisplayText as col_1_0_,
   menusetup0_.MenuStatus  as col_2_0_,
   menusetup0_.MenuOrder   as col_3_0_,
   menusetup1_.MenuId      as col_4_0_,
   menusetup1_.MenuId      as MenuId10_,
   menusetup1_.DisplayText as DisplayT2_10_,
   menusetup1_.MenuStatus  as MenuStatus10_,
   menusetup1_.MenuOrder   as MenuOrder10_,
   menusetup1_.HasKids     as HasKids10_,
   menusetup1_.ParentMenu  as ParentMenu10_
   from   [MenuSetup] menusetup0_
   left outer join [MenuSetup] menusetup1_
     on menusetup0_.ParentMenu = menusetup1_.MenuId

认真等待帮助。

谢谢

更新解决方案

我经过多次修补后找到了解决方案

我需要在MenuSetup类中声明字段,如下所示

public class MenuSetup
{
    .
    .
    public virtual int ParentMenu { get; set; }
    .
}

在Mapping类中,我也声明了列。

我的检索代码已更改为

var session = MvcApplication.SessionFactory.GetCurrentSession();
string qry = @"select p.MenuId,p.DisplayText,p.MenuStatus,p.MenuOrder,
              p.ParentMenu from MenuSetup as p";
var vm=session.CreateQuery(qry).List<object[]>()
        .Select(x=>new HomeMenuViewModel()
        {
             MenuId=(int)x[0], 
             DisplayText=(string)x[1], 
             MenuStatus=(Boolean)x[2], 
             MenuOrder=(int)x[3],
             ParentMenu = x[4] == null ? 0 : (int)x[4]
        }).ToList();

1 个答案:

答案 0 :(得分:1)

object[]项的数量与 HQL 查询相关,而与生成的 SQL 查询无关。即上述查询将返回包含5个元素的object[]

// the HQL Snippet
select 
p.MenuId,      // object[0]
p.DisplayText, // object[1]
p.MenuStatus,  // object[2]
p.MenuOrder,   // object[3]
m              // object[4]
from MenuSetup ....

所以,没有object[10] ...这就是为什么我们有System.IndexOutOfRangeException

5th元素是完整的父元素。解决方案应该是这样的:

ParentMenu = x[4] == null ? null : (MenuSetup)x[4]

注意:如果我们只使用父项中的一个属性,可能会更好,例如:将HQL更改为...m.DisplayText...