1

在 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 的流量。但也许这也不是正确的方法?

4

2 回答 2

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();
}    
于 2012-06-15T20:57:00.653 回答
1

如果您在外部源和 RavenDB 之间共享相同的 ID,您可以很容易地以 ACID 方式在一个事务中完成此操作。

跟踪在同步操作之间更改的 ID,一旦您拥有该 ID 列表,您就可以轻松地执行此操作:

打开一个会话,使用 session.Store() 添加新文档,使用 session.Load(string[]) session.Load().Lazily 加载所有需要更新或删除的文档,使用 Deferred 选项进行更新(和删除),一旦你完成调用 session.SaveChanges()。

这应该让你得到覆盖,并且只发生在服务器的一次往返中。

无论哪种方式,您都不想每次都进行完全同步。你总是想使用增量。

于 2012-06-13T18:31:32.043 回答