ASP.NET Core 中的通用 MongoDB 存储库模式

作者:微信公众号:【架构师老卢】
3-16 9:53
88

在现代软件开发中,与各种数据存储解决方案进行交互是很常见的,而 MongoDB 是流行的选择之一,尤其是在灵活性和可扩展性至关重要的场景中。使用 ASP.NET Core 开发应用程序时,拥有结构良好的数据访问层对于可维护性和可扩展性至关重要。在本文中,我们将探讨如何在 ASP.NET Core 中利用 MongoDB .NET 驱动程序实现通用 MongoDB 存储库模式。

了解存储库模式

存储库模式是一种设计模式,它将从基础数据存储中检索数据的逻辑与应用程序的其余部分分开。它提供了比数据访问操作更高级别的抽象,使应用程序代码更加模块化和可测试。存储库模式的关键组件包括:

  • 存储库接口:定义与数据存储交互的协定。
  • 具体存储库实现:实现存储库接口,并包含 CRUD(创建、读取、更新、删除)操作的逻辑。

构建通用 MongoDB 存储库

为了在 ASP.NET Core 中实现 MongoDB 的存储库模式,我们将创建一个可用于任何类型的实体的通用存储库类。让我们分解一下实现的组件:

1. 存储库接口

我们定义存储库接口如下:IRepository<T>

public interface IRepository<T>  
{  
    Task<IEnumerable<T>> GetAllAsync(ProjectionDefinition<T> project, int limit);  
    Task<T> GetByIdAsync(string id);  
    Task<IEnumerable<T>> GetAllAsync(FilterDefinition<T> filter, ProjectionDefinition<T> projection, int limit);  
    Task<T> CreateAsync(T entity);  
    Task UpdateAsync(string id, T entity);  
    Task DeleteAsync(string id);  
}

此接口指定可对任何实体类型执行的常见 CRUD 操作。T

2. 具体存储库实现

我们的具体存储库实现 利用 MongoDB .NET 驱动程序与 MongoDB 数据库进行交互。这是它的样子:MongoRepository<T>

using MongoDB.Driver;

    public class MongoRepository<T> : IRepository<T>
    {
        FilterDefinitionBuilder<T> _filterBuilder;
        private readonly IMongoCollection<T> _collection;

        /// <summary>
        /// Initializes a new instance of the MongoRepository class.
        /// </summary>
        /// <param name="database">MongoDB database instance.</param>
        /// <param name="collectionName">Name of the collection.</param>
        public MongoRepository(IMongoDatabase database, string collectionName)
        {
            _collection = database.GetCollection<T>(collectionName);
            _filterBuilder = new FilterDefinitionBuilder<T>();
        }

        /// <summary>
        /// Retrieves all documents from the collection.
        /// </summary>
        /// <returns>A list of entities.</returns>
        public async Task<IEnumerable<T>> GetAllAsync(ProjectionDefinition<T> project, int limit)
        {
            return await _collection.Find(_ => true).Project<T>(project).Limit(limit).ToListAsync();
        }

        /// <summary>
        /// Retrieves a document by its unique identifier.
        /// </summary>
        /// <param name="id">Unique identifier of the document.</param>
        /// <returns>The entity corresponding to the provided identifier, or null if not found.</returns>
        public async Task<T> GetByIdAsync(string id)
        {
            var filter = Builders<T>.Filter.Eq("_id", id);
            return await _collection.Find(filter).FirstOrDefaultAsync();
        }

        /// <summary>
        /// Retrieves documents from the collection based on a filter.
        /// </summary>
        /// <param name="filter">Filter definition to apply.</param>
        /// <returns>A list of entities matching the filter.</returns>
        public async Task<IEnumerable<T>> GetAllAsync(FilterDefinition<T> filter, ProjectionDefinition<T> projection, int limit)
        {
            var query = _collection.Find(filter).Limit(limit);

            if (projection != null)
                query = query.Project<T>(projection);

            return await query.ToListAsync();
        }

        /// <summary>
        /// Creates a new document in the collection.
        /// </summary>
        /// <param name="entity">Entity to be created.</param>
        /// <returns>The created entity.</returns>
        public async Task<T> CreateAsync(T entity)
        {
            await _collection.InsertOneAsync(entity);
            return entity;
        }

        /// <summary>
        /// Updates an existing document in the collection.
        /// </summary>
        /// <param name="id">Unique identifier of the document to update.</param>
        /// <param name="entity">Updated entity.</param>
        public async Task UpdateAsync(string id, T entity)
        {
            var filter = Builders<T>.Filter.Eq("_id", id);
            await _collection.ReplaceOneAsync(filter, entity);
        }

        /// <summary>
        /// Deletes a document from the collection.
        /// </summary>
        /// <param name="id">Unique identifier of the document to delete.</param>
        public async Task DeleteAsync(string id)
        {
            var filter = Builders<T>.Filter.Eq("_id", id);
            await _collection.DeleteOneAsync(filter);
        }        
    }

在此实现中:

  • 我们将 的实例和集合名称注入构造函数中。IMongoDatabase
  • 我们利用 MongoDB .NET 驱动程序提供的接口与集合进行交互。IMongoCollection<T>
  • 我们使用 MongoDB .NET 驱动程序的功能实现接口中定义的方法,用于 CRUD 操作。IRepository<T>

3. 使用示例

现在,让我们看看如何在典型的 ASP.NET Core 应用程序中使用通用 MongoDB 存储库:

public class CarService
{
    private readonly IRepository<CarEntity> _repository;

    public ExampleService(IRepository<CarEntity> repository)
    {
        _repository = repository;
    }

    public async Task<IEnumerable<CarEntity>> GetAllExamples()
    {
        return await _repository.GetAllAsync(null, 10);
    }
}

在此示例中,是要使用的任何实体类型的占位符。CarEntity

让我们不要忘记program.cs和应用程序设置

public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                })
                .ConfigureServices((hostContext, services) =>
                {
                    // Configure MongoDB
                    var mongoConnectionString = hostContext.Configuration.GetConnectionString("MongoDB");
                    var mongoClient = new MongoClient(mongoConnectionString);
                    var mongoDatabase = mongoClient.GetDatabase("YourDatabaseName");

                    // Register MongoDB repository
                    services.AddSingleton<IMongoDatabase>(mongoDatabase);
                    services.AddScoped(typeof(IRepository<>), typeof(MongoRepository<>));
                });
    }
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "MongoDB": "mongodb://localhost:27017"
  }
}

结论

在 ASP.NET Core 中实现通用 MongoDB 存储库模式提供了一种干净的模块化数据访问方法,从而提高了代码的可重用性和可测试性。通过将数据访问逻辑与应用程序的其余部分分开,您可以轻松地在不同的数据存储解决方案之间切换或更改基础数据访问代码,而不会影响整个应用程序结构。提供的实现为构建具有 MongoDB 集成的可扩展和可维护 ASP.NET 核心应用程序奠定了坚实的基础。

相关留言评论
昵称:
邮箱:
阅读排行