从所有表中获取数据而不是使用HQL查询获取数据,该数据只能获取1个表的数据

时间:2010-01-16 05:00:22

标签: c# nhibernate fluent-nhibernate hql

我在数据库中创建了3个表并将数据放入其中。 3个表都有外键将它们连接在一起。下面是表类和映射。当我运行最后列出的查询时,我得到IList<>对象,他们有来自所有3个表的数据。但是,我的HQL查询仅来自最顶层的表。我怎样才能从最顶层的表中得到结果?

这些是我的课程:

public class Technology
{
    public virtual int Id { get; private set; }
    public virtual string Name { get; set; }
    public virtual int SortOrder { get; set; }
    public virtual string Abbreviation { get; set; }
    public virtual IList<TechnologyDescription> TechnologyDescriptions { get; private set; }

    public Technology()
    {
        TechnologyDescriptions = new List<TechnologyDescription>();
    }

    public virtual void AddTechnologyDescription(TechnologyDescription technologyDescription)
    {
        technologyDescription.Technology = this;
        TechnologyDescriptions.Add(technologyDescription);
    }
}

public class TechnologyDescription
{
    public virtual int Id { get; private set; }
    public virtual Technology Technology { get; set; }
    public virtual string Description { get; set; }
    public virtual DescriptionType DescriptionType { get; set; }
}

public class DescriptionType
{
    public virtual int Id {get; private set;}
    public virtual string Type { get; set; }
}

These are my mapping objects:

public class TechnologyMap : ClassMap<Technology>
{
    public TechnologyMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        Map(x => x.SortOrder);
        Map(x => x.Abbreviation);
        HasMany(x => x.TechnologyDescriptions)
                .Inverse()
                .Cascade.All();
    }
}

public class TechnologyDescriptionMap  : ClassMap<TechnologyDescription>
{
    public TechnologyDescriptionMap()
    {
        Id(x => x.Id);
        References(x => x.Technology);
        Map(x => x.Description);
        References(x => x.DescriptionType);
    }
}

public class DescriptionTypeMap : ClassMap<DescriptionType>
{
    public DescriptionTypeMap()
    {
        Id(x => x.Id);
        Map(x => x.Type);
    }
}

这是我的HQL代码:

IQuery q = session.CreateQuery("from Technology T");
IList technologies = q.List();

2 个答案:

答案 0 :(得分:1)

我不知道是否可以使用HQL,但使用NHibernate的Criteria API,你可以这样做:

ICriteria criteria = session.CreateCriteria (typeof(Technology));

criteria.SetFetchMode ("TechnologyDescriptions", FetchMode.Lazy);

var list = criteria.List<Technology>();

但是,这可能不是你想要的。现在不会提取TechnologyDescriptions,但是一旦访问它们就会被提取(即:第一次调用TechnologyDescriptions属性时)。

使用NHibernate时,不应该考虑“数据”。相反,你应该用“实体”来思考 检索实体时,您希望直接(直接或以懒惰方式)检索实体。部分检索实体是不可能的,这是非常明显的; 当你试图保存那个实体时,NHibernate应该对你部分检索过的实体做些什么?

在我脑海中浮现的其他东西: 我想你想要检索技术,没有任何相关因为你想在概述或类似的东西中显示它们? 在这种情况下,您应该看看'转换'。 例如,您可以创建一个名为TechnologyView的附加类,如下所示:

public class TechnologyView
{
    public int Id
    {
        get;
        private set;
    }

    public string Name
    {
        get;
        private set;
    }

    public string Abbreviation
    {
        get;
        private set;
    }

    private TechnologyView()
    {
       // Private constructor, required for NH
    }

    public TechnologyView( int id, string name, string abbreviation )
    {
       this.Id = id;
       this.Name = name;
       this.Abbreviation = abbreviation;
    }
}

完成此操作后,您必须告知NHibernate此课程的存在。 例如,您可以通过在hbm.xml文件中导入类来完成此操作。 (我不知道如何使用Fluent)。

<import class="MyNamespace.TechnologyView" />

之后,您可以创建一个查询(使用HQL或Criteria)来检索TechnologyView个实例。 NHibernate非常智能,可以生成高性能的SQL查询。

使用HQL:

IQuery q = s.CreateQuery ("select new TechnologyView (t.Id, t.Name, t.Abbreviation) from Technology t");

使用标准:

ICriteria criteria = s.CreateCriteria (typeof(Technology));
criteria.SetResultTransformer (Transformers.AliasToBean (typeof(TechnologyView));
var result = criteria.List<TechnologyView>();

答案 1 :(得分:1)

我认为您正在寻找的是延迟加载TechnologyDescriptions。这样,只有在访问它们时才会从数据库加载描述(NHibernate将发出第二个数据库查询。请注意,在某些情况下这可能会导致N + 1选择,您可能更喜欢根据使用情况一次性查询。 )

通过NHibernate xml映射默认为延迟加载集合。在过去,似乎Fluent NHibernate没有相同的默认值。您需要将.LazyLoad()添加到映射中。

最近看起来延迟加载已成为默认的流畅映射: Is the default behavior with Fluent NHibernate to lazy load HasMany<T> collections?