1

我将User对象存储在 RavenDB 中。每个User人都有一个User.Id财产。

我还有一个Relationship类将两个User.Ids 链接在一起以创建 Mentor/Mentee 关系,如下所示:

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 回答