【问题标题】:NHibernate Left Outer Join Unrelated EntitiesNHibernate 左外连接不相关实体
【发布时间】:2010-09-20 15:35:20
【问题描述】:

我有 2 个实体角色和翻译。
角色 -> Role_ID、代码
翻译 -> 代码、语言、名称

这个想法是说某个角色,它有英文名,法文名等等。
例如:
Role(1, 'Rol_001') 可以具有以下关系:Translation('Rol_001', 'English', '') & Translation('Rol_001', 'French', '')。

我想用 HQL 表达以下 SQL 查询:


select r.Role_ID, t.Name
from Role r left outer join Translation t 
   on r.Code = t.Code and t.Language = @lang;

在我的映射文件中,这两个实体之间没有任何关系,但以下 HQL 查询就像是内部联接一样工作


IQuery query = session.CreateQuery("select new Lookup(r.Role, t.Name) from Role r, Translation t where r.Code = r.Code and t.Language = :language");

如果我将 HQL 更改为左外连接,我会得到连接异常所需的路径。

您能帮我解决以下问题吗:
1- 我需要更改我的映射文件吗?
2- 如果我可以保持映射文件原样,如何在 HQL 中编写这样的查询?
3- HQL 是如何真正起作用的?为什么这样一个简单的外连接查询不起作用?我一定是在这里遗漏了什么!

编辑:
现在我根据使用 CreateSQL 的建议使用以下代码:


ISQLQuery query = session.CreateSQLQuery("select m.MedicineTypeID, t.Name, m.IsDeleted from MedicineType m left outer join Translation t on m.Code = t.Code and t.Language = :language");
query.SetString("language", language);
IList rawLookup = query.List();

IList medicineTypesLookup = new List(rawLookup.Count);
foreach (object[] lookup in rawLookup)
{
    medicineTypesLookup.Add(new Lookup((int)lookup[0], (string)lookup[1], (bool)lookup[2]));
}
return medicineTypesLookup;

这是可行的,但是我想使用 query.List() 直接获取结果,而不是自己进行转换。
我尝试使用query.AddEntity(typeof(Lookup));,但出现异常NHibernate.MappingException: No persister for: DAL.Domain.Lookup
Lookup 只是一个 POCO,不映射到任何数据库表。它的映射文件就是<import class="Lookup" />

【问题讨论】:

  • HQL 使用映射关系,而不是任意连接子句。您可以使用 SQL 来实现。
  • 这是一个 SQL Server CE,我可以直接使用 NHibernate 执行 SQL 语句还是使用 SqlCeConnection 和 SqlCeCommand 来执行 sql 语句并得到结果?
  • 我看到我可以使用 session.CreateSQLQuery 但是结果是一个 Object[]。我正在尝试找到一种方法来获得 IList. 的结果
  • 最后我使用 query.SetResultTransformer(Transformers.AliasToBean()).List(); 找到了答案
  • 现在可以使用 NHibernate v3.3.1 和 LINQ API。有关示例,请参见以下答案:stackoverflow.com/a/17586211/670028

标签: nhibernate left-join


【解决方案1】:

终于找到答案了:

ISession session = NHibernateHelper.Session;
ISQLQuery query = session.CreateSQLQuery("select m.MedicineTypeID as ID, t.Name, m.IsDeleted from MedicineType m left outer join Translation t on m.Code = t.Code and t.Language = :language");
query.setString("language", language);
IList lookup = query.SetResultTransformer(Transformers.AliasToBean()).List();
return lookup;
并且查找是一个带有无参数构造函数和 3 个属性 ID、Name 和 IsDeleted 的 POCO 类。

我要感谢 Kelly 和 Diego Mijelshon 的提示。尽管他们没有提供完整的答案,但使用 Session.CreateSqlQuery() 是一个非常有用的提示。

所以完整的解决方案是 Session.CreateSQLQuery 和 query.SetResultTransformer

注意:Transformers.AliasToBean() 是如此的 java。

编辑:http://docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/impl/SQLQueryImpl.htmlsetString() 的正确方法

【讨论】:

    【解决方案2】:

    您必须在映射中定义关系或执行子查询

    【讨论】:

    • 再次查看您的示例,您可能必须使用 2 个单独的查询(一个用于角色,一个用于语言),然后是一个进程中的 linq 左外连接。但是,这不是一个好的解决方案 IMO,你真的应该在映射中定义简单的关系或使用 session.CreateSqlQuery()。
    猜你喜欢
    • 2012-04-11
    • 2022-07-29
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    相关资源
    最近更新 更多