RavenDB:将数据库中的文档与来自外部源的数据同步
本文关键字:外部 同步 数据 文档 数据库 RavenDB | 更新日期: 2023-09-27 18:37:01
在
RavenDB中同步文档的最有效方法是什么?
从外部来源,我得到了IEnumerable
博客文章,我想用它执行以下操作:
- 添加 RavenDB 的新对象
- 更新现有对象
- 删除在外部源中删除的对象
需要实现的代码:
public void SyncIntoRaven(IEnumerable<BlogPost> postsToSync, IDocumentStore store) {
// TODO: Implement
// AddNewItems(postsToSync);
// TODO: Implement
// RemoveDeletedItems(postsToSync);
// TODO: Implement
// UpdateExistingItems(postsToSync);
}
人们可以从RavenDB中提取所有BlogPosts并在本地同步,然后将所有更改推送回去,但我想尽量减少RavenDB的流量。但也许这也不是正确的方法?
如果您在外部源和 RavenDB 之间共享相同的 ID,则可以在一个事务中以 ACID 方式非常轻松地执行此操作。
跟踪在同步操作之间更改的 ID,获得该 ID 列表后,您可以轻松完成此操作:
打开会话,使用会话添加新文档。Store(),使用会话加载所有需要更新或删除的文档。加载(字符串[])会话。加载()。懒洋洋地进行更新(并使用"延迟"选项进行删除),并在完成呼叫会话后进行。保存更改()。
这应该可以覆盖您,并且只需一次往返服务器即可完成。
无论哪种方式,您都不想每次都进行完全同步。您始终希望使用增量。
在 synhershko 的描述形式的帮助下,我想通了它,并希望分享代码,简化以显示概念。
private void RefreshBlogPosts(IDocumentSession session, IList<BlogPost> parsedPosts) {
var parsedPostsIds = parsedPosts.Select(x => x.Id);
var storePosts = session.Load<BlogPost>(parsedPostsIds);
// Update existing or create new posts
for(int i = 0; i < storePosts.Count(); i++) {
var parsedPost = parsedPosts[i];
var storePost = storePosts[i];
if(storePost == null) {
storePost = parsedPost;
session.Store(storePost);
} else {
// Update post's properties
}
}
// Find posts IDs no longer in database
var removedPostIds = session.Query<BlogPost>().Select(x => x.Id)
.Where(postId => !parsedPostsIds.Contains(postId));
foreach(var removedPostId in removedPostIds) {
session.Advanced.Defer(new DeleteCommandData() { Key = removedPostId });
}
session.SaveChanges();
}