【问题标题】:Any disadvantage to calling _documentSession.Store when updating existing documents in RavenDB?更新 RavenDB 中的现有文档时调用 _documentSession.Store 有什么缺点吗?
【发布时间】:2013-03-29 03:36:31
【问题描述】:

在 RavenDB 中创建新文档或更新现有文档时,文档说要按照以下方式进行:

public string Save(Blogpost post)
{
    Blogpost model;

    if (String.IsNullOrEmpty(post.Id))
    {
        model = new Blogpost();
        _documentSession.Store(model);
    }
    else
    {
        model = _documentSession.Load<Blogpost>(post.SimpleId);
    }

    model.Text = template.Text;
    model.Name = template.Name;
    _documentSession.SaveChanges();

    return model.Id;
}

我团队中的某个人正在使用另一种方法来创建新文档或更新现有文档:

public string Save(Blogpost post)
{
    _documentSession.Store(post);
    _documentSession.SaveChanges();
    return post.Id;
}

即使文档已经存在,总是调用.Store() 有什么缺点吗?

【问题讨论】:

    标签: ravendb


    【解决方案1】:

    杰森, 您的代码将始终覆盖文档。那是你想做的事情吗?

    【讨论】:

    • 在大约 1/2 的用例中,完全覆盖是可以的。我质疑他提出的这种方法,因为我习惯了实体框架和典型的工作单元。我只是想确保这种方法不会在我们的应用程序中引起潜在的问题。
    • 覆盖的一个不太明显的副作用是自定义元数据值将丢失。
    • 是的,如果你想保留元数据,加载文档,更新它,然后调用 SaveChanges()
    【解决方案2】:

    如果您正在开发一个富客户端应用程序并将完整的 BlogPost 序列化到客户端,如下所示:

    //GET BlogPost/1
    public BlogPost Get(int id)
    {
        return _documentSession.Load<BlogPost>(id)
    }
    

    然后在用户进行更改后在服务器上重新填充完整的 BlogPost。下面的代码似乎比先加载再存储效率更高:

    //POST BlogPost/
    public void Post(BlogPost post)
    {
        //blog post already has an Id in this example
        _documentSession.Store(post)
        _documentSession.SaveChanges(); 
    }
    

    当你做一个

    documentSession.Load<Blogpost>(id)
    

    RavenDB 返回您已经拥有的博客文章的完整 JSON,以便您覆盖它,转身并重新保存,将博客文章的完整 JSON 通过网络再次发送回乌鸦。

    这意味着当您已经拥有所有数据时执行加载和存储会导致 Raven 的网络流量增加一倍,而我使用 Fiddler 并没有看到额外的好处。

    即使您只是更改对象的一部分(比如博客帖子的名称),RavenDB .NET API 在执行以下操作时仍会通过线路发送完整的对象:

    • 加载()
    • 进行一些更改(但不更改所有内容)
    • 商店()
    • SaveChanges()

    也许 Ayende Rahien 可以启发我们了解我在这里错过的任何事情?

    【讨论】:

    • 您缺少 3 件事:1) RavenDB 客户端 API 使用缓存,因此如果您已经在 Get 中加载它,在 Post 中再次加载它会产生最少的流量,而不是完整的 JSON 文档。如果您获得了完整的 JSON 文档,那么您最好再次加载它,因为在您处理它时还有其他更改。 2) 继续#1,它使您能够利用乐观并发,并且 3) UoW 是做这些事情的正确方法,主要是出于我刚才提到的原因。
    • 太棒了,这就是我们正在寻找的答案。我不知道我是否看到 #1 发生在有线通信中,但这可能是由于进行调试。我认为乐观并发是一个很好的观点。我想可以使用 Automapper 将 BlogPost 从客户端推送到 Load'ed 或者这有关系吗?好东西!也许我/你也可以更新这方面的文档页面。
    【解决方案3】:

    Store 会将此对象存储在一个新文档中。使用会话对象中内置的更改跟踪功能,也就是工作单元模式,就像文档建议的那样。

    【讨论】:

    • 我同意。这个想法是别人提出来的,我宁愿不要在不明白为什么的情况下随意将其击落。优点是它确实使代码在某些方面明显更清晰。
    • synhershko 是否有某种我想念的理由这样做?在我的有线测试中,它似乎对原始流量没有任何作用......
    • @JohnCulviner 看到我的 cmets 到你的帖子。这变成了真正应该在邮件列表而不是 SO 上进行的讨论。
    猜你喜欢
    • 1970-01-01
    • 2019-11-09
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 2011-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多