How to optionally pass a IClientSessionHandle using the C# MongoDB Driver?
Asked Answered
B

1

13

I use the repository pattern. My repository methods receive an optional IClientSessionHandle parameter which defaults to null. A part of each method prepares the filters/updates/etc., then a call is made. Since the session is optional, I have something like this:

if (sessionHandle != null)
    await Collection.InsertOneAsync(sessionHandle, myObject);
else
    await Collection.InsertOneAsync(myObject);

I suppose that always sending the session, null or not, wouldn't work, but I did not test it yet. Also, even if it would actually work, I would have no guarantee that this behavior wouldn't change in the future, as it's not part of the contract.

Is there a way to have a single call?

PS: The reason to have an optional IClientSessionHandle is to re-use the same repository methods, within a transaction or not.

Braw answered 14/1, 2020 at 21:29 Comment(5)
i've had to use the same pattern as there's no other alternative than calling the appropriate overload depending on wether session is null or not.Twin
JohnKnoop.MongoRepository provides an abstraction that automatically enlists with the current transaction. That means you don't have to bother with the separate calls. github.com/johnknoop/MongoRepository#transactionsAllisonallissa
@JohnKnoop I see your useful library automatically attaches to the current transaction. Doesn't the official MongoDb.Driver work in the same way? This article medium.com/c-sharp-progarmming/… seems to imply that it does, because it does not pass the session explicitly between starting it and commiting changes.Bledsoe
All Mongo driver methods have an overload that accepts a Session object. If you don't pass in a Session object, the operation will not be part of any transaction. I'm guessing the author of the linked article must have missed this.Allisonallissa
you could try a ternary operator to see if that would work. something like this: await (sessionHandle != null ? Collection.InsertOneAsync(sessionHandle, myObject) : Collection.InsertOneAsync(myObject));Discontinue
P
0

a way is using optional parameters , for example :

public class Collection
{
    public Task InsertOneAsync(object myObject, object sessionHandle = null)
    {
        /*your code*/
        return Task.CompletedTask;
    }
}

now use its :

var collection = new Collection();
await collection.InsertOneAsync(myObject,sessionHandle);

another way is using factory class for example :

public interface ICollection
{
    Task InsertOneAsync(object myObject);
}
public static class CollectionFactory
{
    public static ICollection Factory(object sessionHandle)
    {
        switch (sessionHandle)
        {
            case null: return new SimpleCollection();
            default: return new SessionOrientedCollection(sessionHandle);
        }
    }
}

public class SimpleCollection : ICollection
{
    public virtual Task InsertOneAsync(object myObject)
    {
        /*your code*/
        return Task.CompletedTask;
    }
}
public class SessionOrientedCollection : SimpleCollection
{
    private readonly object sessionHandle;
    public SessionOrientedCollection(object sessionHandle)
    {
        this.sessionHandle = sessionHandle;
    }
    public override Task InsertOneAsync(object myObject)
    {
        base.InsertOneAsync(myObject);
        /*your code*/
        return Task.CompletedTask;
    }
}

now use its :

var collection = CollectionFactory.Factory(sessionHandle);
await collection.InsertOneAsync(myObject);
Perforation answered 13/3, 2023 at 15:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.