在RavenDB中同步文档的最有效方式是什么?
从外部来源,我得到了IEnumerable
BlogPosts,我想要执行以下操作:
需要实施的代码:
public void SyncIntoRaven(IEnumerable<BlogPost> postsToSync, IDocumentStore store) {
// TODO: Implement
// AddNewItems(postsToSync);
// TODO: Implement
// RemoveDeletedItems(postsToSync);
// TODO: Implement
// UpdateExistingItems(postsToSync);
}
可以从RavenDB中拔出所有BlogPosts,然后在本地同步然后再推送所有更改,但我想最大限度地减少到RavenDB的流量。但也许这也不是正确的方法?
答案 0 :(得分:1)
如果您在外部源和RavenDB之间共享相同的ID,则可以非常轻松地以ACID方式在一次交易中完成此操作。
跟踪同步操作之间更改的ID,一旦拥有ID列表,您就可以轻松完成此操作:
打开会话,使用session.Store()添加新文档,使用session.Load(string [])session.Load()加载需要更新或删除的所有文档。懒洋洋地,进行更新(和删除使用延迟选项),一旦完成,请调用session.SaveChanges()。
这应该让你得到保障,并且只在一次往返服务器中发生。
无论哪种方式,您都不希望每次都完全同步。你总是想使用增量。
答案 1 :(得分:1)
在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();
}