考虑下面的类
public class Something
{
public ObjectId Id;
public DateTime DbUpdatedAt;
public string AnotherProperty;
public int SomeIntProp;
}
我通常会使用以下代码进行部分更新
var obj = ... // an instance of Something
var update = new UpdateBuilder<Something>();
update.Set(x => x.DbUpdatedAt, DateTime.UtcNow);
...
/// later on,
// database is an instance of MongoDatabase
database.GetCollection("CollectionName")
.Update(Query<Something>.Eq(x => x.Id, something.Id), update);
问题是,我不知道有什么方法可以检查 update
是否已配置为设置 DbUpdatedAt
的值。
如果我盲目地尝试为 DbUpdatedAt
设置新值,则会收到错误。
...
/// later on,
update.Set(x => x.DbUpdatedAt, DateTime.UtcNow.AddHours(1)); // this throws a Duplicate element name error
// database is an instance of MongoDatabase
database.GetCollection("CollectionName")
.Update(Query<Something>.Eq(x => x.Id, something.Id), update);
我明白为什么会发生错误。我需要一种方法,
- 检测到存在重复的关键场景,
- 用新的键、值对替换旧的键、值对。
最佳答案
当前实现的 UpdateBuilder 认为尝试将同一字段设置为两个不同的值是一个错误(尽管我希望抛出的异常更清晰......)。
期望对同一字段调用 Set 两次只会用第二个字段覆盖第一个字段并不是没有道理的,但这不是它目前的工作方式。如果您认为应该这样做,请提交一份 JIRA 票证以建议更改。
作为解决方法,您可以在 UpdateBuilder 上定义一个按您希望的方式运行的扩展方法。它可能看起来像这样:
public static UpdateBuilder<TDocument> SetWithOverride<TDocument, TField>(this UpdateBuilder<TDocument> update, Expression<Func<TDocument, TField>> memberExpression, TField value)
{
var set = Update<TDocument>.Set(memberExpression, value).ToBsonDocument();
var combined = update.ToBsonDocument();
if (combined.Contains("$set"))
{
var element = set[0].AsBsonDocument.GetElement(0);
combined["$set"][element.Name] = element.Value;
}
else
{
combined.Merge(set);
}
return Update<TDocument>.Combine(combined.Elements.Select(e => new UpdateDocument(e)));
}
下面是一些示例代码,显示了它的使用情况:
var update = Update<C>.Set(c => c.X, 1).Set(c => c.Y, 2);
update = update.SetWithOverride(c => c.Y, 3);
关于mongodb - 构造 UpdateBuilder 时如何避免 'Duplicate Element Name' 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21227428/