.net driver : Best practices to avoid first slow query

Hi,

I’m trying to apply best practices for wrapping the IMongoClient into a repository.

It works but I always encounter the same problem : the first query is slow. Indeed when launching my container, first query takes 500ms to 1s and all following calls take less than 50ms. I don’t know it’s should be normal (using some kind of caching for next calls) or if I did a mistake in my repository approach.

Basically for the IMongoClient, I register the DI this way (note that I initiate a scoped IClientSessionHandle is it a good practice to handle transaction or should I initiate it once I need it only ?)

           services.AddSingleton<IMongoClient>(c =>
            {
                return new MongoClient(configuration.ConnectionString);
            });        
    
services.AddScoped(c =>
                c.GetService<IMongoClient>().StartSession()); // IClientSessionHandle scoped

Then I basically inject these object into an abstract repository

    public abstract class MongoRepository<T> : IMongoRepository<T> where T : BaseClass<string>
    {
        private readonly IMongoClient _mongoClient;
        private readonly IClientSessionHandle _clientSessionHandle;
        private readonly string _collection;
        private readonly string _databaseName;
        public IMongoCollection<T> Collection { get; }
        public MongoRepository(IMongoClient mongoClient, IClientSessionHandle clientSessionHandle, string databaseName , string collection)
        {
            if (string.IsNullOrWhiteSpace(collection))
                throw new ArgumentNullException(nameof(collection));            if (string.IsNullOrWhiteSpace(databaseName))
                throw new ArgumentNullException(nameof(databaseName));            (_mongoClient, _clientSessionHandle, _databaseName, _collection) = (mongoClient, clientSessionHandle, databaseName, collection);            
if (!_mongoClient.GetDatabase(_databaseName).ListCollectionNames().ToList().Contains(_collection))
                _mongoClient.GetDatabase(_databaseName).CreateCollection(_collection);            Collection = _mongoClient.GetDatabase(_databaseName).GetCollection<T>(_collection);
        }

Then any strongly typed repository inheriting it are scoped in DI

services.AddScoped<ICatalogReferencesRepository, CatalogReferencesRepository>();

    public class CatalogReferencesRepository : MongoRepository<CatalogReferencesSubset>, ICatalogReferencesRepository
    {
        private readonly IServiceScopeFactory _scopeFactory;
        private readonly ILogger<CatalogReferencesRepository> _logger;
        private readonly IOptionsMonitor<AvailabilitySettings> _availabilitySettings;        public CatalogReferencesRepository(
            SharedLibraries.MongoDB.Configuration configuration,
            IMongoClient mongoClient, 
            IClientSessionHandle clientSessionHandle,
            IServiceScopeFactory scopeFactory,
            ILogger<CatalogReferencesRepository> logger,
            IOptionsMonitor<AvailabilitySettings> availabilitySettings) : base(mongoClient, clientSessionHandle, configuration.DatabaseNameSubset, "catalog_references")
        {
            _scopeFactory = scopeFactory;
            _logger = logger;
            _availabilitySettings = availabilitySettings;
        }

Well, I tried to :

  • inject the repository as Singleton
  • warm up the singleton repository in startup (let’s say with a count in the target collection)

And I always fall with the same behavior : first call in 10x slower than following same queries. Note my collection is less than 22k records.

Could you please tell me what’s I’m doing wrong and how get rid of the extra time for first query (if doable) ?

Thank you very much