gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 08:13:14 27 4
gpt4 key购买 nike

我想在存储在 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引用 User 的类.此用户引用使用 UserReference 进行管理下面的课。

非规范化引用
public class UserReference
{
public string Id { get; set; }
public string UserName { get; set; }

public static implicit operator UserReference(User user)
{
return new UserReference
{
Id = user.Id,
UserName = user.UserName
};
}
}

请注意引用类如何还带有 UserName .这个值不会经常改变但它可能会改变所以我们需要一种方法来更新 UserName属性(property)在 UserReference持有的属性(property) Assessment类(class)。要进行更改,我们必须首先找到正确的 Assessment来自 RavenDB 的实例,为此我们需要一个索引。

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

每当出现 User 时都需要调用此索引的 UserName值已更新。我有一个 UserService帮助我协调所有与用户相关的功能的类,所以这就是我放置这段代码的地方。

我将此代码重用于其他引用,因此已将其抽象化了一点。这可能会帮助您创建您想要的更复杂的层次结构(或者“域图”可能是更好的描述)。

用户服务
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
}
}
}
};
}

这就对了。你知道,现在我把它全部列出来,我明白你的意思了。仅更新引用就需要大量工作。也许可以使 Service 代码更加 DRY 并重用于不同的关系类型,但我不知道如何避免编写大量索引,每个引用类型一个。

关于ravendb - 如何在 RavenDB 中实现非规范化引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10496391/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com