1

UserRavenDB にオブジェクトを格納します。それぞれUserUser.Idプロパティがあります。

次のように、メンター/メンティー関係を作成するために 2 つのをリンクするRelationshipクラスもあります。User.Id

public class User
{
    public string Id { get; set; }
    public string UserName { get; set; }
    ... more properties
}

public class Relationship
{
    public string Id { get; set; }
    public string MentorId { get; set; }
    public string MenteeId { get; set; }
    public RelationshipStatus Status { get; set; }
}

ここで、特定のメンターのメンティーのリストを取得したいと考えています。私は次の方法でこれを行いました:

public static List<User> GetMentees(IDocumentSession db, string mentorId)
{
    var mentees = new List<User>();
    db.Query<Relationship>()
            .Where(r => r.MentorId == mentorId)
            .Select(r => r.MenteeId)
            .ForEach(id => mentees.Add(db.Load<User>(id)));
    return mentees;
}

IDocumentSessionこれは問題なく動作しているように見えますが、私の肩に乗っているコーディング エンジェルは、 (db)のネストされた使用と、リストLoadを埋めるために複数の呼び出しが必要であることから発せられる臭いに鼻をすくめています。Mentees

ベスト プラクティスの RavenDB 構文を使用してこの方法を最適化するにはどうすればよいですか?

編集 データベースへの複数の呼び出しの問題を解決してくれた @Jonah Himango (以下の受け入れられた回答を参照) に感謝します。さらに、「Memoize」という新しい拡張メソッドを作成して、外部の「メンティー」結果リストを不要にしました (上記のコードを参照)。

これが最適化されたコードです。お気軽にコメントして、さらに絞り込んでください。

リンク

public static List<User> GetMentees(IDocumentSession db, string mentorId)
{
    return  db.Query<Relationship>()
            .Customize(x => x.Include<Relationship>(o => o.MenteeId))
            .Where(r => r.MentorId == mentorId)
            .Memoize()
            .Select(r => db.Load<User>(r.MenteeId))
            .ToList();
}

拡張方法

public static List<T> Memoize<T>(this IQueryable<T> target)
{
    return target.ToList();
}

ToList(): この拡張メソッドは完全に不必要に見えるかもしれません (実際にはそうです) が、リストを作成するためではなく、Linq ステートメントの実行を強制するために、という関数を呼び出さなければならないという私のオタク腺を苛立たせます。したがって、私の拡張メソッドの名前ToList()は、はるかに正確なMemoize().

4

1 に答える 1

1

.Include クエリのカスタマイズを使用して、Raven に各リレーションシップから関連するユーザー オブジェクトを含めるように指示します。

db.Query<Relationship>()
            .Customize(x => x.Include<Relationship>(o => o.MenteeId))
            .Where(r => r.MentorId == mentorId)
            .Select(r => r.MenteeId)
            .ForEach(id => mentees.Add(db.Load<User>(id))); // .Load no longer makes a call to the DB; it's already loaded into the session!

関連ドキュメントはこちら

Load() の呼び出しは完全にクライアント側で解決されます (つまり、RavenDB サーバーへの追加の要求は必要ありません)。これは、[関連する] オブジェクトが .Include 呼び出しによって既に取得されているためです。

于 2012-09-07T16:46:27.590 に答える