【问题标题】:How can I efficiently retrieve linked rows in NHibernate?如何有效地检索 NHibernate 中的链接行?
【发布时间】:2011-07-28 10:29:20
【问题描述】:

假设我的数据库中有这些表,这些表由 Web 服务 (WCF) 通过 NHibernate 查询:

Table "Patients"
  Column "Id"
  Column "LastName"
  Column "FirstName"
  Column "Age"

Table "Treatments"
  Column "Id"
  Column "PatientId"
  Column "Name"
  Column "IsActive"

患者可以接受任意数量的治疗。如果我想收集一份目前正在接受积极治疗的患者列表,我怎样才能在 NHibernate 中最有效地实现这一目标?

目前,我正在这样做(当然是使用 SetFirstResult() 和 SetMaxResults()):

var patientsWithTreatments = new List<PatientWithTreatments>();

var patients = Session.CreateCriteria<Patient>().List<Patient>();
foreach(Patient patient in patients) {
  patientsWithTreatments.Add(
    new PatientWithTreatments(patient) {
      Treatments = Session.CreateCriteria<Treatment>()
        .Add(Restrictions.Eq("PatientId", patient.Id)).List<Treatment>()
    }
  );
}

这涉及到结果集中每个患者的数据库往返,这是一个非常糟糕的主意。普通的 NHibernate 查询是否有一些魔力,或者我是否必须使用 HQL(我还没有牢牢掌握):)

【问题讨论】:

    标签: c# mysql database wcf nhibernate


    【解决方案1】:

    您基本上需要在 Patient 类中有一个名为 Treatments 的集合。在你的 nHibernate 映射中,你应该有类似的东西:

    <many-to-one name="Treatments" column="TreatmentID" class="Treatment" fetch="select" cascade="none"/>
    

    然后您可以通过以下方式检索患者的所有治疗:

    List<Treatment> treatments = yourPatient.Treatments;
    

    【讨论】:

    • 是的,这是一种选择。不过,我感兴趣的是,如果我不想在我的域类中公开关系(实际代码会使这有点困难),我想知道如何使用 NHibernate 的 Criteria API(或必要时的 HQL)来实现这一点因为关系超过了第二张表)
    • 您可以尝试使用 Aliases,然后在 Criteria 中使用 ProjectionList,但我不确定如果没有未映射的“治疗”,这是否可行。您总是可以只映射处理并将它们标记为“延迟加载”以提高效率。
    • 这样我就回到了第一个问题:每次延迟加载的处理都对数据库进行一次往返,这会将我的 0.5 秒查询变成一个需要几分钟才能完成的怪物......
    【解决方案2】:

    NHibernate 可以选择通过映射文件中的access="noop" 在幕后添加关系(意味着 NHibernate 知道它们但不暴露给代码)。

    这些可以像 HQL 中任何通常声明的关系一样使用。

    从 NHibernate 3.1.0 开始,对我来说,这有一点不方便的副作用,即在运行查询时从另一个表中完全删除所有引用的行,因此您可能需要在使用 @ 之前仔细检查987654322@ 在生产代码中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-17
      • 2018-11-22
      • 1970-01-01
      • 2014-04-03
      相关资源
      最近更新 更多