MongoDB的使用

环境

 1. .net core 3.1
 2. MongoDB
 3. Navicat Premium 16

项目

1.选择ASP.NET Core Web API 项目模板

MongoDB的使用_第1张图片


2.配置项目信息 项目名称,项目路径

MongoDB的使用_第2张图片

3.配置项目其它信息,这里选择使用.net core 3.1 不配置https

MongoDB的使用_第3张图片
添加依赖

1.获取MongoDB.Driver包 版本 2.18.0
方案A. install-package MongoDB.Driver
方案B. nuget包管理工具搜索 MongoDB.Driver
方案C. 选中项目,双击,添加
<ItemGroup>
    <PackageReference Include="MongoDB.Driver" Version="2.18.0" />
</ItemGroup>

注册中间件

1.添加配置文件
"MongoDB": {
"ConnName": "mongodb://root:[email protected]:27017/",
"DatabaseName": "test"
}

2.添加配置类
public class MongoDBConfig
{
    /// 
    /// 连接字符串
    /// 
    public string ConnName { get; set; }

    /// 
    /// 数据库名称
    /// 
    public string DatabaseName { get; set; }
}

3.注册配置文件与中间件
//读取配置文件
var mongoDBOptions = Configuration.GetSection("MongoDB").Get<MongoDBConfig>();

//注册配置
services.Configure<MongoDBConfig>(this.Configuration.GetSection("MongoDB"));

//注册中间件
services.AddSingleton(new MongoClient(mongoDBOptions.ConnName));

解释:其实就是注册了一个mongodb的客户端实例,然后用这个客户端实例来实现crud,如果你想优雅点(强迫症),也可以自定义一个拓展,来注册这个实例,这是一个通用技巧,后面使用到的类请自行注册

public static class MongoDBExtensions 
{
    public static void AddMongoDB(this IServiceCollection services, Action<MongoDBConfig> setupAction)
    {
        if (setupAction == null)
        {
            throw new ArgumentNullException(nameof(setupAction));
        }
        var options = new MongoDBConfig();
        setupAction(options);
        services.Configure(setupAction);
        services.AddSingleton(services.AddSingleton(new MongoClient(options.ConnName)));
    }
}

拓展,来注册中间件

var mongoDBOptions = Configuration.GetSection("MongoDB").Get<MongoDBConfig>();
services.AddMongoDB(m => 
{
    m.ConnName = mongoDBOptions.ConnName;
    m.DatabaseName = mongoDBOptions.DatabaseName;
});

封装基础操作
最常用的办法,就是弄个DBHelper类,这种简单粗暴的方式,在.net core里使用

public class BaseDbContext
{
    private readonly IMongoDatabase _database;
    public BaseDbContext(MongoClient client, IOptions<MongoDBConfig> options)
    {
        //决定使用哪个库
        _database = client.GetDatabase(options.Value.DatabaseName);
    }

    /// 
    /// 数据库对象
    /// 
    public IMongoDatabase MongoDatabase { get{ return _database; } }
}

如果项目只操作一个数据库,直接在基类里指定操作的数据库即可,如果需要操作多个数据库,可以再新建一个子类(TestDbContext),在子类里指定要操作的数据库
前面我已经注册了mongodb的客户端跟配置文件,所以在Startup类下,可以直接注册这个类,容器会自动管理这些依赖

services.AddSingleton(typeof(BaseDbContext));

如果你想更优雅点(强迫症),可以创建一个IBaseDbContext 接口,在接口里定义相关的规范

services.AddSingleton<IBaseDbContext>();

3.创建 BaseRepertoty 类
public class BaseRepertoty<T> where T : class, new()
{
    private readonly IMongoDatabase _database;

    private readonly string _collName;

    public BaseRepertoty(BaseDbContext baseDbContext) 
    {
        _database = baseDbContext.MongoDatabase;
        _collName = typeof(T).GetAttributeValue((TableAttribute m) => m.Name);
        _collName = _collName ?? typeof(T).Name;

    }
}

解释:前面我们已经注册了BaseDbContext,它的主要作用是确定操作的库,那BaseRepertoty就是对具体集合(表)的操作,这里使用泛型,避免重复的CRUD操作
我新建了一个拓展,用于获取实体类上真实集合(表)的名称,如果用户没有指定,则取实体类的类名,做为集合(表)的名称

public static class AttributeExtensions
{
    public static TValue GetAttributeValue<TAttribute, TValue>(
        this Type type,
        Func<TAttribute, TValue> valueSelector)
        where TAttribute : Attribute
    {
        var att = type.GetCustomAttributes(
            typeof(TAttribute), true
        ).FirstOrDefault() as TAttribute;
        if (att != null)
        {
            return valueSelector(att);
        }
        return default(TValue);
    }
}

4.创建 UserInfoRepertoty 类
public class UserInfoRepertoty : BaseRepertoty<UserInfo>
{
    public UserInfoRepertoty(BaseDbContext baseDbContext) : base(baseDbContext) 
    {

    }
}

解释:它的作用是指定操作具体的集合(表),这个类是非必须的,它只是指定了泛型的具体类型,也可以在server层调用的时候指定

5.创建 UserInfo 实体类
[Table("UserInfo")]
public class UserInfo
{
    /// 
    /// 主键
    /// 
    [BsonId]
    public ObjectId Id { get; set; }

    /// 
    /// 用户名
    /// 
    public string Name { get; set; }

    /// 
    /// 年龄
    /// 
    public int Age { get; set; }

    /// 
    /// 创建时间
    /// 
    [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
    public DateTime CreateTime { get; set; }

    /// 
    /// 合作伙伴
    /// 
    public List<Partner> PartnerList { get; set; }

    /// 
    /// 其它信息
    /// 
    public Info Info { get; set; }
}



public class Partner
{
    /// 
    /// 伙伴名称
    /// 
    public string Name { get; set; }

    /// 
    /// 合作状态
    /// 
    public int? Status { get; set; }
}


public class Info 
{
    /// 
    /// 身份编码
    /// 
    public string Code { get; set; }

    /// 
    /// 图片
    /// 
    public string Pic { get; set; }
}

解释:mongodb里默认的主键是_id,它会自动生成,类型为ObjectId,强烈推荐使用自动生成,速度快,且能提供获取对应的时间戳的方法

ObjectId 类似唯一主键,可以很快的去生成和排序,包含 12 bytes,含义是:
前4个字节表示创建 unix 时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时
接下来的3个字节是机器标识码
紧接的两个字节由进程 id 组成 PID
最后三个字节是随机数

时间类型要做对应的处理,标记为当前时间

其它常用注解说明

BsonId修饰的字段对应BsonDocument中的_id;
BsonDefaultValue(value)用于指定默认值;
BsonIgnore表示不映射,即使BsonDocument中包含该字段也不会赋值给属性;
BsonExtraElements修饰的字段用于存储没有映射到类中的其他属性;
BsonElement可以指定修饰的属性映射到BsonDocument中的哪个字段;

解释:使用mongodb的一个主要原因,就是它灵活的存储方式,类json,我们就来体验一番,基于这个模型来进行CRUD,我定义的类型如下,基本上能覆盖99%的使用场景

BaseRepertoty类里,实现CRUD,完整代码如下

public class BaseRepertoty<T> where T : class, new()
{
    private readonly IMongoDatabase _database;

    private readonly string _collName;

    public BaseRepertoty(BaseDbContext baseDbContext) 
    {
        _database = baseDbContext.MongoDatabase;
        _collName = typeof(T).GetAttributeValue((TableAttribute m) => m.Name);
        _collName = _collName ?? typeof(T).Name;

    }



    #region Add 添加一条数据
    /// 
    /// 添加一条数据
    /// 
    /// 添加的实体
    /// 
    public bool Add(T t)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            client.InsertOne(t);
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    #endregion

    #region AddAsync 异步添加一条数据
    /// 
    /// 异步添加一条数据
    /// 
    /// 添加的实体
    /// 
    public async Task<bool> AddAsync(T t)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            await client.InsertOneAsync(t);
            return true;
        }
        catch
        {
            return false;
        }
    }
    #endregion

    #region InsertMany 批量插入
    /// 
    /// 批量插入
    /// 
    /// 实体集合
    /// 
    public bool InsertMany(List<T> t)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            client.InsertMany(t);
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    #endregion

    #region InsertManyAsync 异步批量插入
    /// 
    /// 异步批量插入
    /// 
    /// 实体集合
    /// 
    public async Task<bool> InsertManyAsync(List<T> t)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            await client.InsertManyAsync(t);
            return true;
        }
        catch
        {
            return false;
        }
    }
    #endregion

    #region UpdateOne 修改数据(单条)
    /// 
    /// 批量修改数据
    /// 
    /// 要修改的字段
    /// 修改条件
    /// 
    public UpdateResult UpdateOne(UpdateDefinition<T> update, FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return client.UpdateOne(filter, update);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region UpdateOneAsync 异步批量修改数据
    /// 
    /// 异步批量修改数据
    /// 
    /// 要修改的字段
    /// 修改条件
    /// 
    public async Task<UpdateResult> UpdateOneAsync(UpdateDefinition<T> update, FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return await client.UpdateOneAsync(filter, update);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region UpdateManay 批量修改数据
    /// 
    /// 批量修改数据
    /// 
    /// 要修改的字段
    /// 修改条件
    /// 
    public UpdateResult UpdateManay(UpdateDefinition<T> update, FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return  client.UpdateMany(filter, update);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region UpdateManayAsync 异步批量修改数据
    /// 
    /// 异步批量修改数据
    /// 
    /// 要修改的字段
    /// 修改条件
    /// 
    public async Task<UpdateResult> UpdateManayAsync(UpdateDefinition<T> update, FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return await client.UpdateManyAsync(filter, update);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion



    #region DeleteOne 删除一条数据
    /// 
    /// 删除多条数据
    /// 
    /// 删除的条件
    /// 
    public DeleteResult DeleteOne(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return client.DeleteOne(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }
    #endregion

    #region DeleteOneAsync 异步删除一条数据
    /// 
    /// 异步删除多条数据
    /// 
    /// 删除的条件
    /// 
    public async Task<DeleteResult> DeleteOneAsync(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return await client.DeleteOneAsync(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }
    #endregion

    #region DeleteMany 删除多条数据
    /// 
    /// 删除多条数据
    /// 
    /// 删除的条件
    /// 
    public DeleteResult DeleteMany(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return client.DeleteMany(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }
    #endregion

    #region DeleteManyAsync 异步删除多条数据
    /// 
    /// 异步删除多条数据
    /// 
    /// 删除的条件
    /// 
    public async Task<DeleteResult> DeleteManyAsync(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return await client.DeleteManyAsync(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }
    #endregion

    #region FindOne 根据id查询一条数据
    /// 
    /// 根据id查询一条数据
    /// 
    /// objectid
    /// 要查询的字段,不写时查询全部
    /// 
    public T FindOne(string id, bool isObjectId = true, string[] field = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            FilterDefinition<T> filter;
            if (isObjectId)
            {
                filter = Builders<T>.Filter.Eq("_id", new ObjectId(id));
            }
            else
            {
                filter = Builders<T>.Filter.Eq("_id", id);
            }
            //不指定查询字段
            if (field == null || field.Length == 0)
            {
                return client.Find(filter).FirstOrDefault<T>();
            }

            //制定查询字段
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();
            return client.Find(filter).Project<T>(projection).FirstOrDefault<T>();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region FindOneAsync 异步根据id查询一条数据
    /// 
    /// 异步根据id查询一条数据
    /// 
    /// objectid
    /// 
    public async Task<T> FindOneAsync(string id, bool isObjectId = true, string[] field = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            FilterDefinition<T> filter;
            if (isObjectId)
            {
                filter = Builders<T>.Filter.Eq("_id", new ObjectId(id));
            }
            else
            {
                filter = Builders<T>.Filter.Eq("_id", id);
            }

            //不指定查询字段
            if (field == null || field.Length == 0)
            {
                return await client.Find(filter).FirstOrDefaultAsync();
            }

            //制定查询字段
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();
            return await client.Find(filter).Project<T>(projection).FirstOrDefaultAsync();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region FindList 查询集合
    /// 
    /// 查询集合
    /// 
    /// 查询条件
    /// 要查询的字段,不写时查询全部
    /// 要排序的字段
    /// 
    public List<T> FindList(FilterDefinition<T> filter, string[] field = null, SortDefinition<T> sort = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            //不指定查询字段
            if (field == null || field.Length == 0)
            {
                if (sort == null) return client.Find(filter).ToList();
                //进行排序
                return client.Find(filter).Sort(sort).ToList();
            }

            //制定查询字段
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();
            if (sort == null) return client.Find(filter).Project<T>(projection).ToList();
            //排序查询
            return client.Find(filter).Sort(sort).Project<T>(projection).ToList();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region FindListAsync 异步查询集合
    /// 
    /// 异步查询集合
    /// 
    /// 查询条件
    /// 要查询的字段,不写时查询全部
    /// 要排序的字段
    /// 
    public async Task<List<T>> FindListAsync(FilterDefinition<T> filter, string[] field = null, SortDefinition<T> sort = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            //不指定查询字段
            if (field == null || field.Length == 0)
            {
                //return await client.Find(new BsonDocument()).ToListAsync();
                if (sort == null) return await client.Find(filter).ToListAsync();
                return await client.Find(filter).Sort(sort).ToListAsync();
            }

            //制定查询字段
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();
            if (sort == null) return await client.Find(filter).Project<T>(projection).ToListAsync();
            //排序查询
            return await client.Find(filter).Sort(sort).Project<T>(projection).ToListAsync();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region FindListByPage 分页查询集合
    /// 
    /// 分页查询集合
    /// 
    /// 查询条件
    /// 当前页
    /// 页容量
    /// 总条数
    /// 要查询的字段,不写时查询全部
    /// 要排序的字段
    /// 
    public List<T> FindListByPage(FilterDefinition<T> filter, int pageIndex, int pageSize, out long count, string[] field = null, SortDefinition<T> sort = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            count = client.CountDocuments(filter);
            //不指定查询字段
            if (field == null || field.Length == 0)
            {
                if (sort == null) return client.Find(filter).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();
                //进行排序
                return client.Find(filter).Sort(sort).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();
            }

            //制定查询字段
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();

            //不排序
            if (sort == null) return client.Find(filter).Project<T>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();

            //排序查询
            return client.Find(filter).Sort(sort).Project<T>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList();

        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region FindListByPageAsync 异步分页查询集合
    /// 
    /// 异步分页查询集合
    /// 
    /// 查询条件
    /// 当前页
    /// 页容量
    /// 要查询的字段,不写时查询全部
    /// 要排序的字段
    /// 
    public async Task<List<T>> FindListByPageAsync(FilterDefinition<T> filter, int pageIndex, int pageSize, string[] field = null, SortDefinition<T> sort = null)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            //不指定查询字段
            if (field == null || field.Length == 0)
            {
                if (sort == null) return await client.Find(filter).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();
                //进行排序
                return await client.Find(filter).Sort(sort).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();
            }

            //制定查询字段
            var fieldList = new List<ProjectionDefinition<T>>();
            for (int i = 0; i < field.Length; i++)
            {
                fieldList.Add(Builders<T>.Projection.Include(field[i].ToString()));
            }
            var projection = Builders<T>.Projection.Combine(fieldList);
            fieldList?.Clear();

            //不排序
            if (sort == null) return await client.Find(filter).Project<T>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();

            //排序查询
            return await client.Find(filter).Sort(sort).Project<T>(projection).Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToListAsync();

        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion


    #region Count 根据条件获取总数
    /// 
    /// 根据条件获取总数
    /// 
    /// 条件
    /// 
    public long Count(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return client.CountDocuments(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion

    #region CountAsync 异步根据条件获取总数
    /// 
    /// 异步根据条件获取总数
    /// 
    /// 条件
    /// 
    public async Task<long> CountAsync(FilterDefinition<T> filter)
    {
        try
        {
            var client = _database.GetCollection<T>(_collName);
            return await client.CountDocumentsAsync(filter);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    #endregion
}

6.创建 UserInfoService 类
public class UserInfoService
{
    private readonly UserInfoRepertoty _userInfoRepertoty;

    private readonly FilterDefinitionBuilder<UserInfo> _buildFilter;
    public UserInfoService(UserInfoRepertoty userInfoRepertoty) 
    {
        _userInfoRepertoty = userInfoRepertoty;
        _buildFilter = Builders<UserInfo>.Filter;
    }
}

你可能感兴趣的:(mongodb,mongodb,数据库,nosql)