使用RavenDB,如何有效地检索与“外键”相关的项目列表

时间:2012-09-07 16:32:53

标签: linq ravendb

我在RavenDB中存储User个对象。每个User都有User.Id个属性。

我还有一个Relationship类,它将两个User.Id链接在一起以创建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(见下面接受的答案),他为我解决了多次调用数据库的问题。此外,我还创建了一个名为&#39; Memoize&#39;的新扩展方法。消除对外部学员的需要。结果列表(见上面的代码)。

这是优化的代码。请随时评论并进一步完善。

Linq

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()

1 个答案:

答案 0 :(得分:1)

您希望使用.Include query customization告诉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!

Relevant documentation here

  

对Load()的调用完全由客户端解决(即没有   对RavenDB服务器的其他请求)因为[相关]   已经通过.Include调用检索了对象。