RavenDB:将数据库中的文档与来自外部源的数据同步

时间:2012-06-12 20:39:52

标签: c# sync ravendb data-synchronization

在RavenDB中同步文档的最有效方式是什么?

从外部来源,我得到了IEnumerable BlogPosts,我想要执行以下操作:

  • 添加RavenDB的新对象
  • 更新现有对象
  • 删除在外部源中删除的对象

需要实施的代码:

public void SyncIntoRaven(IEnumerable<BlogPost> postsToSync, IDocumentStore store) {
    // TODO: Implement
    // AddNewItems(postsToSync);

    // TODO: Implement
    // RemoveDeletedItems(postsToSync);

    // TODO: Implement
    // UpdateExistingItems(postsToSync);
}

可以从RavenDB中拔出所有BlogPosts,然后在本地同步然后再推送所有更改,但我想最大限度地减少到RavenDB的流量。但也许这也不是正确的方法?

2 个答案:

答案 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();
}