如何在RavenDB中实现非规范化引用

如何在RavenDB中实现非规范化引用,ravendb,Ravendb,我希望在RavenDB文档数据库中存储两个实体之间的引用。由于这不是关系数据库,我知道我应该使用RavenDBs文档中描述的非规范化引用技术。虽然一开始这看起来不错,但一旦我开始创建一个包括双向引用的真实世界域“层次结构”,保持所有这些引用最新的努力就显得不成比例了。我觉得我可能在什么地方出错了 您能否解释一下使用RavenDB对相当复杂的域层次结构建模的最佳/最简单方法 谢谢我不确定这是否足以回答您的问题,但以下是我如何在RavenDB中创建一个非规范化引用(这是从真实代码中提取的,为了清晰起

我希望在RavenDB文档数据库中存储两个实体之间的引用。由于这不是关系数据库,我知道我应该使用RavenDBs文档中描述的非规范化引用技术。虽然一开始这看起来不错,但一旦我开始创建一个包括双向引用的真实世界域“层次结构”,保持所有这些引用最新的努力就显得不成比例了。我觉得我可能在什么地方出错了

您能否解释一下使用RavenDB对相当复杂的域层次结构建模的最佳/最简单方法


谢谢

我不确定这是否足以回答您的问题,但以下是我如何在RavenDB中创建一个非规范化引用(这是从真实代码中提取的,为了清晰起见,删除了非基本内容)

public class User : IUserIdentity
{
    public string UserName { get; set; }
    public IEnumerable<string> Claims { get; set; }
    public string Id { get; set; }
    public Guid FormsAuthenticationGuid { get; set; }
}

public class Assessment
{ 
    public string Id { get; set; }
    public UserReference User { get; set; }
    public AssessmentState State { get; set; }
}
注意引用类如何携带
用户名
。该值不会经常更改,但可能会更改,因此我们需要一种方法来更新
Assessment
类中的
UserReference
属性中的
UserName
属性。要进行更改,我们必须首先从RavenDB中找到正确的
评估
实例,为此我们需要一个索引

乌鸦指数

public class Assessment_ByUserId : AbstractIndexCreationTask<Assessment>
{
    public Assessment_ByUserId()
    {
        Map = assessments => from assessment in assessments
                                select new
                                    {
                                            User_Id = assessment.User.Id
                                    };
    }
}

就是这样。你知道,现在我把一切都说出来了,我明白你的意思了。仅仅更新一个参考资料就需要做很多工作。也许服务代码可以变得更加枯燥,并可用于不同的关系类型,但我不知道如何避免编写大量索引,每个引用类型一个。

太好了,感谢biofractal,我正在尝试一种更复杂的方法,这看起来很理想。这篇博文可能会帮助您做出决定:感谢dasheddot,这真的很有用,谢谢。这看起来很有趣。多映射/减少索引
public class Assessment_ByUserId : AbstractIndexCreationTask<Assessment>
{
    public Assessment_ByUserId()
    {
        Map = assessments => from assessment in assessments
                                select new
                                    {
                                            User_Id = assessment.User.Id
                                    };
    }
}
public static void SetUserName(IDocumentSession db, string userId, string userName)
{
    var user = db.Load<User>(userId);
    user.UserName = userName;
    db.Save(user);
    UpdateDenormalizedReferences(db, user, userName);
}

private static void UpdateDenormalizedReferences(IDocumentSession db, User user, string userName)
{
    db.Advanced.DatabaseCommands.UpdateByIndex(
            RavenIndexes.IndexAssessmentByUserId,
            GetQuery(user.Id),
            GetUserNamePatch(userName),
            allowStale: true);

}

private static IndexQuery GetQuery(string propertyValue, string propertyName = "User_Id")
{
    return new IndexQuery {Query = string.Format("{0}:{1}", propertyName, propertyValue)};
}

private static PatchRequest[] GetUserNamePatch(string referenceValue, string referenceName = "User")
{
    return new[]
            {
                    new PatchRequest
                    {
                            Type = PatchCommandType.Modify,
                            Name = referenceName,
                            Nested = new[]
                                    {
                                            new PatchRequest
                                            {
                                                    Type = PatchCommandType.Set,
                                                    Name = "UserName",
                                                    Value = referenceValue
                                            }
                                    }
                    }
            };
}