0

有一个实体A

此外,还有一个实体BA有两个关联。

A有一个集合B

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

问题是 A 上的集合映射必须根据检查两个A关联之一是否是父关联来过滤子项。

我怎样才能做到这一点?

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

注 2:请建议如何使用 XML 映射来实现,我不会在代码中这样做。

更新:真实场景:

这都是关于友谊的实施。我想在实体 UserProfile 中映射友谊的集合。Friendship 有两个代表关系的关联:OneUser、OtherUser。如果我想为我获取所有朋友,我需要检查这两个属性,因为如果两个属性之一是我自己,一个是我的朋友。

4

2 回答 2

1

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

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

我看到的几件看起来很有希望的事情是 SQLQueries,它以通过 Queryover 连接的别名形式返回对象。

或者 - 将 .Where 子句添加到“hasMany”映射。我所读到的有关此选项的所有内容都表明它非常有限。尽管执行您所要求的逻辑似乎很简单-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,这违背了子查询的目的。

我看过另一篇文章,其中提供了另外两种解决方案。

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

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

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

于 2012-01-02T13:14:28.703 回答
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)

于 2012-01-02T15:40:35.897 回答