public virtual async Task <long> ReplaceMany(IEnumerable <T> entities, bool isUpsert, CancellationToken token = default)
        {
            if (entities.Count() == 0)
            {
                return(0);
            }

            var requests = new List <WriteModel <T> >();

            Func <object, object> idGetter = FieldDefinitions.GetIdFieldGetter(typeof(T));

            foreach (T entity in entities)
            {
                ObjectId entityId = (ObjectId)idGetter.Invoke(entity);
                var      filter   = Builders <T> .Filter.Eq("_id", entityId);

                requests.Add(new ReplaceOneModel <T>(filter, entity)
                {
                    IsUpsert = isUpsert
                });
            }

            // BulkWrite
            var options = new BulkWriteOptions()
            {
                IsOrdered = false
            };

            BulkWriteResult <T> bulkResult = await _collection
                                             .BulkWriteAsync(requests, options, cancellationToken : token)
                                             .ConfigureAwait(false);

            return(bulkResult.Upserts.Count + bulkResult.ModifiedCount);
        }
        public virtual Task <T> FindOneAndReplace(T entity, bool isUpsert, ReturnDocument returnDocument = ReturnDocument.Before, CancellationToken token = default)
        {
            Func <object, object> idGetter = FieldDefinitions.GetIdFieldGetter(typeof(T));
            ObjectId entityId = (ObjectId)idGetter.Invoke(entity);
            var      filter   = Builders <T> .Filter.Eq("_id", entityId);

            var options = new FindOneAndReplaceOptions <T>
            {
                ReturnDocument = returnDocument,
                IsUpsert       = isUpsert
            };

            return(_collection.FindOneAndReplaceAsync(filter, entity, options, cancellationToken: token));
        }
        public virtual async Task <long> ReplaceOne(T entity, bool isUpsert, CancellationToken token = default)
        {
            Func <object, object> idGetter = FieldDefinitions.GetIdFieldGetter(typeof(T));
            ObjectId entityId = (ObjectId)idGetter.Invoke(entity);
            var      filter   = Builders <T> .Filter.Eq("_id", entityId);

            var options = new ReplaceOptions
            {
                IsUpsert = isUpsert
            };
            ReplaceOneResult result = await _collection.ReplaceOneAsync(filter, entity, options, cancellationToken : token)
                                      .ConfigureAwait(false);

            return(result.ModifiedCount);
        }
        public Task <long> ReplaceOne(T entity, bool isUpsert, CancellationToken token = default)
        {
            Func <object, object> idGetter = FieldDefinitions.GetIdFieldGetter(typeof(T));
            ObjectId entityId = (ObjectId)idGetter.Invoke(entity);

            T entityToReplace = Collection.Find(x => (ObjectId)idGetter.Invoke(x) == entityId);

            long replaced  = 0;
            bool doReplace = isUpsert || entityToReplace != null;

            if (doReplace)
            {
                replaced = Collection.RemoveAll(x => (ObjectId)idGetter.Invoke(x) == entityId);
                Collection.Add(entity);
            }

            return(Task.FromResult(replaced));
        }
        public async Task <T> FindOneAndReplace(T entity, bool isUpsert, ReturnDocument returnDocument = ReturnDocument.Before, CancellationToken token = default)
        {
            Func <object, object> idGetter = FieldDefinitions.GetIdFieldGetter(typeof(T));
            ObjectId entityId         = (ObjectId)idGetter.Invoke(entity);
            T        collectionEntity = Collection
                                        .Where(x => (ObjectId)idGetter.Invoke(x) == entityId)
                                        .FirstOrDefault();

            T returnedEntity = collectionEntity;

            if (returnDocument == ReturnDocument.Before)
            {
                //Could clone it here if required with AutoMapper or BinarySerializer.
                //However BinarySerializer does not serialize ObjectId.
                returnedEntity = collectionEntity;
            }

            await ReplaceOne(entity, isUpsert, token);

            return(returnedEntity);
        }