有一个实体 A 。
此外,还有一个实体 B ,它与 A 有两个关联。
包含 B 的集合。
如果关联的 A 之一是已加载的的父级,则此集合必须加载任何 B A
问题是 上的集合映射必须根据检查两个 A 关联中的一个是否过滤来过滤子项父母一个。
我怎样才能做到这一点?
注意:订单无关紧要,因此您可以使用包建议一些映射。
注意2:请建议如何使用XML映射实现这一点,我不会在代码中实现。
更新:真实场景:
这是关于友谊实施的全部内容。我想在实体UserProfile中映射友谊的集合。友谊有两个表示关系的关联:OneUser,OtherUser。如果我想要让所有朋友都能找到我,我需要检查这两个属性,因为如果其中一个属性是我自己,那么我的朋友就是我的朋友。
答案 0 :(得分:1)
这不是一个真正的答案,但我需要能够格式化并且没有字符限制。
我有同样的问题,但由于解决方案不是很容易,我决定通过修改我的结构来解决它。
我看到的一些看起来很有希望的东西是SQLQueries,它将对象作为通过Queryover加入的别名返回。
或者 - 在“hasMany”映射中添加.Where子句。我读到的关于这个选项的一切都说它非常有限。虽然做你所要求的逻辑似乎很简单 - Select Distinct ... From ... Where (OneUser = UserId or OtherUser = UserId)
修改强>
在这里查看JoinQueryOver:http://nhibernate.info/blog/2009/12/17/queryover-in-nh-3-0.html
此处的Native SQL查询:http://knol.google.com/k/nhibernate-chapter-14-native-sql#
虽然这不是映射级解决方案,但您可以在选择用户时在where子句中指定条件,以便正确填充其好友。如果您无法通过Fluent QueryOver实现所需的过滤,我认为您可以使用Native SQL查询创建别名,并使用JoinQueryOver / JoinAlias来相应地填充Friends集合。
如果这是您已经知道的所有信息,我道歉。无论哪种方式 - 我有兴趣看到这个问题的解决方案。
**编辑2:** 我玩了一下它,这就像我能得到它一样接近:
Public Class UserMapping
Inherits ClassMap(Of User)
Public Sub New()
Id(Function(x) x.Id).Column("UserID")
Map(Function(x) x.Name).Length(50).Not.Nullable().Column("UserName")
HasMany(Function(x) x.Friends).Inverse.KeyColumn("UserID").Where("Users.UserID in (select Friendships.FriendOne from Friendships where Friendships.FriendTwo = UserID) or UserID in (select Friendships.FriendTwo from Friendships where Friendships.FriendOne = UserID)")
Table("Users")
End Sub
End Class
查询不能正常工作,因为它继续在where子句中添加一个额外的约束,UserID需要等于外部userId,这违背了子查询的目的。
我见过另一个帖子,其中提供了另外两个解决方案。
创建两个子集合。一个映射当前用户是主要朋友的朋友,另一个映射当前用户是次要朋友。然后,您可以创建一个属性,在NH查询它之外将它们合并在一起。
在数据库中创建冗余条目,以便每个用户都有一个条目,其中它是与其他人共享的所有关系的PrimaryUser。
基于这两个选项 - 我可能会选择选项#1。
答案 1 :(得分:1)
如果您愿意将解决方案略微移出数据域,则您的用户可能与他们指定为朋友的其他用户建立了一对多的关系。如果您不希望它泄露,可以是protected
或private
。
然后,您实施一个公共属性,将实际的友谊定义为需要双向关系。也许是这样的:
public List<User> Friends {
this.assignedFriends.Where(f => f.assignFriends.Contains(this)).ToList();
}
如果您这样做,您将需要确保使用二级缓存形式,否则对此属性的请求将破坏您的数据库。
如果您需要返回专用Friendship
对象的集合,则取决于您如何持久保存这些条目以及如何映射该类。
一个选项是将Friendship
定义为只有三列,一个主键和两个外键返回User
表。每当有人试图添加朋友时,您需要一点逻辑:首先需要检查一半的关系是否已经存在..
var f = session.Query<Friend>()
.Where(x => x.User1 == YourCurrentUser)
.Cacheable()
.FirstOrDefault();
然后如果它存在,则分配关系的另一半
f.User2 = TheOtherUser;
否则创建一个新对象:
f = new Friendship();
f.User1 = YourCurrentUser;
并在任何一个分支之后:
session.SaveOrUpdate(f);
然后User
的朋友变成
public property List<Friendship> {
session.Query<Friendship>()
.Where(f =>
f.User1 != null && f.User2 != null
&& (f.User1 == this || f.User2 == this)
).Cacheable()
.ToList();
}
请注意,我不在我的VS安装附近。请原谅错别字,或者我是否犯了明显的错误(早上2:30,我原来是这样)