C# 2.0 Update Definition conditional set

1,014 views
Skip to first unread message

Aaron Powell

unread,
Apr 29, 2015, 9:50:00 PM4/29/15
to mongod...@googlegroups.com
I'm migrating from 2.0.0-beta1 to 2.0.0 and in the process need to convert from UpdateBuilder to UpdateDefinition.

I am doing some updates using the API that are from HTTP PATCH methods, meaning that most of the values are optional so using the UpdateDefinitionBuilder I wanted to conditionally set the value if one was provided.

I created myself an extension method like this:

public static UpdateDefinition<T> SetIfValue<T>(this UpdateDefinition<T> builder, Expression<Func<T, string>> setter, string value)

{

if (!string.IsNullOrEmpty(value))

builder.Set(setter, value);

return builder;

}


Which works just fine if it's not the first method called, but if I have the UpdateDefinitionBuilder it's a whole lot harder. Basically I was trying to do:

var builder = Builders<SomeClass>.Update;

var updates = builder.SetIfValue(x => x.Foo, model.Foo)
    .SetIfValue(x => x.Bar, model.Bar);

Because UpdateDefinitionBuilder and UpdateDefinition are now separate classes (UpdateBuilder was the class that you a) created and b) passed to UpdateOneAsync) this doesn't work, returning the UpdateDefinitionBuilder is really complex to ensure that the chaining works (at some point I need to convert it from a UDB to a UD).

How could one go about doing this? I was thinking of creating a `NoopUpdateDefinition` which does nothing in the Render method but pass-through to the rest of the items but I don't get how the Render method works from the source code and (and my quick test resulted in corrupt documents :P).

Craig Wilson

unread,
Apr 30, 2015, 4:43:51 PM4/30/15
to mongod...@googlegroups.com
Hi Aaron,

I coded this up as follows. However, let me couch this in a bug I found while doing this... https://jira.mongodb.org/browse/CSHARP-1265. So, if you are going to do this prior to us getting the bug fixed, then you need to make sure that you don't end up with an empty document as your update. I'm not sure what you were doing to get corrupted documents, so perhaps a posting of that code would help if this doesn't solve the problem.

Craig

[Test]
    public void TestExtension()
    {
        var subject = CreateSubject<Person>();
 
        Assert(subject.SetIf(x => x.FirstName, "Jack"), "{$set: {fn: 'Jack'}}");
        Assert(subject.SetIf(x => x.FirstName, null), "{ }");
 
        Assert(subject.Set(x => x.Age, 10).SetIf(x => x.FirstName, "Jack"), "{$set: {age: 10, fn: 'Jack'}}");
        Assert(subject.Set(x => x.Age, 10).SetIf(x => x.FirstName, null), "{$set: {age: 10}}");
    }
 
    public static class UpdateDefExtensions
    {
        public static UpdateDefinition<TDocument> SetIf<TDocument>(this UpdateDefinition<TDocument> builder, Expression<Func<TDocument, string>> field, string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                return builder.Set(field, value);
            }
 
            return builder;
        }
 
        public static UpdateDefinition<TDocument> SetIf<TDocument>(this UpdateDefinitionBuilder<TDocument> builder, Expression<Func<TDocument, string>> field, string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                return builder.Set(field, value);
            }
 
            return NoopUpdateDefinition<TDocument>.Instance;
        }
 
        public sealed class NoopUpdateDefinition<TDocument> : UpdateDefinition<TDocument>
        {
            private static readonly NoopUpdateDefinition<TDocument> __instance = new NoopUpdateDefinition<TDocument>();
 
            private NoopUpdateDefinition()
            {
            }
 
            public static NoopUpdateDefinition<TDocument> Instance
            {
                get { return __instance; }
            }
 
            public override BsonDocument Render(IBsonSerializer<TDocument> documentSerializer, IBsonSerializerRegistry serializerRegistry)
            {
                return new BsonDocument();
            }
        }
    }

Aaron Powell

unread,
Apr 30, 2015, 11:49:40 PM4/30/15
to mongod...@googlegroups.com

The only different between your implementation of the Noop and mine was that I wasn’t using a singleton, instead returning a new instance each time.

 

I’ll give this a try and let you know how it goes J

--
You received this message because you are subscribed to the Google Groups "mongodb-user"
group.
 
For other MongoDB technical support options, see: http://www.mongodb.org/about/support/.
---
You received this message because you are subscribed to a topic in the Google Groups "mongodb-user" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mongodb-user/d5seLlEzHaI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mongodb-user...@googlegroups.com.
To post to this group, send email to mongod...@googlegroups.com.
Visit this group at http://groups.google.com/group/mongodb-user.
To view this discussion on the web visit https://groups.google.com/d/msgid/mongodb-user/2e6b5a04-4f1a-49aa-9962-f6a30093660a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Aaron Powell

unread,
Apr 30, 2015, 11:50:51 PM4/30/15
to mongod...@googlegroups.com

Actually, looking at the bug, I think that’s what I was hitting to corrupt my documents, they ended up only having their `_id` left.

Craig Wilson

unread,
May 1, 2015, 6:14:53 AM5/1/15
to mongod...@googlegroups.com
Yeah, singleton cause, in this case, why not...  

The fix for the bug will be to throw an exception indicating that the update document must have at least 1 dollar operator. So, you're going to have to work through that problem anyways, making sure that your update document has at least 1 actual update.

Craig

To unsubscribe from this group and all its topics, send an email to mongodb-use...@googlegroups.com.
To post to this group, send email to mongo...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "mongodb-user"
group.
 
For other MongoDB technical support options, see: http://www.mongodb.org/about/support/.
---
You received this message because you are subscribed to a topic in the Google Groups "mongodb-user" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mongodb-user/d5seLlEzHaI/unsubscribe.

To unsubscribe from this group and all its topics, send an email to mongodb-use...@googlegroups.com.
To post to this group, send email to mongo...@googlegroups.com.

Reply all
Reply to author
Forward
0 new messages