前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >.NET MongoDB数据仓储和工作单元模式封装

.NET MongoDB数据仓储和工作单元模式封装

作者头像
郑子铭
发布2025-01-22 14:06:19
发布2025-01-22 14:06:19
9500
代码可运行
举报
运行总次数:0
代码可运行

一、引言

在.NET开发中,MongoDB作为一种高性能、灵活的NoSQL数据库,常用于存储和管理大量数据。为了更好地组织代码结构,提高开发效率和代码可维护性,可以将数据访问层与业务逻辑层解耦,使用数据仓储(Repository)模式和工作单元(UnitOfWork)模式来封装MongoDB数据库操作。数据仓储模式通过抽象出通用的CRUD方法,使业务逻辑层无需关心数据的存储细节;工作单元模式则负责协调多个仓储操作,统一管理事务,确保数据的一致性。

二、安装MongoDB.Driver

首先,需要安装MongoDB的官方.NET驱动程序MongoDB.Driver。可以通过NuGet包管理器进行安装:

代码语言:javascript
代码运行次数:0
复制
dotnet add package MongoDB.Driver

或者使用Package Manager:

代码语言:javascript
代码运行次数:0
复制
Install-Package MongoDB.Driver

三、定义MongoDB上下文

创建一个MongoDB上下文类,用于封装数据库连接和集合的获取。例如:

代码语言:javascript
代码运行次数:0
复制
public classMongoContext : IDisposable
{
    privatereadonly IMongoDatabase _database;
    privatereadonly MongoClient _client;

    public MongoContext(string connectionString, string databaseName)
    {
        _client = new MongoClient(connectionString);
        _database = _client.GetDatabase(databaseName);
    }

    public IMongoCollection<T> GetCollection<T>(string collectionName)
    {
        return _database.GetCollection<T>(collectionName);
    }

    public void Dispose()
    {
        _client.Dispose();
    }
}

这里使用IMongoDatabase接口来获取MongoDB数据库实例,并提供了GetCollection方法来获取指定集合。

四、定义数据仓储接口和实现

数据仓储接口定义了通用的CRUD操作方法,例如:

代码语言:javascript
代码运行次数:0
复制
public interface IRepository<T> where T : class
{
    Task AddAsync(T entity);
    Task<IEnumerable<T>> GetAllAsync();
    Task<T> GetByIdAsync(string id);
    Task UpdateAsync(T entity);
    Task DeleteAsync(string id);
}

然后实现该接口,创建一个具体的仓储类:

代码语言:javascript
代码运行次数:0
复制
public classRepository<T> : IRepository<T> whereT : class
{
    privatereadonly IMongoCollection<T> _collection;

    public Repository(IMongoCollection<T> collection)
    {
        _collection = collection;
    }

    public async Task AddAsync(T entity)
    {
        await _collection.InsertOneAsync(entity);
    }

    publicasync Task<IEnumerable<T>> GetAllAsync()
    {
        returnawait _collection.Find(Builders<T>.Filter.Empty).ToListAsync();
    }

    public async Task<T> GetByIdAsync(string id)
    {
        var filter = Builders<T>.Filter.Eq("_id", id);
        returnawait _collection.Find(filter).FirstOrDefaultAsync();
    }

    public async Task UpdateAsync(T entity)
    {
        var filter = Builders<T>.Filter.Eq("_id", entity.GetType().GetProperty("_id").GetValue(entity));
        await _collection.ReplaceOneAsync(filter, entity);
    }

    public async Task DeleteAsync(string id)
    {
        var filter = Builders<T>.Filter.Eq("_id", id);
        await _collection.DeleteOneAsync(filter);
    }
}

这里使用了MongoDB.Driver提供的API来实现具体的CRUD操作。

五、实现工作单元模式

工作单元模式负责协调多个仓储操作,并统一管理事务。定义一个工作单元接口:

代码语言:javascript
代码运行次数:0
复制
public interface IUnitOfWork : IDisposable
{
    Task<int> CommitAsync();
    void RegisterNew<T>(T entity) where T : class;
    void RegisterModified<T>(T entity) where T : class;
    void RegisterDeleted<T>(T entity) where T : class;
}

然后实现该接口,创建一个工作单元类:

代码语言:javascript
代码运行次数:0
复制
public classUnitOfWork : IUnitOfWork
{
    privatereadonly MongoContext _context;
    privatereadonly List<Func<Task>> _commands = new List<Func<Task>>();

    public UnitOfWork(MongoContext context)
    {
        _context = context;
    }

    public async Task<int> CommitAsync()
    {
        using (var session = await _context.Client.StartSessionAsync())
        {
            session.StartTransaction();
            try
            {
                foreach (var command in _commands)
                {
                    await command();
                }
                await session.CommitTransactionAsync();
                return _commands.Count;
            }
            catch (Exception)
            {
                await session.AbortTransactionAsync();
                return0;
            }
            finally
            {
                _commands.Clear();
            }
        }
    }

    publicvoid RegisterNew<T>(T entity) where T : class
    {
        _commands.Add(async () => await _context.GetCollection<T>(typeof(T).Name).InsertOneAsync(entity));
    }

    publicvoid RegisterModified<T>(T entity) where T : class
    {
        var filter = Builders<T>.Filter.Eq("_id", entity.GetType().GetProperty("_id").GetValue(entity));
        _commands.Add(async () => await _context.GetCollection<T>(typeof(T).Name).ReplaceOneAsync(filter, entity));
    }

    publicvoid RegisterDeleted<T>(T entity) where T : class
    {
        var filter = Builders<T>.Filter.Eq("_id", entity.GetType().GetProperty("_id").GetValue(entity));
        _commands.Add(async () => await _context.GetCollection<T>(typeof(T).Name).DeleteOneAsync(filter));
    }

    public void Dispose()
    {
        _context.Dispose();
    }
}

这里使用了MongoDB的事务功能来确保多个操作的原子性。

六、使用示例

以下是如何使用封装好的数据仓储和工作单元模式进行数据库操作的示例:

代码语言:javascript
代码运行次数:0
复制
// 创建MongoDB上下文
var context = new MongoContext("mongodb://localhost:27017", "YourDatabaseName");

// 创建工作单元实例
var unitOfWork = new UnitOfWork(context);

// 创建仓储实例
var userRepository = new Repository<User>(context.GetCollection<User>("Users"));

// 添加用户
var newUser = new User { Name = "张三", Email = "zhangsan@example.com" };
unitOfWork.RegisterNew(newUser);

// 更新用户
var userToUpdate = await userRepository.GetByIdAsync("existingUserId");
userToUpdate.Email = "updated@example.com";
unitOfWork.RegisterModified(userToUpdate);

// 删除用户
unitOfWork.RegisterDeleted(new User { Id = "userIdToDelete" });

// 提交事务
await unitOfWork.CommitAsync();

通过这种方式,可以方便地进行数据库的CRUD操作,并且确保了数据的一致性。

七、总结

通过封装.NET MongoDB的数据仓储和工作单元模式,可以有效地解耦业务逻辑层与数据访问层,提高代码的可维护性和可重用性。同时,工作单元模式的引入,使得在处理复杂的业务场景时,能够更好地管理事务,确保数据的一致性和完整性。在实际开发中,可以根据具体需求对这些封装进行扩展和优化,以满足不同的业务需求。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-01-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、引言
  • 二、安装MongoDB.Driver
  • 三、定义MongoDB上下文
  • 四、定义数据仓储接口和实现
  • 五、实现工作单元模式
  • 六、使用示例
  • 七、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档