我有以下C模型课程:
public class Thingy
{
public ObjectId Id { get; set; }
public string Title { get; set; }
public DateTime TimeCreated { get; set; }
public string Content { get; set; }
public string UUID { get; set; }
}
以及以下asp.mvc控制器操作:
public ActionResult Create(Thingy thing)
{
var query = Query.EQ("UUID", thing.UUID);
var update = Update.Set("Title", thing.Title)
.Set("Content", thing.Content);
var t = _collection.Update(query, update, SafeMode.True);
if (t.UpdatedExisting == false)
{
thing.TimeCreated = DateTime.Now;
thing.UUID = System.Guid.NewGuid().ToString();
_collection.Insert(thing);
}
/*
var t = _collection.FindOne(query);
if (t == null)
{
thing.TimeCreated = DateTime.Now;
thing.UUID = System.Guid.NewGuid().ToString();
_collection.Insert(thing);
}
else
{
_collection.Update(query, update);
}
*/
return RedirectToAction("Index", "Home");
}
此方法执行更新或插入。如果需要插入,则必须设置uuid和timecreated成员。如果需要进行更新,则必须保留uuid和timecreated,但必须更新成员的标题和内容。
注释掉的代码可以工作,但似乎不是最有效的。当它调用findone时,这是一次mongodb之旅。然后如果它转到else子句,它将执行另一个查询和一个更新操作,这样就可以再访问mongodb两次。
做我想做的事,有什么更有效的方法?
最佳答案
正如linked so答案中提到的,要使upserts工作,您需要更新整个文档,而不仅仅是一些属性。
就我个人而言,我会将Create
和Edit
分离为单独的mvc操作。SRP。创建Thingy
与更新它有不同的考虑因素。
如果仍要执行upsert而不是单独的插入/更新调用,则需要使用以下代码:
_collection.Update(
Query.EQ("UUID", thing.UUID),
Update.Replace(thing),
UpsertFlags.Upsert
);
现在的问题是,我们如何确保
thing
对于这两种情况都有适当的值,即插入和更新。我的假设是(基于您绑定到
Thingy
实例的代码模型),您的视图将发送回所有字段(包括UUID
和TimeCreated
)。这意味着,在更新的情况下,视图已经预先填充了UUID
和TimeCreated
的值。因此,在更新Thingy
的情况下,thing
对象具有最新的值。现在,在创建的情况下,当呈现视图时,可以为
DateTime.MinValue
字段存储TimeCreated
。在Create
mvc操作中,您可以检查TimeCreated
是否DateTime.MinValue
,然后将其设置为当前时间,并为UUID
存储一个新值。这样,在插入的情况下,
thing
也有最新的值。这样我们就可以安全地进行一次升级。关于c# - 在mongodb中执行高效的upsert,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12460005/