< Summary

Information
Class: ArturRios.Data.MongoDb.Repositories.MongoDocumentRepository<T>
Assembly: ArturRios.Data.MongoDb
File(s): /home/ci/agent/workspace/dotnet-data-docs_main/app/src/ArturRios.Data.MongoDb/Repositories/MongoDocumentRepository.cs
Line coverage
87%
Covered lines: 204
Uncovered lines: 28
Coverable lines: 232
Total lines: 486
Line coverage: 87.9%
Branch coverage
75%
Covered branches: 53
Total branches: 70
Branch coverage: 75.7%
Method coverage
97%
Covered methods: 45
Fully covered methods: 35
Total methods: 46
Method coverage: 97.8%
Full method coverage: 76%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.cctor()50%44100%
get_Collection()100%11100%
get_Session()100%11100%
GetAllAsync(...)100%11100%
GetByIdAsync(...)100%11100%
FindAsync(...)100%11100%
CreateAsync(...)100%11100%
CreateRangeAsync(...)100%11100%
UpdateAsync(...)100%11100%
UpdateRangeAsync(...)100%1190%
DeleteAsync(...)100%11100%
DeleteRangeAsync(...)100%1194.11%
Query()100%11100%
GetAll()100%11100%
GetById(...)100%22100%
Find(...)100%11100%
Create(...)100%11100%
CreateRange(...)100%66100%
Update(...)100%11100%
UpdateRange(...)0%620%
Delete(...)100%11100%
DeleteRange(...)50%4493.75%
IdFilter(...)100%11100%
IsObjectId(...)100%11100%
ExistingIdCandidates(...)100%22100%
InRequestOrder(...)100%11100%
DeleteFilter(...)100%22100%
EnsureDeleted(...)100%66100%
DeleteOne(...)50%22100%
EnsureId(...)100%22100%
FindFluent(...)100%22100%
InsertOne(...)50%2275%
InsertMany(...)50%2275%
DeleteMany(...)50%2275%
Replace(...)100%4481.25%
EnsureMatched(...)100%44100%
ReplaceOne(...)50%22100%
Guarded(...)100%1166.66%
InsertOneAsync(...)100%22100%
InsertManyAsync(...)50%22100%
DeleteManyAsync(...)50%22100%
DeleteOneAsync()50%22100%
ReplaceAsync()62.5%9877.27%
GuardedAsync()100%1166.66%
Fail(...)100%44100%

File(s)

/home/ci/agent/workspace/dotnet-data-docs_main/app/src/ArturRios.Data.MongoDb/Repositories/MongoDocumentRepository.cs

#LineLine coverage
 1using System.Linq.Expressions;
 2using System.Runtime.CompilerServices;
 3using ArturRios.Data.MongoDb.Exceptions;
 4using ArturRios.Data.MongoDb.Interfaces;
 5using ArturRios.Output;
 6using Microsoft.Extensions.Logging;
 7using MongoDB.Bson;
 8using MongoDB.Bson.Serialization;
 9using MongoDB.Driver;
 10
 11namespace ArturRios.Data.MongoDb.Repositories;
 12
 13/// <summary>
 14///     MongoDB implementation of the document repository contracts. Runs against the
 15///     <see cref="MongoContext" /> collection and enlists in its ambient session so operations
 16///     participate in a unit-of-work transaction. Failures are returned as <see cref="DataOutput{T}" />.
 17/// </summary>
 18/// <typeparam name="T">The document type.</typeparam>
 19/// <param name="context">The Mongo context.</param>
 20/// <param name="logger">
 21///     Optional logger. Envelopes never carry driver text, so a failure is otherwise
 22///     undiagnosable: supply a logger and the full exception, plus the document type and the
 23///     repository method that failed, is written at <see cref="LogLevel.Error" />. Document
 24///     contents and key values are never logged. Resolved from DI when logging is registered.
 25/// </param>
 7026public class MongoDocumentRepository<T>(MongoContext context, ILogger<MongoDocumentRepository<T>>? logger = null)
 27    : IDocumentRepository<T>, IAsyncDocumentRepository<T> where T : Document
 28{
 29    /// <summary>Message returned when an operation fails with no finer classification.</summary>
 30    protected const string OperationFailedMessage = MongoErrors.GenericMessage;
 31
 32    /// <summary>Message returned when the failure is transient and the operation may be retried.</summary>
 33    protected const string TransientMessage = MongoErrors.TransientMessage;
 34
 35    /// <summary>Message returned on an optimistic-concurrency conflict.</summary>
 36    protected const string ConcurrencyMessage = MongoErrors.ConcurrencyMessage;
 37
 38    /// <summary>Message returned when a write violates a unique index.</summary>
 39    protected const string UniqueViolationMessage = MongoErrors.UniqueViolationMessage;
 40
 41    // Cached: the serialized BSON element name for VersionedDocument.Version on T
 42    // (respects any element-name convention the consumer registered).
 443    private static readonly string VersionElementName =
 444        BsonClassMap.LookupClassMap(typeof(T)).AllMemberMaps
 845            .FirstOrDefault(m => m.MemberName == nameof(VersionedDocument.Version))?.ElementName
 446        ?? nameof(VersionedDocument.Version);
 47
 48    /// <summary>The collection for <typeparamref name="T" />.</summary>
 16849    protected IMongoCollection<T> Collection => context.GetCollection<T>();
 50
 16651    private IClientSessionHandle? Session => context.Session;
 52
 53    /// <inheritdoc />
 54    public Task<DataOutput<IEnumerable<T>>> GetAllAsync(CancellationToken ct = default) =>
 2455        GuardedAsync<IEnumerable<T>>(async () => await FindFluent(FilterDefinition<T>.Empty).ToListAsync(ct).ConfigureAw
 56
 57    /// <inheritdoc />
 58    public Task<DataOutput<T?>> GetByIdAsync(string id, CancellationToken ct = default) =>
 2859        GuardedAsync<T?>(async () => IsObjectId(id)
 2860            ? await FindFluent(IdFilter(id)).FirstOrDefaultAsync(ct).ConfigureAwait(false)
 2861            : null);
 62
 63    /// <inheritdoc />
 64    public Task<DataOutput<IEnumerable<T>>> FindAsync(Expression<Func<T, bool>> predicate,
 65        CancellationToken ct = default) =>
 466        GuardedAsync<IEnumerable<T>>(async () => await FindFluent(Builders<T>.Filter.Where(predicate)).ToListAsync(ct).C
 67
 68    /// <inheritdoc />
 69    public Task<DataOutput<string>> CreateAsync(T document, CancellationToken ct = default) =>
 2470        GuardedAsync(async () =>
 2471        {
 2472            EnsureId(document);
 2473            await InsertOneAsync(document, ct).ConfigureAwait(false);
 2474            return document.Id;
 4875        });
 76
 77    /// <inheritdoc />
 78    public Task<DataOutput<IEnumerable<string>>> CreateRangeAsync(IEnumerable<T> documents,
 79        CancellationToken ct = default) =>
 680        GuardedAsync<IEnumerable<string>>(async () =>
 681        {
 682            var list = documents.ToList();
 2883            foreach (var d in list)
 684            {
 885                EnsureId(d);
 686            }
 687
 688            if (list.Count > 0)
 689            {
 490                await InsertManyAsync(list, ct).ConfigureAwait(false);
 691            }
 692
 1493            return list.Select(d => d.Id).ToList();
 1294        });
 95
 96    /// <inheritdoc />
 97    public Task<DataOutput<T>> UpdateAsync(T document, CancellationToken ct = default) =>
 1098        GuardedAsync(async () =>
 1099        {
 10100            await ReplaceAsync(document, ct).ConfigureAwait(false);
 8101            return document;
 18102        });
 103
 104    /// <inheritdoc />
 105    public Task<DataOutput<IEnumerable<T>>>
 106        UpdateRangeAsync(IEnumerable<T> documents, CancellationToken ct = default) =>
 2107        GuardedAsync<IEnumerable<T>>(async () =>
 2108        {
 2109            var list = documents.ToList();
 10110            foreach (var d in list)
 2111            {
 4112                await ReplaceAsync(d, ct).ConfigureAwait(false);
 2113            }
 2114
 0115            return list;
 2116        });
 117
 118    /// <inheritdoc />
 119    public Task<DataOutput<string>> DeleteAsync(T document, CancellationToken ct = default) =>
 6120        GuardedAsync(async () =>
 6121        {
 6122            await DeleteOneAsync(document, ct).ConfigureAwait(false);
 4123            return document.Id;
 10124        });
 125
 126    /// <inheritdoc />
 127    public Task<DataOutput<IEnumerable<string>>> DeleteRangeAsync(IEnumerable<string> ids,
 128        CancellationToken ct = default) =>
 6129        GuardedAsync<IEnumerable<string>>(async () =>
 6130        {
 6131            var candidates = ExistingIdCandidates(ids);
 6132            if (candidates.Count == 0)
 6133            {
 0134                return [];
 6135            }
 6136
 6137            var found = await FindFluent(Builders<T>.Filter.In(d => d.Id, candidates)).Project(d => d.Id)
 6138                .ToListAsync(ct).ConfigureAwait(false);
 6139            if (found.Count > 0)
 6140            {
 4141                await DeleteManyAsync(Builders<T>.Filter.In(d => d.Id, found), ct).ConfigureAwait(false);
 6142            }
 6143
 6144            return InRequestOrder(candidates, found);
 12145        });
 146
 147    /// <inheritdoc />
 2148    public IQueryable<T> Query() => Collection.AsQueryable();
 149
 150    /// <inheritdoc />
 151    public DataOutput<IEnumerable<T>> GetAll() =>
 20152        Guarded(IEnumerable<T> () => FindFluent(FilterDefinition<T>.Empty).ToList());
 153
 154    /// <inheritdoc />
 155    public DataOutput<T?> GetById(string id) =>
 36156        Guarded<T?>(() => IsObjectId(id) ? FindFluent(IdFilter(id)).FirstOrDefault() : null);
 157
 158    /// <inheritdoc />
 159    public DataOutput<IEnumerable<T>> Find(Expression<Func<T, bool>> predicate) =>
 4160        Guarded(IEnumerable<T> () => FindFluent(Builders<T>.Filter.Where(predicate)).ToList());
 161
 162    /// <inheritdoc />
 24163    public DataOutput<string> Create(T document) => Guarded(() =>
 24164    {
 24165        EnsureId(document);
 24166        InsertOne(document);
 20167        return document.Id;
 24168    });
 169
 170    /// <inheritdoc />
 6171    public DataOutput<IEnumerable<string>> CreateRange(IEnumerable<T> documents) => Guarded(IEnumerable<string> () =>
 6172    {
 6173        var list = documents.ToList();
 28174        foreach (var d in list)
 6175        {
 8176            EnsureId(d);
 6177        }
 6178
 6179        if (list.Count > 0)
 6180        {
 4181            InsertMany(list);
 6182        }
 6183
 14184        return list.Select(d => d.Id).ToList();
 6185    });
 186
 187    /// <inheritdoc />
 14188    public DataOutput<T> Update(T document) => Guarded(() =>
 14189    {
 14190        Replace(document);
 8191        return document;
 14192    });
 193
 194    /// <inheritdoc />
 0195    public DataOutput<IEnumerable<T>> UpdateRange(IEnumerable<T> documents) => Guarded(IEnumerable<T> () =>
 0196    {
 0197        var list = documents.ToList();
 0198        foreach (var d in list)
 0199        {
 0200            Replace(d);
 0201        }
 0202
 0203        return list;
 0204    });
 205
 206    /// <inheritdoc />
 4207    public DataOutput<string> Delete(T document) => Guarded(() =>
 4208    {
 4209        DeleteOne(document);
 2210        return document.Id;
 4211    });
 212
 213    /// <inheritdoc />
 4214    public DataOutput<IEnumerable<string>> DeleteRange(IEnumerable<string> ids) => Guarded(IEnumerable<string> () =>
 4215    {
 4216        var candidates = ExistingIdCandidates(ids);
 4217        if (candidates.Count == 0)
 4218        {
 0219            return [];
 4220        }
 4221
 4222        var found = FindFluent(Builders<T>.Filter.In(d => d.Id, candidates)).Project(d => d.Id).ToList();
 4223        if (found.Count > 0)
 4224        {
 4225            DeleteMany(Builders<T>.Filter.In(d => d.Id, found));
 4226        }
 4227
 4228        return InRequestOrder(candidates, found);
 4229    });
 230
 231    // --- session-aware driver helpers (sync) ---
 66232    private static FilterDefinition<T> IdFilter(string id) => Builders<T>.Filter.Eq(d => d.Id, id);
 233
 234    // Document.Id is stored as an ObjectId, so a string that is not one cannot match any document. It is
 235    // answered as not-found rather than sent to the server, where serializing the filter would fail.
 54236    private static bool IsObjectId(string? id) => ObjectId.TryParse(id, out _);
 237
 238    private static List<string> ExistingIdCandidates(IEnumerable<string> ids) =>
 10239        ids.Where(IsObjectId).Distinct().ToList();
 240
 241    private static List<string> InRequestOrder(List<string> requested, List<string> found)
 242    {
 10243        var deleted = found.ToHashSet();
 10244        return requested.Where(deleted.Contains).ToList();
 245    }
 246
 247    // A versioned document is deleted only at the version the caller holds, as the relational and
 248    // DynamoDB repositories do; a stale delete is a concurrency conflict rather than a silent removal of
 249    // someone else's newer write. A plain document's delete stays idempotent.
 250    private static FilterDefinition<T> DeleteFilter(T document) =>
 10251        document is VersionedDocument versioned
 10252            ? Builders<T>.Filter.And(IdFilter(document.Id),
 10253                Builders<T>.Filter.Eq(VersionElementName, versioned.Version))
 10254            : IdFilter(document.Id);
 255
 256    private static void EnsureDeleted(T document, DeleteResult result)
 257    {
 10258        if (document is VersionedDocument && result.IsAcknowledged && result.DeletedCount == 0)
 259        {
 4260            throw new MongoConcurrencyException();
 261        }
 6262    }
 263
 264    private void DeleteOne(T document)
 265    {
 4266        var filter = DeleteFilter(document);
 4267        EnsureDeleted(document, Session is { } s ? Collection.DeleteOne(s, filter) : Collection.DeleteOne(filter));
 2268    }
 269
 270    private static void EnsureId(T document)
 271    {
 64272        if (string.IsNullOrEmpty(document.Id))
 273        {
 56274            document.Id = ObjectId.GenerateNewId().ToString();
 275        }
 64276    }
 277
 278    private IFindFluent<T, T> FindFluent(FilterDefinition<T> filter) =>
 64279        Session is { } s ? Collection.Find(s, filter) : Collection.Find(filter);
 280
 281    private void InsertOne(T document)
 282    {
 24283        if (Session is { } s)
 284        {
 0285            Collection.InsertOne(s, document);
 286        }
 287        else
 288        {
 24289            Collection.InsertOne(document);
 290        }
 20291    }
 292
 293    private void InsertMany(IEnumerable<T> documents)
 294    {
 4295        if (Session is { } s)
 296        {
 0297            Collection.InsertMany(s, documents);
 298        }
 299        else
 300        {
 4301            Collection.InsertMany(documents);
 302        }
 4303    }
 304
 305    private void DeleteMany(FilterDefinition<T> filter)
 306    {
 4307        if (Session is { } s)
 308        {
 0309            Collection.DeleteMany(s, filter);
 310        }
 311        else
 312        {
 4313            Collection.DeleteMany(filter);
 314        }
 4315    }
 316
 317    // Replace with optimistic-concurrency handling for VersionedDocument.
 318    private void Replace(T document)
 319    {
 14320        if (document is VersionedDocument versioned)
 321        {
 10322            var expected = versioned.Version;
 10323            versioned.Version = expected + 1;
 10324            var filter = Builders<T>.Filter.And(IdFilter(document.Id),
 10325                Builders<T>.Filter.Eq(VersionElementName, expected));
 326
 327            ReplaceOneResult result;
 328            try
 329            {
 10330                result = ReplaceOne(filter, document);
 10331            }
 0332            catch
 333            {
 334                // The write never landed, so the in-memory bump must not survive: keeping it would
 335                // make every retry filter on a version the server never stored.
 0336                versioned.Version = expected;
 0337                throw;
 338            }
 339
 10340            if (result.MatchedCount == 0)
 341            {
 4342                versioned.Version = expected; // roll back the in-memory bump on a failed (stale) update
 4343                throw new MongoConcurrencyException();
 344            }
 345
 6346            return;
 347        }
 348
 4349        EnsureMatched(ReplaceOne(IdFilter(document.Id), document));
 2350    }
 351
 352    // Update replaces an existing document. One that matched nothing was removed by another process (or
 353    // never existed), which the relational repository reports as a concurrency conflict too - so this one
 354    // does, instead of reporting a write that never happened as a success.
 355    private static void EnsureMatched(ReplaceOneResult result)
 356    {
 14357        if (result.IsAcknowledged && result.MatchedCount == 0)
 358        {
 6359            throw new MongoConcurrencyException();
 360        }
 8361    }
 362
 363    private ReplaceOneResult ReplaceOne(FilterDefinition<T> filter, T document) =>
 14364        Session is { } s ? Collection.ReplaceOne(s, filter, document) : Collection.ReplaceOne(filter, document);
 365
 366    /// <summary>Runs a synchronous operation, converting failures to envelope errors.</summary>
 367    /// <param name="operation">The operation to run.</param>
 368    /// <param name="operationName">The calling repository method, used as log context.</param>
 369    protected DataOutput<TResult> Guarded<TResult>(Func<TResult> operation,
 370        [CallerMemberName] string operationName = "")
 371    {
 372        try
 373        {
 82374            return DataOutput<TResult>.New.WithData(operation());
 375        }
 0376        catch (OperationCanceledException)
 377        {
 0378            throw;
 379        }
 12380        catch (Exception ex)
 381        {
 12382            return Fail<TResult>(ex, operationName);
 383        }
 82384    }
 385
 386    // --- session-aware driver helpers (async) ---
 387    private Task InsertOneAsync(T document, CancellationToken ct) =>
 24388        Session is { } s
 24389            ? Collection.InsertOneAsync(s, document, null, ct)
 24390            : Collection.InsertOneAsync(document, null, ct);
 391
 392    private Task InsertManyAsync(IEnumerable<T> documents, CancellationToken ct) =>
 4393        Session is { } s
 4394            ? Collection.InsertManyAsync(s, documents, null, ct)
 4395            : Collection.InsertManyAsync(documents, null, ct);
 396
 397    private Task DeleteManyAsync(FilterDefinition<T> filter, CancellationToken ct) =>
 4398        Session is { } s ? Collection.DeleteManyAsync(s, filter, null, ct) : Collection.DeleteManyAsync(filter, ct);
 399
 400    private async Task DeleteOneAsync(T document, CancellationToken ct)
 401    {
 6402        var filter = DeleteFilter(document);
 6403        EnsureDeleted(document, Session is { } s
 6404            ? await Collection.DeleteOneAsync(s, filter, null, ct).ConfigureAwait(false)
 6405            : await Collection.DeleteOneAsync(filter, ct).ConfigureAwait(false));
 4406    }
 407
 408    private async Task ReplaceAsync(T document, CancellationToken ct)
 409    {
 14410        if (document is VersionedDocument versioned)
 411        {
 4412            var expected = versioned.Version;
 4413            versioned.Version = expected + 1;
 4414            var filter = Builders<T>.Filter.And(IdFilter(document.Id),
 4415                Builders<T>.Filter.Eq(VersionElementName, expected));
 416            ReplaceOneResult result;
 417            try
 418            {
 4419                result = Session is { } s
 4420                    ? await Collection.ReplaceOneAsync(s, filter, document, cancellationToken: ct).ConfigureAwait(false)
 4421                    : await Collection.ReplaceOneAsync(filter, document, cancellationToken: ct).ConfigureAwait(false);
 4422            }
 0423            catch
 424            {
 425                // The write never landed, so the in-memory bump must not survive: keeping it would
 426                // make every retry filter on a version the server never stored.
 0427                versioned.Version = expected;
 0428                throw;
 429            }
 430
 4431            if (result.MatchedCount == 0)
 432            {
 0433                versioned.Version = expected; // roll back the in-memory bump on a failed (stale) update
 0434                throw new MongoConcurrencyException();
 435            }
 436
 4437            return;
 438        }
 439
 10440        var idFilter = IdFilter(document.Id);
 10441        var replaced = Session is { } session
 10442            ? await Collection.ReplaceOneAsync(session, idFilter, document, cancellationToken: ct).ConfigureAwait(false)
 10443            : await Collection.ReplaceOneAsync(idFilter, document, cancellationToken: ct).ConfigureAwait(false);
 444
 10445        EnsureMatched(replaced);
 10446    }
 447
 448    /// <summary>Runs an asynchronous operation, converting failures to envelope errors.</summary>
 449    /// <param name="operation">The operation to run.</param>
 450    /// <param name="operationName">The calling repository method, used as log context.</param>
 451    protected async Task<DataOutput<TResult>> GuardedAsync<TResult>(Func<Task<TResult>> operation,
 452        [CallerMemberName] string operationName = "")
 453    {
 454        try
 455        {
 82456            return DataOutput<TResult>.New.WithData(await operation().ConfigureAwait(false));
 457        }
 0458        catch (OperationCanceledException)
 459        {
 0460            throw;
 461        }
 6462        catch (Exception ex)
 463        {
 6464            return Fail<TResult>(ex, operationName);
 465        }
 82466    }
 467
 468    /// <summary>
 469    ///     Logs the failure when a logger is configured, and maps it to an error envelope.
 470    ///     Driver text names indexes, collections, key values and cluster endpoints, so it goes to
 471    ///     the log and never to the caller.
 472    /// </summary>
 473    /// <param name="ex">The exception caught by a guard.</param>
 474    /// <param name="operationName">The repository method that failed, used as log context.</param>
 475    protected DataOutput<TResult> Fail<TResult>(Exception ex, string operationName = "")
 476    {
 477        // A concurrency conflict is an expected outcome of optimistic locking, not an operational
 478        // fault: logging it at Error would fill the log with routine contention.
 18479        var level = ex is MongoConcurrencyException ? LogLevel.Debug : LogLevel.Error;
 480
 18481        logger?.Log(level, ex, "Mongo operation failed. Document: {Document}, operation: {Operation}",
 18482            typeof(T).Name, operationName);
 483
 18484        return DataOutput<TResult>.New.WithError(MongoErrors.Describe(ex));
 485    }
 486}

Methods/Properties

.ctor(ArturRios.Data.MongoDb.MongoContext,Microsoft.Extensions.Logging.ILogger`1<ArturRios.Data.MongoDb.Repositories.MongoDocumentRepository`1<T>>)
.cctor()
get_Collection()
get_Session()
GetAllAsync(System.Threading.CancellationToken)
GetByIdAsync(System.String,System.Threading.CancellationToken)
FindAsync(System.Linq.Expressions.Expression`1<System.Func`2<T,System.Boolean>>,System.Threading.CancellationToken)
CreateAsync(T,System.Threading.CancellationToken)
CreateRangeAsync(System.Collections.Generic.IEnumerable`1<T>,System.Threading.CancellationToken)
UpdateAsync(T,System.Threading.CancellationToken)
UpdateRangeAsync(System.Collections.Generic.IEnumerable`1<T>,System.Threading.CancellationToken)
DeleteAsync(T,System.Threading.CancellationToken)
DeleteRangeAsync(System.Collections.Generic.IEnumerable`1<System.String>,System.Threading.CancellationToken)
Query()
GetAll()
GetById(System.String)
Find(System.Linq.Expressions.Expression`1<System.Func`2<T,System.Boolean>>)
Create(T)
CreateRange(System.Collections.Generic.IEnumerable`1<T>)
Update(T)
UpdateRange(System.Collections.Generic.IEnumerable`1<T>)
Delete(T)
DeleteRange(System.Collections.Generic.IEnumerable`1<System.String>)
IdFilter(System.String)
IsObjectId(System.String)
ExistingIdCandidates(System.Collections.Generic.IEnumerable`1<System.String>)
InRequestOrder(System.Collections.Generic.List`1<System.String>,System.Collections.Generic.List`1<System.String>)
DeleteFilter(T)
EnsureDeleted(T,MongoDB.Driver.DeleteResult)
DeleteOne(T)
EnsureId(T)
FindFluent(MongoDB.Driver.FilterDefinition`1<T>)
InsertOne(T)
InsertMany(System.Collections.Generic.IEnumerable`1<T>)
DeleteMany(MongoDB.Driver.FilterDefinition`1<T>)
Replace(T)
EnsureMatched(MongoDB.Driver.ReplaceOneResult)
ReplaceOne(MongoDB.Driver.FilterDefinition`1<T>,T)
Guarded(System.Func`1<TResult>,System.String)
InsertOneAsync(T,System.Threading.CancellationToken)
InsertManyAsync(System.Collections.Generic.IEnumerable`1<T>,System.Threading.CancellationToken)
DeleteManyAsync(MongoDB.Driver.FilterDefinition`1<T>,System.Threading.CancellationToken)
DeleteOneAsync()
ReplaceAsync()
GuardedAsync()
Fail(System.Exception,System.String)