我正在寻找最有效的方法来更新存储在 Postgres 数据库 (V 10) 中的现有 Marten 文档中的单个属性。例如,假设 User 定义为:
public class User(){
public string Id {get; set;}
public string Name {get; set;}
public int Age {get; set;}
}
我有一个用户保存在用户数据库中,ID:1,姓名:Joe,年龄:30。然后我想将 Name 的值更新为 Joe Smith,我可以:
查询文档的服务器,更新文档并再次保存:
DocumentStore store = // omitted for brevity
User user;
// Get User Document
using (var session = store.OpenSession())
{
user = session
.Query<User>()
.Where(x => x.Id == 1)
.FirstOrDefault();
}
// Update user name
user.Name = "Joe Smith";
using (var session = store.LightweightSession())
{
session.Store(user);
session.SaveChanges();
}
但这似乎非常低效,因为有两个事务,一个用于查询,一个用于保存。
我从 2015 年开始使用 Session.Patch找到Jeremy Miller 的讨论,并实施了这种类型的更新。我不得不为 Postgres 安装plv8 扩展,因为他们似乎从之前的几个版本中停止包含它。我有自己的方法执行:
private void UpdateUserName(string userId, string newName, DocumentStore store)
{
try
{
using (var session = store.OpenSession())
{
Guid userGuid = new Guid(userId);
session.Patch<User>(userGuid).Set(u => u.Name, newName );
}
}
catch
{
throw;
}
}
这会在不引发任何异常的情况下执行,但不会影响对保存在数据库中的用户文档的更改。
我不确定我的补丁中是否有错误,或者是否有更好的方法来使用不需要 plv8 扩展的不同会话方法。
更新:通过在补丁调用之后添加 SaveChanges() 调用来解决补丁不影响对数据库的更改,如下所示:
private void UpdateUserName(string userId, string newName, DocumentStore store)
{
try
{
using (var session = store.OpenSession())
{
Guid userGuid = new Guid(userId);
session.Patch<User>(userGuid).Set(u => u.Name, newName );
session.SaveChanges(); // <-- force changes to database
}
}
catch
{
throw;
}
}
我仍然想知道这是否是部分更新文档的最有效方法。