如何避免重复元素名称'构造UpdateBuilder时出错

时间:2014-01-20 06:20:42

标签: mongodb mongodb-.net-driver

考虑以下课程

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);

我明白为什么会发生错误。我需要一种方法,

  1. 检测到存在重复的关键字方案,
  2. 将旧密钥,值对替换为新密钥,值对。

2 个答案:

答案 0 :(得分:2)

当前实现的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);

答案 1 :(得分:0)

来自the manuals

  

使用$ set运算符将字段的值替换为指定的值。如果该字段不存在,$ set运算符将添加具有指定值的字段。

根据您的说明,您不应该收到任何重复的密钥错误,除非您已DbUpdatedAt部分unique index或部分错误。

我认为更常见的错误是插入文档而不是更新文档(使用C#驱动程序很容易)但如果使用Mongo的查询构建器进行更新,则不会发生这种情况,正如你似乎在做的那样。

总而言之,你得到的错误没有意义。你确定没有其他事情导致这个错误吗?