0

エンティティAがあります。

さらに、Aと2つの関連付けを持つエンティティBがあります。

AにはBのコレクションがあります。

関連するAの1つがロードされたAの親である 場合、このコレクションは任意のBをロードする必要があります。

問題は、 Aのコレクションマッピングが、2つのAアソシエーションの1つが親アソシエーションであるかどうかのチェックに基づいて子をフィルタリングする必要があることです。

どうすればそれを達成できますか?

注:順序は重要ではないため、bagを使用してマッピングを提案できます。

注2:XMLマッピングを使用してそれを実現する方法を提案してください。コードでは行いません。

更新:実際のシナリオ:

それはすべて友情の実装についてです。フレンドシップのコレクションをエンティティUserProfileにマップしたいと思います。友情には、関係を表す2つの関連付けがあります。OneUser、OtherUserです。すべての友達を取得したい場合は、両方のプロパティを確認する必要があります。両方のプロパティのいずれかが自分自身である場合、一方が私の友達だからです。

4

2 に答える 2

1

これは実際には答えではありませんが、文字制限がなく、フォーマットできるようにする必要がありました。

私はこれと同じ問題を抱えていましたが、解決策があまり簡単ではなかったため、代わりに構造を変更することで回避することにしました。

私が調べた中で有望だと思われたのは、Queryover を介して結合されたエイリアスとしてオブジェクトを返す SQLQueries でした。

または - 「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 から Alias を作成して、それに応じて 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

クエリは、サブクエリの目的に反して、UserID が外部の userId と等しくなければならないという追加の制約を where 句に入れ続けているため、うまく機能しません。

他の 2 つのソリューションが提供されている別の投稿を見たことがあります。

  1. 2 つの子コレクションを作成します。1 つは、現在のユーザーがプライマリ フレンドであるフレンドと、現在のユーザーがセカンダリ フレンドであるフレンドをマップするものです。次に、NH がクエリを実行する方法以外で、これらをマージするプロパティを作成できます。

  2. データベースに冗長なエントリを作成して、各ユーザーが他のユーザーと共有するすべての関係の PrimaryUser であるエントリを持つようにします。

これら 2 つのオプションに基づいて、おそらくオプション 1 を選択します。

于 2012-01-02T13:14:28.703 に答える
1

ソリューションをデータ ドメインから少しだけ移動する場合、ユーザーは、友人として割り当てた他のユーザーと 1 対多の関係を持つことができます。これは、protectedまたはprivate漏れたくない場合に発生する可能性があります。

次に、実際の友情を両方向の関係を必要とするものとして定義するパブリック プロパティを実装します。たぶん次のようなもの:

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

ただし、これを行う場合は、第 2 レベルのキャッシュの形式を使用していることを確認する必要があります。そうしないと、このプロパティへのリクエストがデータベースに打撃を与えます。


代わりに専用オブジェクトのコレクションを返す必要がある場合は、Friendshipそれらのエントリを永続化する方法とそのクラスをどのようにマップしたかによって異なります。

1 つのオプションはFriendship、単純に 3 つの列、1 つの主キー、および 2 つの外部キーを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);

その後、Usersの友達は次のようになります

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 に答える