【问题标题】:Getting Data from all tables instead of one with HQL Query that should only get 1 table's data从所有表中获取数据,而不是使用 HQL 查询获取数据,而 HQL 查询应该只获取 1 个表的数据
【发布时间】:2010-01-16 05:00:22
【问题描述】:

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

【问题讨论】:

  • 谢谢你们俩。你的回答帮助了我。谢谢!

标签: c# nhibernate fluent-nhibernate hql


【解决方案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" />

之后,您可以创建一个检索 TechnologyView 实例的查询(使用 HQL 或 Criteria)。 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>();

【讨论】:

  • 这确实有帮助。我想澄清一件事,也许这就是我迷路的地方。我不希望我的每项技术的 TechnologyDescription 表中的所有数据都是因为某些描述与我所在的页面无关。但是,如果我对您的理解正确,那么我想通过我如何循环通过技术实体来删除/忽略这些结果。这确实让我觉得很奇怪,因为这意味着没有理由使用查询字符串,因为在那之后一切都会完成。
  • 我不太明白你的评论。如果您根本不需要当前页面上的描述,我会选择“转换”方法。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2012-03-13
    • 1970-01-01
    • 2015-04-25
    • 2016-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    相关资源
    最近更新 更多