NHibernate,映射一个集合,其中键可以是两个不同的列

有一个实体A.

此外,还有一个实体B ,它与A有两个关联。

A有一个B的集合。

如果关联的A之一是加载的A的父级,则此集合必须加载任何B.

问题是A集合映射必须基于检查两个A关联中的一个是否是父关联来过滤子项。

我怎样才能做到这一点?

注意:顺序无关紧要,因此您可以使用bag建议一些映射。

注意2:请建议如何使用XML映射实现这一点,我不会在代码中执行此操作。

更新:真实场景:

这是关于友谊实施的全部内容。 我想在实体UserProfile中映射友谊的集合。 友谊有两个表示关系的关联:OneUser,OtherUser。 如果我想让所有朋友都能找到我,我需要检查这两个属性,因为如果其中一个属性是我自己,那么我的朋友就是我的朋友。

如果您愿意将解决方案略微移出数据域,则您的用户可以与他们分配为朋友的其他用户建立一对多的关系。 如果您不希望它泄露,这可能是protectedprivate

然后,您实现一个公共属性,该属性将实际的友谊定义为需要双向关系。 也许是这样的:

 public List Friends { this.assignedFriends.Where(f => f.assignFriends.Contains(this)).ToList(); } 

如果您这样做,您将需要确保使用二级缓存forms,否则对此属性的请求将破坏您的数据库。


如果您需要返回专用Friendship对象的集合,则取决于您如何持久保存这些条目以及如何映射该类。

一种选择是将Friendship定义为只有三列,一个主键和两个外键返回到User表。 每当有人试图添加朋友时,您需要一些逻辑:首先需要检查一半的关系是否已经存在。

 var f = session.Query() .Where(x => x.User1 == YourCurrentUser) .Cacheable() .FirstOrDefault(); 

然后,如果它存在,你分配关系的另一半

 f.User2 = TheOtherUser; 

否则创建一个新对象:

 f = new Friendship(); f.User1 = YourCurrentUser; 

在任何一个分支之后:

 session.SaveOrUpdate(f); 

那么User的朋友就变成了

 public property List { session.Query() .Where(f => f.User1 != null && f.User2 != null && (f.User1 == this || f.User2 == this) ).Cacheable() .ToList(); } 

请注意,我不在我的VS安装附近。 请原谅错别字或者我是否犯了明显的错误错误(早上2:30我在哪里)

这不是一个真正的答案,但我需要能够格式化并且没有字符限制。

我有同样的问题,但由于解决方案不是很容易,我决定通过修改我的结构来解决它。

我看到的一些看起来很有希望的东西是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

以及本地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,这违背了子查询的目的。

我见过另一个post,其中提供了另外两个解决方案。

  1. 创建两个子集合。 一个映射当前用户是主要朋友的朋友,另一个映射当前用户是次要朋友。 然后,您可以创建一个属性,在NH查询它之外将它们合并在一起。

  2. 在数据库中创建冗余条目,以便每个用户都有一个条目,其中它是与其他人共享的所有关系的PrimaryUser。

基于这两个选项 – 我可能会选择选项#1。