我在数据库中创建了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();
答案 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?