using MongoDB.Driver; using MongoDB.Driver.Linq; using MongoDbGenericRepository.DataAccess.Base; using MongoDbGenericRepository.Models; using MongoDbGenericRepository.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace MongoDbGenericRepository.DataAccess.Create { /// /// A class to insert MongoDb document. /// public class MongoDbCreator : DataAccessBase, IMongoDbCreator { /// /// The construct of the MongoDbCreator class. /// /// A instance. public MongoDbCreator(IMongoDbContext mongoDbContext) : base(mongoDbContext) { } #region Create TKey /// /// Asynchronously adds a document to the collection. /// Populates the Id and AddedAtUtc fields if necessary. /// /// The type representing a Document. /// The type of the primary key for a Document. /// The document you want to add. /// An optional cancellation Token. public virtual async Task AddOneAsync(TDocument document, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { FormatDocument(document); await HandlePartitioned(document).InsertOneAsync(document, null, cancellationToken); } /// /// Adds a document to the collection. /// Populates the Id and AddedAtUtc fields if necessary. /// /// The type representing a Document. /// The type of the primary key for a Document. /// The document you want to add. public virtual void AddOne(TDocument document) where TDocument : IDocument where TKey : IEquatable { FormatDocument(document); HandlePartitioned(document).InsertOne(document); } /// /// Asynchronously adds a list of documents to the collection. /// Populates the Id and AddedAtUtc fields if necessary. /// /// The type representing a Document. /// The type of the primary key for a Document. /// The documents you want to add. /// An optional cancellation Token. public virtual async Task AddManyAsync(IEnumerable documents, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { if (!documents.Any()) { return; } foreach (var document in documents) { FormatDocument(document); } // cannot use typeof(IPartitionedDocument).IsAssignableFrom(typeof(TDocument)), not available in netstandard 1.5 if (documents.Any(e => e is IPartitionedDocument)) { foreach (var group in documents.GroupBy(e => ((IPartitionedDocument)e).PartitionKey)) { await HandlePartitioned(group.FirstOrDefault()).InsertManyAsync(group.ToList(), null, cancellationToken); } } else { await GetCollection().InsertManyAsync(documents.ToList(), null, cancellationToken); } } /// /// Adds a list of documents to the collection. /// Populates the Id and AddedAtUtc fields if necessary. /// /// The type representing a Document. /// The type of the primary key for a Document. /// The documents you want to add. public virtual void AddMany(IEnumerable documents) where TDocument : IDocument where TKey : IEquatable { if (!documents.Any()) { return; } foreach (var document in documents) { FormatDocument(document); } // cannot use typeof(IPartitionedDocument).IsAssignableFrom(typeof(TDocument)), not available in netstandard 1.5 if (documents.Any(e => e is IPartitionedDocument)) { foreach (var group in documents.GroupBy(e => ((IPartitionedDocument)e).PartitionKey)) { HandlePartitioned(group.FirstOrDefault()).InsertMany(group.ToList()); } } else { GetCollection().InsertMany(documents.ToList()); } } #endregion /// /// Sets the value of the document Id if it is not set already. /// /// The document type. /// The type of the primary key. /// The document. protected void FormatDocument(TDocument document) where TDocument : IDocument where TKey : IEquatable { if (document == null) { throw new ArgumentNullException(nameof(document)); } var defaultTKey = default(TKey); if (document.Id == null || (defaultTKey != null && defaultTKey.Equals(document.Id))) { document.Id = IdGenerator.GetId(); } } } }