我开始怀疑我实际上是不是太愚蠢而无法使用NHibernate。我目前正在使用FluentNHibernate来创建简单的db映射,这对我们来说效果很好。当我们孤立地处理各种类时,我们能够对所有这些类进行读写,执行更新等。然而,我的问题是尝试构建一个涉及比过滤实体类型字段更复杂的查询。下面举例说明了一个完美的例子 -
映射的相关部分:
public class UserMap : ClassMap<User> {
Id(u => u.Id).Column("UserID").GeneratedBy.Identity();
//other non-pertinent fields
}
public class RoleMap : ClassMap<Role> {
Id(r => r.Id).Column("RoleId").GeneratedByIdentity();
//snip
}
public class RoleMapMap : ClassMap<RoleMap> {
Id(rm => rm.Id).Column("RoleMapId").GeneratedByIdentity();
Map(rm => rm.UserId);
Map(rm => rm.RoleId);
//snip
}
目的是生成一个带有Criteria API的查询,以检索特定角色的所有用户 - 在较高级别,根据特定角色ID过滤角色图,然后加入用户,并仅返回这些用户。
尝试使用以下内容,但我对CreateAlias的使用明显存在缺陷,因为运行时异常基本上告诉我它不知道下面的“RoleMap”与User对象有什么关系。
var criteria = session.CreateCriteria<User>().
CreateAlias("RoleMap", "rm").
Add(Expression.Eq("rm.UserId", "UserId")).
Add(Expression.Eq("rm.RoleId", 99)).
SetResultTransformer(new
DistinctRootEntityResultTransformer());
var users = criteria.List<User>();
有人能指出我正确的方向吗?我不希望编辑底层对象来公开集合 - (例如User.Roles []集合),因为在某些情况下我们专门有用于连接的表但我们不希望浮动到中间层。所以学习如何加入孤立的课程对我们来说很重要。
答案 0 :(得分:4)
您的映射无法从User导航到RoleMap,但这是您在Criteria API调用中尝试执行的操作。你有多种选择。这是一对夫妇:
1)允许用户在映射中导航到RoleMap。这是最简单的以及通常如何完成。
2)使用两个查询,一个用于获取基于RoleMap to Role关系的UserIds列表,然后是第二个查询以获取这些UserIds的所有用户。
您说您不希望在中间层中使用User.Roles集合,但NHibernate应该存在于您的数据层中,而不一定是您的业务层。您可以允许NHibernate了解User.Roles,同时有效地将其隐藏在业务层中。
加入隔离的类并不是真正构建ORM的。 ORM是为加入相关类而构建的。相关类通常映射到数据库级别的相关表。要加入隔离的类,您需要执行上面的选项2,您可以运行多个查询和/或解决自定义代码中缺少关系的问题。