@@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging; | |||
using Newtonsoft.Json; | |||
using SqlSugar; | |||
namespace BPA.Component.DbClient.RepositoryModel | |||
namespace BPA.Component.DbClient | |||
{ | |||
/// <summary> | |||
/// 数据库客户端基类 | |||
@@ -19,7 +19,7 @@ namespace BPA.Component.DbClient.RepositoryModel | |||
private readonly ILogger<TDbClient> _logger; | |||
/// <summary> | |||
/// 是否打印日志 | |||
/// 是否打印SQL | |||
/// </summary> | |||
private readonly bool _isLogSql; | |||
@@ -1,4 +1,5 @@ | |||
using BPA.Component.DbClient.RepositoryModel; | |||
using BPA.Component.DbClient; | |||
using BPA.Component.DbClient.RepositoryModel; | |||
using Microsoft.Extensions.Logging; | |||
using SqlSugar; | |||
@@ -4,7 +4,7 @@ | |||
"commandName": "Project", | |||
"environmentVariables": { | |||
"ASPNETCORE_ENVIRONMENT": "Development", | |||
"APOLLO_META_SERVER_URL": "http://192.168.1.222:28080", | |||
"APOLLO_META_SERVER_URL": "http://10.2.1.21:28080", | |||
"APOLLO_COMMON_NAMESPACE": "Dev.Common", | |||
"APP_NAME": "BPA-DEV" | |||
} | |||
@@ -18,6 +18,7 @@ | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="BPA.Component.Extensions" Version="1.0.1" /> | |||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" /> | |||
<PackageReference Include="MongoDB.Driver" Version="2.15.0" /> | |||
<PackageReference Include="Nuget.Tools.V2" Version="1.1.6"> | |||
<PrivateAssets>all</PrivateAssets> | |||
@@ -1,631 +0,0 @@ | |||
using System.Linq.Expressions; | |||
using MongoDB.Driver; | |||
using MongoDB.Driver.Linq; | |||
namespace BPA.Component.MongoClient | |||
{ | |||
/// <summary> | |||
/// MongoDb基础仓储 | |||
/// </summary> | |||
public abstract class BaseMGRepository<TDocument> : IMGRepository<TDocument> where TDocument : new() | |||
{ | |||
/// <summary> | |||
/// 当前企业(商户)Id | |||
/// </summary> | |||
public long CorpId { protected set; get; } | |||
/// <summary> | |||
/// 当前MongoDB上下文 | |||
/// </summary> | |||
public MongoDbContext CurrMongoDbContext { protected set; get; } | |||
/// <summary> | |||
/// 当前需要操作的文档集 | |||
/// </summary> | |||
public IMongoCollection<TDocument> CurrentCollection { protected set; get; } | |||
/// <summary> | |||
/// MongoDbProvider | |||
/// </summary> | |||
public MongoDbProvider MongoDbProvider { protected set; get; } | |||
/// <summary> | |||
/// 构造方法 | |||
/// </summary> | |||
/// <param name="mongoDbProvider"></param> | |||
public BaseMGRepository(MongoDbProvider mongoDbProvider) | |||
{ | |||
MongoDbProvider = mongoDbProvider; | |||
} | |||
/// <summary> | |||
/// 切换企业Id | |||
/// </summary> | |||
/// <param name="corpId"></param> | |||
public virtual void ChangeCorpId(long corpId) | |||
{ | |||
CorpId = corpId; | |||
CurrMongoDbContext = MongoDbProvider.GetDbContext(corpId); | |||
CurrentCollection = CurrMongoDbContext.GetCollection<TDocument>(null); | |||
} | |||
/// <summary> | |||
/// 检查当前文档集 | |||
/// </summary> | |||
private void CheckCurrentCollection() | |||
{ | |||
if (CurrentCollection == null) | |||
throw new ArgumentNullException($"当前要操作的文档集为空,请调用{nameof(ChangeCorpId)}方法切换企业Id!"); | |||
} | |||
#region 插入扩展 | |||
/// <summary> | |||
/// 插入一个 ,等同使用:<code>IMongoCollection.InsertOne</code> | |||
/// </summary> | |||
/// <param name="document">文档对象</param> | |||
/// <param name="options">插入配置选项</param> | |||
public void InsertOne(TDocument document, InsertOneOptions? options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
CurrentCollection.InsertOne(document, options); | |||
} | |||
/// <summary> | |||
/// 插入多个,等同使用: | |||
/// <code>IMongoCollection.InsertMany(IClientSessionHandle, IEnumerable{TDocument}, InsertManyOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="documents">文档对象</param> | |||
/// <param name="options">插入配置选项</param> | |||
public void InsertMany(IEnumerable<TDocument> documents, InsertManyOptions? options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
CurrentCollection.InsertMany(documents, options); | |||
} | |||
/// <summary> | |||
/// 插入一个 ,等同使用:<code>IMongoCollection.InsertOneAsync</code> | |||
/// </summary> | |||
/// <param name="document">文档对象</param> | |||
/// <param name="options">插入配置选项</param> | |||
public Task InsertOneAsync(TDocument document, InsertOneOptions? options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.InsertOneAsync(document, options); | |||
} | |||
/// <summary> | |||
/// 插入多个,等同使用: | |||
/// <code>IMongoCollection.InsertManyAsync(IEnumerable{TDocument}, InsertManyOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="documents">文档对象</param> | |||
/// <param name="options">插入配置选项</param> | |||
public Task InsertManyAsync(IEnumerable<TDocument> documents, InsertManyOptions? options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.InsertManyAsync(documents, options); | |||
} | |||
#endregion | |||
#region 更新扩展 | |||
/// <summary> | |||
/// 更新满足条件的第一条数据, | |||
/// <code>IMongoCollection.UpdateOne(FilterDefinition{TDocument}, UpdateDefinition{TDocument}, UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
public UpdateResult UpdateOne(TDocument document, Expression<Func<TDocument, bool>> whereExpression, | |||
UpdateOptions options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateOne(document, whereExpression, options); | |||
} | |||
/// <summary> | |||
/// 更新满足条件的第一条数据, | |||
/// <code>IMongoCollection.UpdateOneAsync(FilterDefinition{TDocument}, UpdateDefinition{TDocument}, UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
public Task<UpdateResult> UpdateOneAsync(TDocument document, Expression<Func<TDocument, bool>> whereExpression, | |||
UpdateOptions options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateOneAsync(document, whereExpression, options); | |||
} | |||
/// <summary> | |||
/// 更新满足条件的多条数据, | |||
/// <code>IMongoCollection.UpdateOne(FilterDefinition{TDocument}, UpdateDefinition{TDocument},UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
public UpdateResult UpdateMany(TDocument document, Expression<Func<TDocument, bool>> whereExpression, | |||
UpdateOptions options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateMany(document, whereExpression, options); | |||
} | |||
/// <summary> | |||
/// 更新满足条件的多条数据, | |||
/// <code>IMongoCollection.UpdateOne(FilterDefinition{TDocument}, UpdateDefinition{TDocument},UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
public Task<UpdateResult> UpdateManyAsync(TDocument document, Expression<Func<TDocument, bool>> whereExpression, | |||
UpdateOptions options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateManyAsync(document, whereExpression, options); | |||
} | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的第一条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
public UpdateResult UpdateOne(Expression<Action<TDocument>> columnsExp, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateOne(columnsExp, whereExpression); | |||
} | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的第一条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
public Task<UpdateResult> UpdateOneAsync(Expression<Action<TDocument>> columnsExp, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateOneAsync(columnsExp, whereExpression); | |||
} | |||
/// <summary> | |||
/// 自定义更新字段和条件,更新单条符合条件的数据 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="update"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
public UpdateResult UpdateOne(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, | |||
UpdateOptions options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateOne(filter, update, options); | |||
} | |||
/// <summary> | |||
/// 自定义更新字段和条件,更新单条符合条件的数据 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="update"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
public Task<UpdateResult> UpdateOneAsync(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, | |||
UpdateOptions options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateOneAsync(filter, update, options); | |||
} | |||
/// <summary> | |||
/// 自定义更新字段和条件,更新条符合条件的数据 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="update"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
public UpdateResult UpdateMany(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, | |||
UpdateOptions options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateMany(filter, update, options); | |||
} | |||
/// <summary> | |||
/// 自定义更新字段和条件,更新条符合条件的数据 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="update"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
public Task<UpdateResult> UpdateManyAsync(FilterDefinition<TDocument> filter, | |||
UpdateDefinition<TDocument> update, | |||
UpdateOptions options = null) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateManyAsync(filter, update, options); | |||
} | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的多条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
public UpdateResult UpdateMany(Expression<Action<TDocument>> columnsExp, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateMany(columnsExp, whereExpression); | |||
} | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的多条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
public Task<UpdateResult> UpdateManyAsync(Expression<Action<TDocument>> columnsExp, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.UpdateManyAsync(columnsExp, whereExpression); | |||
} | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 Id,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document">文档对象对象</param> | |||
/// <returns></returns> | |||
public ReplaceOneResult ReplaceOneById(TDocument document) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.ReplaceOneById(document); | |||
} | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 Id,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document">文档对象对象</param> | |||
/// <returns></returns> | |||
public Task<ReplaceOneResult> ReplaceOneByIdAsync(TDocument document) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.ReplaceOneByIdAsync(document); | |||
} | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 ID,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document">文档对象对象</param> | |||
/// <param name="whereExpression">查询添加表达式</param> | |||
/// <returns></returns> | |||
public ReplaceOneResult ReplaceOne(TDocument document, Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.ReplaceOne(document, whereExpression); | |||
} | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 ID,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document">文档对象对象</param> | |||
/// <param name="whereExpression">查询添加表达式</param> | |||
/// <returns></returns> | |||
public Task<ReplaceOneResult> ReplaceOneAsync(TDocument document, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.ReplaceOneAsync(document, whereExpression); | |||
} | |||
#endregion | |||
#region 删除扩展 | |||
/// <summary> | |||
/// 删除满足条件的第一条数据,等同于 | |||
/// <code>IMongoCollection.DeleteOne(FilterDefinition{TDocument}, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="whereExpression">删除条件表达式</param> | |||
public DeleteResult DeleteOne(Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.DeleteOne(whereExpression); | |||
} | |||
/// <summary> | |||
/// 删除满足条件的第一条数据,等同于 | |||
/// <code>IMongoCollection.DeleteOne(FilterDefinition{TDocument}, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="whereExpression">删除条件表达式</param> | |||
public Task<DeleteResult> DeleteOneAsync(Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.DeleteOneAsync(whereExpression); | |||
} | |||
/// <summary> | |||
/// 批量删除满足条件的多条数据,等同于 | |||
/// <code>IMongoCollection.DeleteMany(FilterDefinition{TDocument}, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="whereExpression">删除条件表达式</param> | |||
public DeleteResult DeleteMany(Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.DeleteMany(whereExpression); | |||
} | |||
/// <summary> | |||
/// 批量删除满足条件的多条数据,等同于 | |||
/// <code>IMongoCollection.DeleteMany(FilterDefinition{TDocument}, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="whereExpression">删除条件表达式</param> | |||
public Task<DeleteResult> DeleteManyAsync(Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.DeleteManyAsync(whereExpression); | |||
} | |||
#endregion | |||
#region 查询扩展 | |||
/// <summary> | |||
/// 根据条件查询 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
public IFindFluent<TDocument, TDocument> Find(FilterDefinition<TDocument> filter, FindOptions? options) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Find(filter, options); | |||
} | |||
/// <summary> | |||
/// 根据条件查询 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
public Task<IAsyncCursor<TDocument>> FindAsync( | |||
FilterDefinition<TDocument> filter, | |||
FindOptions<TDocument, TDocument>? options) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.FindAsync(filter, options); | |||
} | |||
/// <summary> | |||
/// 可查询 <see cref="IMongoCollectionExtensions.AsQueryable{TDocument}(IMongoCollection{TDocument}, AggregateOptions)"/> | |||
/// </summary> | |||
/// <returns></returns> | |||
public IMongoQueryable<TDocument> Queryable() | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable(); | |||
} | |||
/// <summary> | |||
/// 可查询 根据条件 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
public IMongoQueryable<TDocument> Queryable(Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable().Where(whereExpression); | |||
} | |||
/// <summary> | |||
/// 可查询 根据条件 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="selectExpression"></param> | |||
/// <returns></returns> | |||
public IMongoQueryable<TResult> Queryable<TResult>(Expression<Func<TDocument, bool>> whereExpression, | |||
Expression<Func<TDocument, TResult>> selectExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable().Where(whereExpression).Select(selectExpression); | |||
} | |||
/// <summary> | |||
/// 根据条件判断是否存在 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
public bool Any(Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable().Where(whereExpression).Any(); | |||
} | |||
/// <summary> | |||
/// 根据ID获取entity | |||
/// </summary> | |||
/// <param name="id"></param> | |||
/// <returns></returns> | |||
public TDocument GetById(dynamic id) | |||
{ | |||
CheckCurrentCollection(); | |||
FilterDefinition<TDocument> filter = Builders<TDocument>.Filter.Eq("_id", id); | |||
var find = CurrentCollection.Find(filter, null); | |||
return find.FirstOrDefault(); | |||
} | |||
/// <summary> | |||
/// 根据ID获取entity | |||
/// </summary> | |||
/// <param name="id"></param> | |||
/// <returns></returns> | |||
public async Task<TDocument> GetByIdAsync(dynamic id) | |||
{ | |||
CheckCurrentCollection(); | |||
FilterDefinition<TDocument> filter = Builders<TDocument>.Filter.Eq("_id", id); | |||
var find = await CurrentCollection.FindAsync(filter, null); | |||
return find.FirstOrDefault(); | |||
} | |||
/// <summary> | |||
/// 根据ID获取entity | |||
/// </summary> | |||
/// <param name="id"></param> | |||
/// <param name="selectExpression">需要返会的字段表达式</param> | |||
/// <returns></returns> | |||
public TResult GetById<TResult>(dynamic id, Expression<Func<TDocument, TResult>> selectExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
FilterDefinition<TDocument> filter = Builders<TDocument>.Filter.Eq("_id", id); | |||
var find = CurrentCollection.Find(filter, null); | |||
return find.Select(selectExpression).FirstOrDefault(); | |||
} | |||
/// <summary> | |||
/// 根据条件 获取第一条数据 | |||
/// </summary> | |||
/// <param name="whereExpression">条件</param> | |||
/// <param name="selectExpression">返回的新对象选择表达式</param> | |||
/// <returns></returns> | |||
public TResult? First<TResult>(Expression<Func<TDocument, bool>> whereExpression, | |||
Expression<Func<TDocument, TResult>> selectExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable().Where(whereExpression).Select(selectExpression).FirstOrDefault(); | |||
} | |||
/// <summary> | |||
/// 根据条件 获取第一条数据 | |||
/// </summary> | |||
/// <param name="whereExpression">条件</param> | |||
/// <param name="selectExpression">返回的新对象选择表达式</param> | |||
/// <returns></returns> | |||
public Task<TResult> FirstAsync<TResult>(Expression<Func<TDocument, bool>> whereExpression, | |||
Expression<Func<TDocument, TResult>> selectExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable().Where(whereExpression).Select(selectExpression).FirstOrDefaultAsync(); | |||
} | |||
/// <summary> | |||
/// 根据条件 获取第一条数据 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
public TDocument? First(Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable().Where(whereExpression).FirstOrDefault(); | |||
} | |||
/// <summary> | |||
/// 根据条件 获取第一条数据 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
public Task<TDocument> FirstAsync(Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable().Where(whereExpression).FirstOrDefaultAsync(); | |||
} | |||
/// <summary> | |||
/// 根据条件获取集合 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
public List<TDocument> QueryList(Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable().Where(whereExpression).ToList(); | |||
} | |||
/// <summary> | |||
/// 根据条件获取集合 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
public Task<List<TDocument>> QueryListAsync(Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable().Where(whereExpression).ToListAsync(); | |||
} | |||
/// <summary> | |||
/// 根据条件获取集合 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="selectExpression"></param> | |||
/// <returns></returns> | |||
public List<TResult> QueryList<TResult>(Expression<Func<TDocument, bool>> whereExpression, | |||
Expression<Func<TDocument, TResult>> selectExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable().Where(whereExpression).Select(selectExpression).ToList(); | |||
} | |||
/// <summary> | |||
/// 根据条件获取集合 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="selectExpression"></param> | |||
/// <returns></returns> | |||
public Task<List<TResult>> QueryListAsync<TResult>(Expression<Func<TDocument, bool>> whereExpression, | |||
Expression<Func<TDocument, TResult>> selectExpression) | |||
{ | |||
CheckCurrentCollection(); | |||
return CurrentCollection.Queryable().Where(whereExpression).Select(selectExpression).ToListAsync(); | |||
} | |||
#endregion | |||
#region 创建 查询 、索引、更新、排序 条件定义 | |||
/// <summary> | |||
/// 创建过滤条件定义 | |||
/// </summary> | |||
public FilterDefinitionBuilder<TDocument> BuilderFilter() => Builders<TDocument>.Filter; | |||
/// <summary> | |||
/// 创建索引条件定义 | |||
/// </summary> | |||
public IndexKeysDefinitionBuilder<TDocument> BuilderIndexKeys() => Builders<TDocument>.IndexKeys; | |||
/// <summary> | |||
/// 创建更新条件定义 | |||
/// </summary> | |||
public UpdateDefinitionBuilder<TDocument> BuilderUpdate() => Builders<TDocument>.Update; | |||
/// <summary> | |||
/// 创建排序条件定义 | |||
/// </summary> | |||
public SortDefinitionBuilder<TDocument> BuilderSort() => Builders<TDocument>.Sort; | |||
/// <summary> | |||
/// Filter | |||
/// </summary> | |||
public FilterDefinitionBuilder<TDocument> Filter => Builders<TDocument>.Filter; | |||
/// <summary> | |||
/// Update | |||
/// </summary> | |||
public UpdateDefinitionBuilder<TDocument> Update => Builders<TDocument>.Update; | |||
/// <summary> | |||
/// Sort | |||
/// </summary> | |||
public SortDefinitionBuilder<TDocument> Sort => Builders<TDocument>.Sort; | |||
#endregion | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
using System.Runtime.CompilerServices; | |||
using Microsoft.Extensions.Logging; | |||
using MongoDB.Driver.Core.Configuration; | |||
namespace BPA.Component.MongoClient; | |||
public class BaseMongoDbClient<TMongoDbClient> : MongoDB.Driver.MongoClient | |||
where TMongoDbClient : BaseMongoDbClient<TMongoDbClient> | |||
{ | |||
/// <summary> | |||
/// Logger | |||
/// </summary> | |||
private readonly ILogger<TMongoDbClient> _logger; | |||
/// <summary> | |||
/// MongoConfig | |||
/// </summary> | |||
private static MongoConfig _config; | |||
/// <summary> | |||
/// CurrentDatabaseName | |||
/// </summary> | |||
protected internal readonly string CurrentDatabaseName; | |||
/// <summary> | |||
/// BaseMongoDbClient | |||
/// </summary> | |||
/// <param name="config"></param> | |||
/// <param name="logger"></param> | |||
public BaseMongoDbClient(MongoConfig config, ILogger<TMongoDbClient> logger = null) | |||
{ | |||
CurrentDatabaseName = config.DatabasesName; | |||
_config = config; | |||
_logger = logger; | |||
} | |||
/// <summary> | |||
/// BuildMongoConfig | |||
/// </summary> | |||
/// <param name="connectionString"></param> | |||
/// <param name="databaseName"></param> | |||
/// <returns></returns> | |||
protected static MongoConfig BuildMongoConfig(string connectionString, string databaseName) | |||
{ | |||
_config = new MongoConfig {ConnectionString = connectionString, DatabasesName = databaseName}; | |||
return _config; | |||
} | |||
} |
@@ -1,425 +0,0 @@ | |||
using System.Linq.Expressions; | |||
using MongoDB.Driver; | |||
using MongoDB.Driver.Linq; | |||
namespace BPA.Component.MongoClient | |||
{ | |||
/// <summary> | |||
/// MongoDB仓储接口 | |||
/// </summary> | |||
public interface IMGRepository<TDocument> where TDocument : new() | |||
{ | |||
/// <summary> | |||
/// 当前企业(商户)Id | |||
/// </summary> | |||
long CorpId { get; } | |||
/// <summary> | |||
/// 切换企业Id | |||
/// </summary> | |||
/// <param name="corpId"></param> | |||
void ChangeCorpId(long corpId); | |||
/// <summary> | |||
/// MongonDbProvider | |||
/// </summary> | |||
MongoDbProvider MongoDbProvider { get; } | |||
/// <summary> | |||
/// 当前MongoDB上下文 | |||
/// </summary> | |||
MongoDbContext CurrMongoDbContext { get; } | |||
/// <summary> | |||
/// 当前需要操作的文档集 | |||
/// </summary> | |||
IMongoCollection<TDocument> CurrentCollection { get; } | |||
#region 插入扩展 | |||
/// <summary> | |||
/// 插入一个 ,等同使用:<code>IMongoCollection.InsertOne</code> | |||
/// </summary> | |||
/// <param name="document">文档对象</param> | |||
/// <param name="options">插入配置选项</param> | |||
void InsertOne(TDocument document, InsertOneOptions? options = null); | |||
/// <summary> | |||
/// 插入多个,等同使用: | |||
/// <code>IMongoCollection.InsertMany(IClientSessionHandle, IEnumerable{TDocument}, InsertManyOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="documents">文档对象</param> | |||
/// <param name="options">插入配置选项</param> | |||
void InsertMany(IEnumerable<TDocument> documents, InsertManyOptions? options = null); | |||
/// <summary> | |||
/// 插入一个 ,等同使用:<code>IMongoCollection.InsertOneAsync</code> | |||
/// </summary> | |||
/// <param name="document">文档对象</param> | |||
/// <param name="options">插入配置选项</param> | |||
Task InsertOneAsync(TDocument document, InsertOneOptions options = null); | |||
/// <summary> | |||
/// 插入多个,等同使用: | |||
/// <code>IMongoCollection.InsertManyAsync(IEnumerable{TDocument}, InsertManyOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="documents">文档对象</param> | |||
/// <param name="options">插入配置选项</param> | |||
Task InsertManyAsync(IEnumerable<TDocument> documents, InsertManyOptions options = null); | |||
#endregion | |||
#region 更新扩展 | |||
/// <summary> | |||
/// 更新满足条件的第一条数据, | |||
/// <code>IMongoCollection.UpdateOne(FilterDefinition{TDocument}, UpdateDefinition{TDocument}, UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
UpdateResult UpdateOne(TDocument document, Expression<Func<TDocument, bool>> whereExpression, UpdateOptions options = null); | |||
/// <summary> | |||
/// 更新满足条件的第一条数据, | |||
/// <code>IMongoCollection.UpdateOneAsync(FilterDefinition{TDocument}, UpdateDefinition{TDocument}, UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
Task<UpdateResult> UpdateOneAsync(TDocument document, Expression<Func<TDocument, bool>> whereExpression, | |||
UpdateOptions options = null); | |||
/// <summary> | |||
/// 更新满足条件的多条数据, | |||
/// <code>IMongoCollection.UpdateOne(FilterDefinition{TDocument}, UpdateDefinition{TDocument},UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
UpdateResult UpdateMany(TDocument document, Expression<Func<TDocument, bool>> whereExpression, UpdateOptions options = null); | |||
/// <summary> | |||
/// 更新满足条件的多条数据, | |||
/// <code>IMongoCollection.UpdateOne(FilterDefinition{TDocument}, UpdateDefinition{TDocument},UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
Task<UpdateResult> UpdateManyAsync(TDocument document, Expression<Func<TDocument, bool>> whereExpression, | |||
UpdateOptions options = null); | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的第一条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
UpdateResult UpdateOne(Expression<Action<TDocument>> columnsExp, Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的第一条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
Task<UpdateResult> UpdateOneAsync(Expression<Action<TDocument>> columnsExp, Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的多条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
UpdateResult UpdateMany(Expression<Action<TDocument>> columnsExp, Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的多条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
Task<UpdateResult> UpdateManyAsync(Expression<Action<TDocument>> columnsExp, Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 自定义更新字段和条件,更新单条符合条件的数据 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="update"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
UpdateResult UpdateOne(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, UpdateOptions options = null); | |||
/// <summary> | |||
/// 自定义更新字段和条件,更新单条符合条件的数据 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="update"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
Task<UpdateResult> UpdateOneAsync(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, | |||
UpdateOptions options = null); | |||
/// <summary> | |||
/// 自定义更新字段和条件,更新条符合条件的数据 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="update"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
UpdateResult UpdateMany(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, UpdateOptions options = null); | |||
/// <summary> | |||
/// 自定义更新字段和条件,更新条符合条件的数据 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="update"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
Task<UpdateResult> UpdateManyAsync(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, | |||
UpdateOptions options = null); | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 Id,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document">文档对象对象</param> | |||
/// <returns></returns> | |||
ReplaceOneResult ReplaceOneById(TDocument document); | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 Id,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document">文档对象对象</param> | |||
/// <returns></returns> | |||
Task<ReplaceOneResult> ReplaceOneByIdAsync(TDocument document); | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 ID,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document">文档对象对象</param> | |||
/// <param name="whereExpression">查询添加表达式</param> | |||
/// <returns></returns> | |||
ReplaceOneResult ReplaceOne(TDocument document, Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 ID,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="document">文档对象对象</param> | |||
/// <param name="whereExpression">查询添加表达式</param> | |||
/// <returns></returns> | |||
Task<ReplaceOneResult> ReplaceOneAsync(TDocument document, Expression<Func<TDocument, bool>> whereExpression); | |||
#endregion | |||
#region 删除扩展 | |||
/// <summary> | |||
/// 删除满足条件的第一条数据,等同于 | |||
/// <code>IMongoCollection.DeleteOne(FilterDefinition{TDocument}, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="whereExpression">删除条件表达式</param> | |||
DeleteResult DeleteOne(Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 删除满足条件的第一条数据,等同于 | |||
/// <code>IMongoCollection.DeleteOne(FilterDefinition{TDocument}, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="whereExpression">删除条件表达式</param> | |||
Task<DeleteResult> DeleteOneAsync(Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 批量删除满足条件的多条数据,等同于 | |||
/// <code>IMongoCollection.DeleteMany(FilterDefinition{TDocument}, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="whereExpression">删除条件表达式</param> | |||
DeleteResult DeleteMany(Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 批量删除满足条件的多条数据,等同于 | |||
/// <code>IMongoCollection.DeleteMany(FilterDefinition{TDocument}, CancellationToken)</code> | |||
/// </summary> | |||
/// <param name="whereExpression">删除条件表达式</param> | |||
Task<DeleteResult> DeleteManyAsync(Expression<Func<TDocument, bool>> whereExpression); | |||
#endregion | |||
#region 查询扩展 | |||
/// <summary> | |||
/// 根据条件查询 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
IFindFluent<TDocument, TDocument> Find(FilterDefinition<TDocument> filter, FindOptions options = null); | |||
/// <summary> | |||
/// 根据条件查询 | |||
/// </summary> | |||
/// <param name="filter"></param> | |||
/// <param name="options"></param> | |||
/// <returns></returns> | |||
Task<IAsyncCursor<TDocument>> FindAsync(FilterDefinition<TDocument> filter, FindOptions<TDocument, TDocument> options = null); | |||
/// <summary> | |||
/// 可查询 <see cref="IMongoCollectionExtensions.AsQueryable{TDocument}(IMongoCollection{TDocument}, AggregateOptions)"/> | |||
/// , 同步时用ToList, 异步时用 ToListAsync | |||
/// </summary> | |||
/// <returns></returns> | |||
IMongoQueryable<TDocument> Queryable(); | |||
/// <summary> | |||
/// 可查询 根据条件 , 同步时用ToList, 异步时用 ToListAsync | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
IMongoQueryable<TDocument> Queryable(Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 可查询 根据条件 , 同步时用ToList , 异步时用 ToListAsync | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="selectExpression"></param> | |||
/// <returns></returns> | |||
IMongoQueryable<TResult> Queryable<TResult>(Expression<Func<TDocument, bool>> whereExpression, | |||
Expression<Func<TDocument, TResult>> selectExpression); | |||
/// <summary> | |||
/// 根据条件判断是否存在 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
bool Any(Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 根据ID获取entity | |||
/// </summary> | |||
/// <param name="id"></param> | |||
/// <returns></returns> | |||
TDocument GetById(dynamic id); | |||
/// <summary> | |||
/// 根据ID获取entity | |||
/// </summary> | |||
/// <param name="id"></param> | |||
/// <returns></returns> | |||
Task<TDocument> GetByIdAsync(dynamic id); | |||
/// <summary> | |||
/// 根据ID获取entity | |||
/// </summary> | |||
/// <param name="id"></param> | |||
/// <param name="selectExpression">需要返回的字段表达式</param> | |||
/// <returns></returns> | |||
TResult GetById<TResult>(dynamic id, Expression<Func<TDocument, TResult>> selectExpression); | |||
/// <summary> | |||
/// 根据条件 获取第一条数据 | |||
/// </summary> | |||
/// <param name="whereExpression">条件</param> | |||
/// <param name="selectExpression">返回的新对象选择表达式</param> | |||
/// <returns></returns> | |||
TResult? First<TResult>(Expression<Func<TDocument, bool>> whereExpression, Expression<Func<TDocument, TResult>> selectExpression); | |||
/// <summary> | |||
/// 根据条件 获取第一条数据 | |||
/// </summary> | |||
/// <param name="whereExpression">条件</param> | |||
/// <param name="selectExpression">返回的新对象选择表达式</param> | |||
/// <returns></returns> | |||
Task<TResult> FirstAsync<TResult>(Expression<Func<TDocument, bool>> whereExpression, | |||
Expression<Func<TDocument, TResult>> selectExpression); | |||
/// <summary> | |||
/// 根据条件 获取第一条数据 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
TDocument? First(Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 根据条件 获取第一条数据 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
Task<TDocument> FirstAsync(Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 根据条件获取集合 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
List<TDocument> QueryList(Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 根据条件获取集合 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <returns></returns> | |||
Task<List<TDocument>> QueryListAsync(Expression<Func<TDocument, bool>> whereExpression); | |||
/// <summary> | |||
/// 根据条件获取集合 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="selectExpression"></param> | |||
/// <returns></returns> | |||
List<TResult> QueryList<TResult>(Expression<Func<TDocument, bool>> whereExpression, | |||
Expression<Func<TDocument, TResult>> selectExpression); | |||
/// <summary> | |||
/// 根据条件获取集合 | |||
/// </summary> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="selectExpression"></param> | |||
/// <returns></returns> | |||
Task<List<TResult>> QueryListAsync<TResult>(Expression<Func<TDocument, bool>> whereExpression, | |||
Expression<Func<TDocument, TResult>> selectExpression); | |||
#endregion | |||
#region 创建 查询 、索引、更新、排序 条件定义 | |||
/// <summary> | |||
/// Filter | |||
/// </summary> | |||
FilterDefinitionBuilder<TDocument> Filter { get; } | |||
/// <summary> | |||
/// Update | |||
/// </summary> | |||
UpdateDefinitionBuilder<TDocument> Update { get; } | |||
/// <summary> | |||
/// Sort | |||
/// </summary> | |||
SortDefinitionBuilder<TDocument> Sort { get; } | |||
/// <summary> | |||
/// 创建过滤条件定义 | |||
/// </summary> | |||
FilterDefinitionBuilder<TDocument> BuilderFilter(); | |||
/// <summary> | |||
/// 创建索引条件定义 | |||
/// </summary> | |||
IndexKeysDefinitionBuilder<TDocument> BuilderIndexKeys(); | |||
/// <summary> | |||
/// 创建更新条件定义 | |||
/// </summary> | |||
UpdateDefinitionBuilder<TDocument> BuilderUpdate(); | |||
/// <summary> | |||
/// 创建排序条件定义 | |||
/// </summary> | |||
SortDefinitionBuilder<TDocument> BuilderSort(); | |||
#endregion | |||
} | |||
} |
@@ -3,20 +3,15 @@ | |||
/// <summary> | |||
/// MongoDb配置 | |||
/// </summary> | |||
public class MongoDbConfig | |||
public class MongoConfig | |||
{ | |||
/// <summary> | |||
/// 别名,同一种的业务数据库的可以有多个,但是每个的别名都不能相同 | |||
/// </summary> | |||
public string Alias { set; get; } | |||
/// <summary> | |||
/// 连接字符串 | |||
/// </summary> | |||
public string ConnectionString { set; get; } | |||
/// <summary> | |||
/// 数据库名称 | |||
/// 数据库名称 | 可空 | |||
/// </summary> | |||
public string DatabasesName { set; get; } | |||
} |
@@ -1,177 +0,0 @@ | |||
using BPA.Component.MongoClient.Conventions; | |||
using MongoDB.Bson; | |||
using MongoDB.Bson.Serialization; | |||
using MongoDB.Bson.Serialization.Conventions; | |||
using MongoDB.Bson.Serialization.Serializers; | |||
using MongoDB.Driver; | |||
using Newtonsoft.Json.Linq; | |||
namespace BPA.Component.MongoClient | |||
{ | |||
/// <summary> | |||
/// MongoDbContext | |||
/// </summary> | |||
public class MongoDbContext : IDisposable | |||
{ | |||
static MongoDbContext() | |||
{ | |||
var serializer = new DateTimeSerializer(DateTimeKind.Local, BsonType.DateTime); | |||
BsonSerializer.RegisterSerializer(typeof(DateTime), serializer); | |||
BsonSerializer.RegisterSerializer(typeof(JObject), new JObjectSerializer()); | |||
BsonSerializer.RegisterSerializer(typeof(JArray), new JArraySerializer()); | |||
BsonSerializer.RegisterSerializer(typeof(Dictionary<string, object>), new DictionarySerializerSerializer()); | |||
BsonSerializer.RegisterSerializer(typeof(decimal), new DecimalSerializer(BsonType.Decimal128)); | |||
BsonSerializer.RegisterSerializer(typeof(decimal?), | |||
new NullableSerializer<decimal>(new DecimalSerializer(BsonType.Decimal128))); | |||
BsonSerializer.RegisterSerializationProvider(new BPASerializationProvider()); | |||
ConventionRegistry.Register("IgnoreExtraElements", | |||
new ConventionPack | |||
{ | |||
new IgnoreExtraElementsConvention(true), new BPACamelCaseElementNameConvention(), | |||
new EnumRepresentationConvention(BsonType.String) | |||
}, _ => true); | |||
} | |||
/// <summary> | |||
/// 当前连接 | |||
/// </summary> | |||
public readonly IMongoClient MongoClient; | |||
/// <summary> | |||
/// 当前操作数据库 | |||
/// </summary> | |||
public readonly IMongoDatabase Database; | |||
/// <summary> | |||
/// 企业ID | |||
/// </summary> | |||
public readonly long CorpId; | |||
/// <summary> | |||
/// 构造方法 | |||
/// </summary> | |||
/// <param name="corpId"></param> | |||
/// <param name="mongoClient"></param> | |||
/// <param name="database"></param> | |||
public MongoDbContext(long corpId, IMongoClient mongoClient, IMongoDatabase database) | |||
{ | |||
CorpId = corpId; | |||
MongoClient = mongoClient; | |||
Database = database; | |||
} | |||
/// <summary> | |||
/// 检查数据库是否存在 | |||
/// </summary> | |||
/// <param name="mongoClient"></param> | |||
/// <param name="databaseName"></param> | |||
/// <returns></returns> | |||
public bool DatabaseExists(MongoDB.Driver.MongoClient mongoClient, string databaseName) | |||
{ | |||
try | |||
{ | |||
var dbNames = mongoClient.ListDatabases().ToList().Select(db => db.GetValue("name").AsString); | |||
return dbNames.Contains(databaseName); | |||
} | |||
catch | |||
{ | |||
return true; | |||
} | |||
} | |||
/// <summary> | |||
/// 检查文档集是否存在 | |||
/// </summary> | |||
/// <param name="mongoDatabase"></param> | |||
/// <param name="collectionName"></param> | |||
/// <returns></returns> | |||
public bool CollectionExists(IMongoDatabase mongoDatabase, string collectionName) | |||
{ | |||
var options = new ListCollectionsOptions | |||
{ | |||
Filter = Builders<BsonDocument>.Filter.Eq("name", collectionName) | |||
}; | |||
return mongoDatabase.ListCollections(options).ToEnumerable().Any(); | |||
} | |||
/// <summary> | |||
/// 获取文档集接口 | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="collectionName"></param> | |||
/// <param name="settings"></param> | |||
/// <returns></returns> | |||
public IMongoCollection<TDocument> GetCollection<TDocument>(string collectionName, | |||
MongoCollectionSettings? settings) | |||
{ | |||
return Database.GetCollection<TDocument>(collectionName, settings); | |||
} | |||
/// <summary> | |||
/// 根据企业名称和文档集类型构建 文档集名称 | |||
/// <code> | |||
/// 返回文档集格式:{typeof(TDocument).Name}{corpId}, | |||
/// </code> | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="corpId">企业ID</param> | |||
/// <returns></returns> | |||
public string BuildCollectionName<TDocument>(long corpId) | |||
{ | |||
return $"{typeof(TDocument).Name}{corpId}"; | |||
} | |||
/// <summary> | |||
/// 根据企业ID获取,获取文档集接口 | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="settings"></param> | |||
/// <returns></returns> | |||
public IMongoCollection<TDocument> GetCollection<TDocument>(MongoCollectionSettings? settings) | |||
{ | |||
var collectionName = BuildCollectionName<TDocument>(CorpId); | |||
return GetCollection<TDocument>(collectionName, settings); | |||
} | |||
/// <summary> | |||
/// 检查文档集是否存在 | |||
/// </summary> | |||
/// <param name="collectionName">文档集名称</param> | |||
/// <returns></returns> | |||
public bool CollectionExists(string collectionName) | |||
{ | |||
var options = new ListCollectionsOptions | |||
{ | |||
Filter = Builders<BsonDocument>.Filter.Eq("name", collectionName) | |||
}; | |||
return Database.ListCollections(options).ToEnumerable().Any(); | |||
} | |||
/// <summary> | |||
/// 清空文档集数据 | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
public IMongoCollection<TDocument> ClearCollection<TDocument>() | |||
{ | |||
var collectionName = BuildCollectionName<TDocument>(CorpId); | |||
//删除文档集 | |||
Database.DropCollection(collectionName); | |||
if (!CollectionExists(Database, collectionName)) | |||
{ | |||
this.CreateCollection<TDocument>(collectionName); | |||
} | |||
return Database.GetCollection<TDocument>(collectionName); | |||
} | |||
/// <summary> | |||
/// 销毁 | |||
/// </summary> | |||
public void Dispose() | |||
{ | |||
} | |||
} | |||
} |
@@ -1,714 +0,0 @@ | |||
using System.Linq.Expressions; | |||
using MongoDB.Bson; | |||
using MongoDB.Driver; | |||
using MongoDB.Driver.Linq; | |||
namespace BPA.Component.MongoClient | |||
{ | |||
/// <summary> | |||
/// MongoDB 文件集扩展类 | |||
/// </summary> | |||
public static class MongoDbExtensions | |||
{ | |||
/// <summary> | |||
/// 聚合默认选项 | |||
/// </summary> | |||
public static readonly AggregateOptions DefaultAggregateOptions = new AggregateOptions {AllowDiskUse = true}; | |||
#region 文档集操作扩展 | |||
/// <summary> | |||
/// 创建文档集 | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档集类型</typeparam> | |||
/// <param name="mongoDbContent"></param> | |||
/// <param name="collectionName">文档集名称</param> | |||
/// <param name="options"></param> | |||
public static void CreateCollection<TDocument>(this MongoDbContext mongoDbContent, string collectionName, | |||
CreateCollectionOptions options = null) | |||
{ | |||
mongoDbContent.Database.CreateCollection(collectionName, options); | |||
} | |||
/// <summary> | |||
/// 创建文档集索引,倒序 | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="collection"></param> | |||
/// <param name="indexFields"></param> | |||
/// <param name="model"></param> | |||
/// <param name="options"></param> | |||
public static void CreateIndex<TDocument>(this IMongoCollection<TDocument> collection, string[] indexFields, | |||
CreateIndexModel<TDocument> model, CreateOneIndexOptions options = null) | |||
{ | |||
if (indexFields == null) | |||
return; | |||
var indexKeys = Builders<TDocument>.IndexKeys; | |||
IndexKeysDefinition<TDocument> keys = null; | |||
if (indexFields.Length > 0) | |||
{ | |||
keys = indexKeys.Descending(indexFields[0]); | |||
} | |||
for (var i = 1; i < indexFields.Length; i++) | |||
{ | |||
var strIndex = indexFields[i]; | |||
keys = keys.Descending(strIndex); | |||
} | |||
if (keys != null) | |||
{ | |||
collection.Indexes.CreateOne(model, options); | |||
} | |||
} | |||
#endregion | |||
#region 插入扩展 | |||
/// <summary> | |||
/// 插入一个 ,等同使用:<code>IMongoCollection.InsertOne</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档集类型</typeparam> | |||
/// <param name="collection">文档集</param> | |||
/// <param name="document">文档对象</param> | |||
/// <param name="options">插入配置选项</param> | |||
public static void InsertOne<TDocument>(this IMongoCollection<TDocument> collection, TDocument document, | |||
InsertOneOptions options = null) | |||
{ | |||
collection.InsertOne(document, options, default); | |||
} | |||
/// <summary> | |||
/// 插入多个,等同使用: | |||
/// <code>IMongoCollection.InsertMany(IClientSessionHandle, IEnumerable{TDocument}, InsertManyOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档集类型</typeparam> | |||
/// <param name="collection">文档集</param> | |||
/// <param name="documents">文档对象</param> | |||
/// <param name="options">插入配置选项</param> | |||
public static void InsertMany<TDocument>(this IMongoCollection<TDocument> collection, | |||
IEnumerable<TDocument> documents, | |||
InsertManyOptions options = null) | |||
{ | |||
collection.InsertMany(documents, options, default); | |||
} | |||
#endregion | |||
#region 更新扩展 | |||
/// <summary> | |||
/// 构建更新操作定义 | |||
/// </summary> | |||
/// <param name="document">bsondocument文档</param> | |||
/// <param name="parent"></param> | |||
/// <returns></returns> | |||
private static List<UpdateDefinition<BsonDocument>> BuildUpdateDefinition(BsonDocument document, string parent) | |||
{ | |||
var updates = new List<UpdateDefinition<BsonDocument>>(); | |||
foreach (var element in document.Elements) | |||
{ | |||
var key = parent == null ? element.Name : $"{parent}.{element.Name}"; | |||
//子元素是对象 | |||
if (element.Value.IsBsonDocument) | |||
{ | |||
updates.AddRange(BuildUpdateDefinition(element.Value.ToBsonDocument(), key)); | |||
} | |||
//子元素是对象数组 | |||
else if (element.Value.IsBsonArray) | |||
{ | |||
var arrayDocs = element.Value.AsBsonArray; | |||
var i = 0; | |||
foreach (var doc in arrayDocs) | |||
{ | |||
if (doc.IsBsonDocument) | |||
{ | |||
updates.AddRange(BuildUpdateDefinition(doc.ToBsonDocument(), key + $".{i}")); | |||
} | |||
else | |||
{ | |||
updates.Add(Builders<BsonDocument>.Update.Set(f => f[key], element.Value)); | |||
continue; | |||
} | |||
i++; | |||
} | |||
} | |||
//子元素是其他 | |||
else | |||
{ | |||
updates.Add(Builders<BsonDocument>.Update.Set(f => f[key], element.Value)); | |||
} | |||
} | |||
return updates; | |||
} | |||
/// <summary> | |||
/// 更新满足条件的第一条数据, | |||
/// <code>IMongoCollection.UpdateOne(FilterDefinition{TDocument}, UpdateDefinition{TDocument}, UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="collection"></param> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
public static UpdateResult UpdateOne<TDocument>(this IMongoCollection<TDocument> collection, | |||
TDocument document, | |||
Expression<Func<TDocument, bool>> whereExpression, | |||
UpdateOptions options = null) | |||
{ | |||
var bsonDocument = document.ToBsonDocument(); | |||
bsonDocument.Remove("_id"); | |||
BsonDocument update = new BsonDocument | |||
{ | |||
{"$set", bsonDocument} | |||
}; | |||
return collection.UpdateOne(whereExpression, update, options); | |||
} | |||
/// <summary> | |||
/// 更新满足条件的第一条数据, | |||
/// <code>IMongoCollection.UpdateOne(FilterDefinition{TDocument}, UpdateDefinition{TDocument}, UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="collection"></param> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
public static Task<UpdateResult> UpdateOneAsync<TDocument>(this IMongoCollection<TDocument> collection, | |||
TDocument document, | |||
Expression<Func<TDocument, bool>> whereExpression, | |||
UpdateOptions options = null) | |||
{ | |||
var bsonDocument = document.ToBsonDocument(); | |||
bsonDocument.Remove("_id"); | |||
BsonDocument update = new BsonDocument | |||
{ | |||
{"$set", bsonDocument} | |||
}; | |||
return collection.UpdateOneAsync(whereExpression, update, options); | |||
} | |||
/// <summary> | |||
/// 更新满足条件的多条数据, | |||
/// <code>IMongoCollection.UpdateOne(FilterDefinition{TDocument}, UpdateDefinition{TDocument},UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="collection"></param> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
public static UpdateResult UpdateMany<TDocument>(this IMongoCollection<TDocument> collection, | |||
TDocument document, | |||
Expression<Func<TDocument, bool>> whereExpression, | |||
UpdateOptions options = null) | |||
{ | |||
var bsonDocument = document.ToBsonDocument(); | |||
bsonDocument.Remove("_id"); | |||
BsonDocument update = new BsonDocument | |||
{ | |||
{"$set", bsonDocument} | |||
}; | |||
return collection.UpdateMany(whereExpression, update, options); | |||
} | |||
/// <summary> | |||
/// 更新满足条件的多条数据, | |||
/// <code>IMongoCollection.UpdateOne(FilterDefinition{TDocument}, UpdateDefinition{TDocument},UpdateOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="collection"></param> | |||
/// <param name="document"></param> | |||
/// <param name="whereExpression"></param> | |||
/// <param name="options"></param> | |||
public static Task<UpdateResult> UpdateManyAsync<TDocument>(this IMongoCollection<TDocument> collection, | |||
TDocument document, | |||
Expression<Func<TDocument, bool>> whereExpression, | |||
UpdateOptions options = null) | |||
{ | |||
var bsonDocument = document.ToBsonDocument(); | |||
bsonDocument.Remove("_id"); | |||
BsonDocument update = new BsonDocument | |||
{ | |||
{"$set", bsonDocument} | |||
}; | |||
return collection.UpdateManyAsync(whereExpression, update, options); | |||
} | |||
/// <summary> | |||
/// 根据更新字段表达式组装UpdateDefinitioons | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="param"></param> | |||
/// <returns></returns> | |||
private static List<UpdateDefinition<TDocument>> BuildUpdateDefinitioonsByExpression<TDocument>( | |||
MemberInitExpression param) | |||
{ | |||
var fieldList = new List<UpdateDefinition<TDocument>>(); | |||
foreach (var item in param.Bindings) | |||
{ | |||
var propertyName = item.Member.Name; | |||
if (propertyName == "_id" || propertyName == "Id") | |||
continue; | |||
object propertyValue = null; | |||
if (!(item is MemberAssignment memberAssignment)) | |||
continue; | |||
if (memberAssignment.Expression.NodeType == ExpressionType.Constant) | |||
{ | |||
if (memberAssignment.Expression is ConstantExpression constantExpression) | |||
propertyValue = constantExpression.Value; | |||
} | |||
else | |||
{ | |||
if (memberAssignment.Expression is MethodCallExpression methodCallExpression2) | |||
{ | |||
if (methodCallExpression2.Method.Name == "AddToSet") | |||
{ | |||
var argument = methodCallExpression2.Arguments[1]; | |||
if (argument is ConstantExpression constantExpression) | |||
{ | |||
fieldList.Add( | |||
Builders<TDocument>.Update.AddToSet(propertyName, constantExpression.Value)); | |||
} | |||
else | |||
{ | |||
propertyValue = Expression.Lambda(argument, null).Compile().DynamicInvoke(); | |||
if (propertyValue is IEnumerable<object> lsArg) | |||
{ | |||
fieldList.Add(Builders<TDocument>.Update.AddToSetEach(propertyName, lsArg)); | |||
} | |||
else | |||
{ | |||
fieldList.Add(Builders<TDocument>.Update.AddToSet(propertyName, propertyValue)); | |||
} | |||
} | |||
continue; | |||
} | |||
} | |||
} | |||
propertyValue = Expression.Lambda(memberAssignment.Expression, null).Compile().DynamicInvoke(); | |||
fieldList.Add(Builders<TDocument>.Update.Set(propertyName, propertyValue)); | |||
} | |||
return fieldList; | |||
} | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的第一条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <typeparam name="TDocument">数据库实体类型</typeparam> | |||
/// <param name="collection"></param> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
public static UpdateResult UpdateOne<TDocument>(this IMongoCollection<TDocument> collection, | |||
Expression<Action<TDocument>> columnsExp, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
if (!(columnsExp.Body is MemberInitExpression param)) | |||
throw new ArgumentException($"{nameof(columnsExp)}错误,更新字段表达式示例: x=>new TDocument{{ F1 = 1,F2 = 2 }}"); | |||
List<UpdateDefinition<TDocument>> fieldList = BuildUpdateDefinitioonsByExpression<TDocument>(param); | |||
return collection.UpdateOne(whereExpression, Builders<TDocument>.Update.Combine(fieldList)); | |||
} | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的第一条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <typeparam name="TDocument">数据库实体类型</typeparam> | |||
/// <param name="collection"></param> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
public static Task<UpdateResult> UpdateOneAsync<TDocument>(this IMongoCollection<TDocument> collection, | |||
Expression<Action<TDocument>> columnsExp, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
if (!(columnsExp.Body is MemberInitExpression param)) | |||
throw new ArgumentException($"{nameof(columnsExp)}错误,更新字段表达式示例: x=>new TDocument{{ F1 = 1,F2 = 2 }}"); | |||
List<UpdateDefinition<TDocument>> fieldList = BuildUpdateDefinitioonsByExpression<TDocument>(param); | |||
return collection.UpdateOneAsync(whereExpression, Builders<TDocument>.Update.Combine(fieldList)); | |||
} | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的多条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <typeparam name="TDocument">数据库实体类型</typeparam> | |||
/// <param name="collection"></param> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
public static UpdateResult UpdateMany<TDocument>(this IMongoCollection<TDocument> collection, | |||
Expression<Action<TDocument>> columnsExp, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
if (!(columnsExp.Body is MemberInitExpression param)) | |||
throw new ArgumentException($"{nameof(columnsExp)}错误,更新字段表达式示例: x=>new TDocument{{ F1 = 1,F2 = 2 }}"); | |||
List<UpdateDefinition<TDocument>> fieldList = BuildUpdateDefinitioonsByExpression<TDocument>(param); | |||
return collection.UpdateMany(whereExpression, Builders<TDocument>.Update.Combine(fieldList)); | |||
} | |||
/// <summary> | |||
/// 自定义字段更新 更新满足条件的多条数据,实体键_id不允许更新 | |||
/// </summary> | |||
/// <typeparam name="TDocument">数据库实体类型</typeparam> | |||
/// <param name="collection"></param> | |||
/// <param name="whereExpression">更新条件</param> | |||
/// <param name="columnsExp">更新字段表达式:x=>new TDocument{ F1=1,F2=2 }</param> | |||
/// <returns></returns> | |||
public static Task<UpdateResult> UpdateManyAsync<TDocument>(this IMongoCollection<TDocument> collection, | |||
Expression<Action<TDocument>> columnsExp, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
if (!(columnsExp.Body is MemberInitExpression param)) | |||
throw new ArgumentException($"{nameof(columnsExp)}错误,更新字段表达式示例: x=>new TDocument{{ F1 = 1,F2 = 2 }}"); | |||
List<UpdateDefinition<TDocument>> fieldList = BuildUpdateDefinitioonsByExpression<TDocument>(param); | |||
return collection.UpdateManyAsync(whereExpression, Builders<TDocument>.Update.Combine(fieldList)); | |||
} | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 Id,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档对象类型</typeparam> | |||
/// <param name="collection">文档集操作接口</param> | |||
/// <param name="document">文档对象对象</param> | |||
/// <returns></returns> | |||
public static ReplaceOneResult ReplaceOneById<TDocument>(this IMongoCollection<TDocument> collection, | |||
TDocument document) | |||
{ | |||
var id = new ObjectId(typeof(TDocument).GetProperty("Id").GetValue(document).ToString()); | |||
return collection.ReplaceOne(new BsonDocument("_id", id), document); | |||
} | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 Id,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档对象类型</typeparam> | |||
/// <param name="collection">文档集操作接口</param> | |||
/// <param name="document">文档对象对象</param> | |||
/// <returns></returns> | |||
public static Task<ReplaceOneResult> ReplaceOneByIdAsync<TDocument>(this IMongoCollection<TDocument> collection, | |||
TDocument document) | |||
{ | |||
var id = new ObjectId(typeof(TDocument).GetProperty("Id").GetValue(document).ToString()); | |||
return collection.ReplaceOneAsync(new BsonDocument("_id", id), document); | |||
} | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 ID,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档对象类型</typeparam> | |||
/// <param name="collection">文档集操作接口</param> | |||
/// <param name="document">文档对象对象</param> | |||
/// <param name="whereExpression">查询添加表达式</param> | |||
/// <returns></returns> | |||
public static ReplaceOneResult ReplaceOne<TDocument>(this IMongoCollection<TDocument> collection, | |||
TDocument document, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
return collection.ReplaceOne(whereExpression, document); | |||
} | |||
/// <summary> | |||
/// 异步覆盖更新满足条件的第一条数据,主键字段名称必须是 ID,等同 | |||
/// <code>IMongoCollection.ReplaceOne(FilterDefinition{TDocument}, TDocument, ReplaceOptions, CancellationToken)</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档对象类型</typeparam> | |||
/// <param name="collection">文档集操作接口</param> | |||
/// <param name="document">文档对象对象</param> | |||
/// <param name="whereExpression">查询添加表达式</param> | |||
/// <returns></returns> | |||
public static Task<ReplaceOneResult> ReplaceOneAsync<TDocument>(this IMongoCollection<TDocument> collection, | |||
TDocument document, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
return collection.ReplaceOneAsync(whereExpression, document); | |||
} | |||
#endregion | |||
#region 删除扩展 | |||
/// <summary> | |||
/// 删除满足条件的第一条数据,等同于 | |||
/// <code>IMongoCollection.DeleteOne(FilterDefinition{TDocument}, CancellationToken)</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档对象类型</typeparam> | |||
/// <param name="collection">文档集操作接口</param> | |||
/// <param name="whereExpression">删除条件表达式</param> | |||
public static DeleteResult DeleteOne<TDocument>(this IMongoCollection<TDocument> collection, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
return collection.DeleteOne(whereExpression, null, default); | |||
} | |||
/// <summary> | |||
/// 批量删除满足条件的多条数据,等同于 | |||
/// <code>IMongoCollection.DeleteMany(FilterDefinition{TDocument}, CancellationToken)</code> | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档对象类型</typeparam> | |||
/// <param name="collection">文档集操作接口</param> | |||
/// <param name="whereExpression">删除条件表达式</param> | |||
public static DeleteResult DeleteMany<TDocument>(this IMongoCollection<TDocument> collection, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
return collection.DeleteMany(whereExpression, null, default); | |||
} | |||
#endregion | |||
#region 查询扩展 | |||
/// <summary> | |||
/// AggregateWithDefautSortOption | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="collection"></param> | |||
/// <param name="optionsAction"></param> | |||
/// <returns></returns> | |||
public static IAggregateFluent<TDocument> AggregateWithDefautSortOption<TDocument>( | |||
this IMongoCollection<TDocument> collection, | |||
Action<AggregateOptions> optionsAction = null) | |||
{ | |||
var options = new AggregateOptions | |||
{ | |||
Collation = new Collation(locale: "zh", numericOrdering: true), | |||
AllowDiskUse = true | |||
}; | |||
if (optionsAction != null) | |||
optionsAction(options); | |||
return collection.Aggregate(options); | |||
} | |||
/// <summary> | |||
/// 可查询 <see cref="IMongoCollectionExtensions.AsQueryable{TDocument}(IMongoCollection{TDocument}, AggregateOptions)"/> | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="collection"></param> | |||
/// <returns></returns> | |||
public static IMongoQueryable<TDocument> Queryable<TDocument>(this IMongoCollection<TDocument> collection) | |||
{ | |||
return collection.AsQueryable(DefaultAggregateOptions); | |||
} | |||
/// <summary> | |||
/// 分页查询,统计总共多少条 | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档集类型</typeparam> | |||
/// <param name="queryable">可查询器</param> | |||
/// <param name="pageIndex">页码,第几页,默认1</param> | |||
/// <param name="pageSize">每页条数,默认10</param> | |||
/// <param name="total">总共多少条</param> | |||
/// <returns></returns> | |||
public static List<TDocument> Pagination<TDocument>(this IQueryable<TDocument> queryable, int pageIndex, | |||
int pageSize, | |||
out int total) | |||
{ | |||
pageIndex = pageIndex < 0 ? 1 : pageIndex; | |||
pageSize = pageSize < 0 ? 10 : pageSize; | |||
total = queryable.Count(); | |||
return queryable.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); | |||
} | |||
/// <summary> | |||
/// 分页查询,统计总共多少条,可以根据查询新对象的表达式,返回新对象集合 | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档集类型</typeparam> | |||
/// <typeparam name="TNewResult">新结构类型</typeparam> | |||
/// <param name="queryable">可查询器</param> | |||
/// <param name="selector">查询func,查询返回新对象的表达式</param> | |||
/// <param name="pageIndex">页码,第几页,默认1</param> | |||
/// <param name="pageSize">每页条数,默认10</param> | |||
/// <param name="total">总共多少条</param> | |||
/// <returns></returns> | |||
public static List<TNewResult> Pagination<TDocument, TNewResult>(this IQueryable<TDocument> queryable, | |||
Expression<Func<TDocument, TNewResult>> selector, int pageIndex, int pageSize, out int total) | |||
{ | |||
pageIndex = pageIndex < 0 ? 1 : pageIndex; | |||
pageSize = pageSize < 0 ? 10 : pageSize; | |||
total = queryable.Count(); | |||
return queryable.Skip((pageIndex - 1) * pageSize).Take(pageSize).Select(selector).ToList(); | |||
} | |||
/// <summary> | |||
/// 分页查询 | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档集类型</typeparam> | |||
/// <param name="queryable">可查询器</param> | |||
/// <param name="pageIndex">页码,第几页,默认1</param> | |||
/// <param name="pageSize">每页条数,默认10</param> | |||
/// <returns></returns> | |||
public static List<TDocument> Pagination<TDocument>(this IQueryable<TDocument> queryable, int pageIndex, | |||
int pageSize) | |||
{ | |||
pageIndex = pageIndex < 0 ? 1 : pageIndex; | |||
pageSize = pageSize < 0 ? 10 : pageSize; | |||
return queryable.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); | |||
} | |||
/// <summary> | |||
/// 分页查询,可以根据查询新对象的表达式,返回新对象集合 | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档集类型</typeparam> | |||
/// <typeparam name="TNewResult">新结构类型</typeparam> | |||
/// <param name="queryable">可查询器</param> | |||
/// <param name="selector">查询func,查询返回新对象的表达式</param> | |||
/// <param name="pageIndex">页码,第几页,默认1</param> | |||
/// <param name="pageSize">每页条数,默认10</param> | |||
/// <returns></returns> | |||
public static List<TNewResult> Pagination<TDocument, TNewResult>(this IMongoQueryable<TDocument> queryable, | |||
Expression<Func<TDocument, TNewResult>> selector, int pageIndex, int pageSize) | |||
{ | |||
pageIndex = pageIndex < 0 ? 1 : pageIndex; | |||
pageSize = pageSize < 0 ? 10 : pageSize; | |||
return queryable.Skip((pageIndex - 1) * pageSize).Take(pageSize).Select(selector).ToList(); | |||
} | |||
/// <summary> | |||
/// 当condition为true,才会执行where表达式里面的条件 | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档集类型</typeparam> | |||
/// <param name="queryable">可查询器</param> | |||
/// <param name="beforeCondition">前置条件</param> | |||
/// <param name="whereExpression">where表达式</param> | |||
/// <returns></returns> | |||
public static IMongoQueryable<TDocument> WhereIF<TDocument>(this IMongoQueryable<TDocument> queryable, | |||
bool beforeCondition, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
if (beforeCondition) | |||
return queryable.Where(whereExpression); | |||
return queryable; | |||
} | |||
/// <summary> | |||
/// 当condition为true,才会执行where表达式里面的条件 | |||
/// </summary> | |||
/// <typeparam name="TDocument">文档集类型</typeparam> | |||
/// <param name="queryable">可查询器</param> | |||
/// <param name="beforeCondition">前置条件</param> | |||
/// <param name="whereExpression">where表达式</param> | |||
/// <returns></returns> | |||
public static IQueryable<TDocument> WhereIF<TDocument>(this IQueryable<TDocument> queryable, | |||
bool beforeCondition, | |||
Expression<Func<TDocument, bool>> whereExpression) | |||
{ | |||
if (beforeCondition) | |||
return queryable.Where(whereExpression); | |||
return queryable; | |||
} | |||
/// <summary> | |||
/// 根据selectNewResultExp 表达式返回新的查询结果,最终要执行 必须ToList、Single、 Any | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <typeparam name="TProjection"></typeparam> | |||
/// <typeparam name="TNewResult"></typeparam> | |||
/// <param name="find"></param> | |||
/// <param name="selectNewResultExp"></param> | |||
/// <returns></returns> | |||
public static IFindFluent<TDocument, TNewResult> As<TDocument, TProjection, TNewResult>( | |||
this IFindFluent<TDocument, TProjection> find, | |||
Expression<Func<TDocument, TNewResult>> selectNewResultExp) | |||
{ | |||
return find.Project(selectNewResultExp); | |||
} | |||
/// <summary> | |||
/// 根据selectNewResultExp 表达式返回新的查询结果,最终要执行 必须ToList、Single、 Any | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <typeparam name="TProjection"></typeparam> | |||
/// <typeparam name="TNewResult"></typeparam> | |||
/// <param name="find"></param> | |||
/// <param name="selectNewResultExp"></param> | |||
/// <returns></returns> | |||
public static IFindFluent<TDocument, TNewResult> Select<TDocument, TProjection, TNewResult>( | |||
this IFindFluent<TDocument, TProjection> find, | |||
Expression<Func<TDocument, TNewResult>> selectNewResultExp) | |||
{ | |||
return find.Project(selectNewResultExp); | |||
} | |||
#endregion | |||
#region 创建 查询 、索引、更新、排序 条件定义 | |||
/// <summary> | |||
/// 创建过滤条件定义 | |||
/// </summary> | |||
/// <param name="collection"></param> | |||
public static FilterDefinitionBuilder<TDocument> BuilderFilter<TDocument>( | |||
this IMongoCollection<TDocument> collection) | |||
{ | |||
return Builders<TDocument>.Filter; | |||
} | |||
/// <summary> | |||
/// 创建索引条件定义 | |||
/// </summary> | |||
/// <param name="collection"></param> | |||
public static IndexKeysDefinitionBuilder<TDocument> BuilderIndexKeys<TDocument>( | |||
this IMongoCollection<TDocument> collection) | |||
{ | |||
return Builders<TDocument>.IndexKeys; | |||
} | |||
/// <summary> | |||
/// 创建更新条件定义 | |||
/// </summary> | |||
/// <param name="collection"></param> | |||
public static UpdateDefinitionBuilder<TDocument> BuilderUpdate<TDocument>( | |||
this IMongoCollection<TDocument> collection) | |||
{ | |||
return Builders<TDocument>.Update; | |||
} | |||
/// <summary> | |||
/// 创建排序条件定义 | |||
/// </summary> | |||
/// <param name="collection"></param> | |||
public static SortDefinitionBuilder<TDocument> BuilderSort<TDocument>( | |||
this IMongoCollection<TDocument> collection) | |||
{ | |||
return Builders<TDocument>.Sort; | |||
} | |||
#endregion | |||
/// <summary> | |||
/// AddToSet 追加到数组 | |||
/// </summary> | |||
/// <typeparam name="T"></typeparam> | |||
/// <param name="source"></param> | |||
/// <param name="item"></param> | |||
/// <returns></returns> | |||
public static List<T> AddToSet<T>(this List<T> source, T item) | |||
{ | |||
return new List<T> {item}; | |||
} | |||
/// <summary> | |||
/// AddToSet 追加到数组 | |||
/// </summary> | |||
/// <typeparam name="T"></typeparam> | |||
/// <param name="source"></param> | |||
/// <param name="items"></param> | |||
/// <returns></returns> | |||
public static List<T> AddToSet<T>(this List<T> source, List<T> items) | |||
{ | |||
return items; | |||
} | |||
} | |||
} |
@@ -1,138 +0,0 @@ | |||
using MongoDB.Driver; | |||
namespace BPA.Component.MongoClient | |||
{ | |||
/// <summary> | |||
/// MongoDbContext 工厂 | |||
/// </summary> | |||
public abstract class MongoDbProvider | |||
{ | |||
/// <summary> | |||
/// 企业和别名的关系 | |||
/// </summary> | |||
protected readonly Dictionary<long, MongoDbContext> CorpWithMongoDbContexts = new(); | |||
/// <summary> | |||
/// 别名和mongondb实例的对应关系 | |||
/// </summary> | |||
protected readonly Dictionary<string, IMongoDatabase> AliasWithMongoDbContexts = new(); | |||
/// <summary> | |||
/// 别名和连接配置关系 | |||
/// </summary> | |||
public IReadOnlyDictionary<string, MongoDbConfig> AliasConfig { private set; get; } | |||
/// <summary> | |||
/// MongonDbFactory | |||
/// </summary> | |||
/// <param name="mongoDbConfigs"></param> | |||
public MongoDbProvider(List<MongoDbConfig> mongoDbConfigs) | |||
{ | |||
SetMongoDbConfigs(mongoDbConfigs); | |||
} | |||
/// <summary> | |||
/// 设置数据库连接配置 | |||
/// </summary> | |||
/// <param name="mongoDbConfigs"></param> | |||
public void SetMongoDbConfigs(List<MongoDbConfig> mongoDbConfigs) | |||
{ | |||
lock (this) | |||
{ | |||
var dic = new Dictionary<string, MongoDbConfig>(); | |||
foreach (var config in mongoDbConfigs) | |||
{ | |||
if (dic.ContainsKey(config.Alias)) | |||
throw new ArgumentException($"数据库{this.GetType().Name}的配置别名[{config.Alias}]出现重复"); | |||
dic.Add(config.Alias, config); | |||
} | |||
AliasConfig = dic; | |||
} | |||
} | |||
/// <summary> | |||
/// 根据企业ID获取MongoDb上下文对象 | |||
/// </summary> | |||
/// <param name="corpId">企业ID</param> | |||
/// <returns></returns> | |||
public virtual MongoDbContext GetDbContext(long corpId) | |||
{ | |||
if (CorpWithMongoDbContexts.ContainsKey(corpId)) | |||
return CorpWithMongoDbContexts[corpId]; | |||
lock (CorpWithMongoDbContexts) | |||
{ | |||
if (CorpWithMongoDbContexts.ContainsKey(corpId)) | |||
return CorpWithMongoDbContexts[corpId]; | |||
var dbAlias = GetDbAliasByCropId(corpId); | |||
if (dbAlias == null) | |||
throw new ArgumentException($"无法获取到企业[{corpId}]的{this.GetType().Name}数据库别名!"); | |||
if (!AliasConfig.ContainsKey(dbAlias)) | |||
throw new ArgumentException($"无法获取到企业[{corpId}]的{this.GetType().Name}数据库别名[{dbAlias}]对应的数据库连接!"); | |||
var databases = GetMongoDatabase(dbAlias); | |||
return CorpWithMongoDbContexts[corpId] = new MongoDbContext(corpId, databases.Client, databases); | |||
} | |||
} | |||
/// <summary> | |||
/// GetMongoDatabase | |||
/// </summary> | |||
/// <param name="dbAlias"></param> | |||
/// <returns></returns> | |||
public IMongoDatabase GetMongoDatabase(string dbAlias) | |||
{ | |||
IMongoDatabase mongoDatabase = null; | |||
lock (AliasWithMongoDbContexts) | |||
{ | |||
if (AliasWithMongoDbContexts.ContainsKey(dbAlias)) | |||
mongoDatabase = AliasWithMongoDbContexts[dbAlias]; | |||
else | |||
{ | |||
var mongoDbConfig = AliasConfig[dbAlias]; | |||
var client = new MongoDB.Driver.MongoClient(mongoDbConfig.ConnectionString); | |||
mongoDatabase = client.GetDatabase(mongoDbConfig.DatabasesName); | |||
AliasWithMongoDbContexts[dbAlias] = mongoDatabase; | |||
} | |||
} | |||
return mongoDatabase; | |||
} | |||
/// <summary> | |||
/// 获取所有的数据库操作对象 别名+数据库操作对象 | |||
/// </summary> | |||
/// <returns></returns> | |||
public IReadOnlyDictionary<string, IMongoDatabase> GetMongoDatabases() | |||
{ | |||
if (AliasConfig.Count != AliasWithMongoDbContexts.Count) | |||
{ | |||
foreach (var dbAlias in AliasConfig.Keys) | |||
{ | |||
GetMongoDatabase(dbAlias); | |||
} | |||
} | |||
return AliasWithMongoDbContexts; | |||
} | |||
/// <summary> | |||
/// 根据企业Id获取数据库别名,子类必须实现 | |||
/// </summary> | |||
/// <returns></returns> | |||
protected abstract string GetDbAliasByCropId(long corpId); | |||
/// <summary> | |||
/// 获取文档集接口 | |||
/// </summary> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <param name="cropId">企业ID</param> | |||
/// <param name="settings"></param> | |||
/// <returns></returns> | |||
public IMongoCollection<TDocument> GetCollection<TDocument>(long cropId, | |||
MongoCollectionSettings settings = null) | |||
{ | |||
MongoDbContext dbContext = GetDbContext(cropId); | |||
return dbContext.GetCollection<TDocument>(settings); | |||
} | |||
} | |||
} |
@@ -0,0 +1,99 @@ | |||
using BPA.Component.MongoClient.Conventions; | |||
using MongoDB.Bson; | |||
using MongoDB.Bson.Serialization; | |||
using MongoDB.Bson.Serialization.Conventions; | |||
using MongoDB.Bson.Serialization.Serializers; | |||
using MongoDB.Driver; | |||
using Newtonsoft.Json.Linq; | |||
namespace BPA.Component.MongoClient.Repository; | |||
/// <summary> | |||
/// MongoDb基础仓储 | |||
/// </summary> | |||
public class BaseMongoDbRepository<TMongoDbClient, TDocument> : IBaseMongoDbRepository<TDocument> | |||
where TMongoDbClient : BaseMongoDbClient<TMongoDbClient> | |||
where TDocument : class, new() | |||
{ | |||
/// <summary> | |||
/// MongoClient | |||
/// </summary> | |||
public MongoDB.Driver.MongoClient _mongoDbClient { get; } | |||
/// <summary> | |||
/// _Database | |||
/// </summary> | |||
private readonly IMongoDatabase _database; | |||
/// <summary> | |||
/// _Collection | |||
/// </summary> | |||
private IMongoCollection<TDocument> _collection; | |||
/// <summary> | |||
/// 构造函数 | |||
/// </summary> | |||
#pragma warning disable CS8618 | |||
internal BaseMongoDbRepository() | |||
#pragma warning restore CS8618 | |||
{ | |||
} | |||
/// <summary> | |||
/// 构造方法 | |||
/// </summary> | |||
public BaseMongoDbRepository(BaseMongoDbClient<TMongoDbClient> mongoDbClient) | |||
{ | |||
_mongoDbClient = mongoDbClient; | |||
_database = _mongoDbClient.GetDatabase(mongoDbClient.CurrentDatabaseName); | |||
var serializer = new DateTimeSerializer(DateTimeKind.Local, BsonType.DateTime); | |||
BsonSerializer.RegisterSerializer(typeof(DateTime), serializer); | |||
BsonSerializer.RegisterSerializer(typeof(JObject), new JObjectSerializer()); | |||
BsonSerializer.RegisterSerializer(typeof(JArray), new JArraySerializer()); | |||
BsonSerializer.RegisterSerializer(typeof(Dictionary<string, object>), new DictionarySerializerSerializer()); | |||
BsonSerializer.RegisterSerializer(typeof(decimal), new DecimalSerializer(BsonType.Decimal128)); | |||
BsonSerializer.RegisterSerializer(typeof(decimal?), new NullableSerializer<decimal>(new DecimalSerializer(BsonType.Decimal128))); | |||
BsonSerializer.RegisterSerializationProvider(new BPASerializationProvider()); | |||
ConventionRegistry.Register("IgnoreExtraElements", | |||
new ConventionPack | |||
{ | |||
new IgnoreExtraElementsConvention(true), new BPACamelCaseElementNameConvention(), | |||
new EnumRepresentationConvention(BsonType.String) | |||
}, _ => true); | |||
} | |||
/// <summary> | |||
/// 变更集合 | |||
/// </summary> | |||
/// <param name="collectionName"></param> | |||
public virtual void ChangeCollection(string collectionName) | |||
{ | |||
_collection = _database.GetCollection<TDocument>(collectionName); | |||
} | |||
/// <summary> | |||
/// 检查当前文档集 | |||
/// </summary> | |||
private void Checkcollection() | |||
{ | |||
if (_collection == null) | |||
{ | |||
throw new ArgumentNullException($"当前要操作的文档集为空,请调用{nameof(ChangeCollection)}方法切换集合文档"); | |||
} | |||
} | |||
/// <summary> | |||
/// 插入一个 | |||
/// </summary> | |||
/// <param name="document"></param> | |||
/// <typeparam name="TDocument"></typeparam> | |||
/// <returns></returns> | |||
public async Task<int> AddAsync<TDocument>(TDocument document) where TDocument : class, new() | |||
{ | |||
var coll = _database.GetCollection<TDocument>(document.GetType().Name); | |||
await coll.InsertOneAsync(document); | |||
return 1; | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
using MongoDB.Driver; | |||
namespace BPA.Component.MongoClient.Repository | |||
{ | |||
/// <summary> | |||
/// MongoDB仓储接口 | |||
/// </summary> | |||
public interface IBaseMongoDbRepository<TDocument> where TDocument : class, new() | |||
{ | |||
MongoDB.Driver.MongoClient _mongoDbClient { get; } | |||
} | |||
} |
@@ -5,10 +5,19 @@ | |||
<ImplicitUsings>enable</ImplicitUsings> | |||
<Nullable>enable</Nullable> | |||
<LangVersion>default</LangVersion> | |||
<OutputType>Exe</OutputType> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="BPA.Component.MongoClient" Version="1.0.1" /> | |||
<ProjectReference Include="..\..\BPA.Component.ApolloClient\BPA.Component.ApolloClient\BPA.Component.ApolloClient.csproj"/> | |||
<ProjectReference Include="..\BPA.Component.MongoClient\BPA.Component.MongoClient.csproj"/> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0"/> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.0"/> | |||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" /> | |||
</ItemGroup> | |||
</Project> |
@@ -1,771 +1,61 @@ | |||
// using BPA.Component.Extensions; | |||
// using BPA.Component.MongoClient; | |||
// using BPA.Component.MongoClientTester.Models; | |||
// using BPA.Component.MongoClientTester.Repositorys; | |||
// using MongoDB.Driver; | |||
// | |||
// namespace BPA.Component.MongoClientTester | |||
// { | |||
// internal class Program | |||
// { | |||
// private static readonly MongoDbConfig TestDbConfig = new MongoDbConfig | |||
// { | |||
// ConnectionString = "mongodb://root:a5014e2c9c5890d517179be4a5c9f9ac@192.168.0.150:27017/?authSource=admin", | |||
// DatabasesName = "test", | |||
// Alias = "crm-test-01" | |||
// }; | |||
// | |||
// private static List<string> _redisCluster = new List<string> | |||
// { | |||
// "192.168.0.149:6380,poolsize=50,ssl=false,writeBuffer=10240", | |||
// "192.168.0.147:6380,poolsize=50,ssl=false,writeBuffer=10240", | |||
// "192.168.0.150:6380,poolsize=50,ssl=false,writeBuffer=10240" | |||
// }; | |||
// | |||
// private static readonly long corpId = 10000; | |||
// | |||
// private static void Main(string[] args) | |||
// { | |||
// Console.WriteLine("1=测试Provider,2=测试Repository,3=TestWatch"); | |||
// var cmd = Console.ReadLine(); | |||
// switch (cmd) | |||
// { | |||
// case "1": | |||
// TestMongonDbProvider(); | |||
// break; | |||
// case "2": | |||
// TestRepository(); | |||
// break; | |||
// default: | |||
// Console.WriteLine("命令错误"); | |||
// break; | |||
// } | |||
// | |||
// Console.ReadLine(); | |||
// } | |||
// | |||
// | |||
// //创建provider | |||
// private static TestMongoDbProvider _testMongoDbProvider = | |||
// new TestMongoDbProvider(new List<MongoDbConfig> {TestDbConfig}); | |||
// | |||
// static void TestWatchMock() | |||
// { | |||
// var corpInfoRepository = new CorpInfoRepository(_testMongoDbProvider); | |||
// //必须切换企业ID | |||
// corpInfoRepository.ChangeCorpId(corpId); | |||
// | |||
// #region 插入 | |||
// | |||
// var insertCorpInfos = new List<CorpInfo>(); | |||
// for (var i = 0; i < 10000; i++) | |||
// { | |||
// insertCorpInfos.Add(new CorpInfo | |||
// { | |||
// CorpId = corpId, | |||
// Id = BPAUniqueIdBulder.NextLong(), | |||
// Phones = new List<string> {$"1921682012{i}"}, | |||
// AddressInfos = new List<CorpAddressInfo> | |||
// { | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, | |||
// Address = ",''''''''''' %%%%天府大道天府三街", Remark = "一号办公地点" | |||
// }, | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府五街", | |||
// Remark = "二号办公地点" | |||
// }, | |||
// }, | |||
// Creator = new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// Name = null, | |||
// No = $"sun{i}", | |||
// Tags = new Dictionary<string, object> | |||
// { | |||
// {"string", $"string{i}"}, | |||
// {"int", 10 + i}, | |||
// {"double", 20.00 + 1}, | |||
// {"datetime", DateTime.Now.AddMinutes(i)}, | |||
// {"bool", i % 2}, | |||
// } | |||
// }); | |||
// } | |||
// | |||
// Thread.Sleep(1000); | |||
// //批量插入 | |||
// corpInfoRepository.InsertMany(insertCorpInfos); | |||
// | |||
// #endregion | |||
// | |||
// #region 更新 | |||
// | |||
// Thread.Sleep(1000); | |||
// corpInfoRepository.UpdateMany(x => new CorpInfo | |||
// { | |||
// Phones = x.Phones.AddToSet("sss ' ,\" \\ \\\\ $ @@@ ") | |||
// }, x => x.No.StartsWith("sun")); | |||
// | |||
// #endregion | |||
// | |||
// return; | |||
// | |||
// #region 删除 | |||
// | |||
// Thread.Sleep(1000); | |||
// var data = DateTime.Now.AddMinutes(5); | |||
// corpInfoRepository.DeleteMany(x => x.CreateDate <= data); | |||
// | |||
// #endregion | |||
// } | |||
// | |||
// static void TestRepository() | |||
// { | |||
// //创建provider | |||
// var testMongonDbProvider = new TestMongoDbProvider(new List<MongoDbConfig> {TestDbConfig}); | |||
// ICorpInfoRepository corpInfoRepository = new CorpInfoRepository(testMongonDbProvider); | |||
// | |||
// //必须切换企业ID | |||
// corpInfoRepository.ChangeCorpId(corpId); | |||
// | |||
// //清空 测试数据清空下,一般清空是不要用到这个方法 | |||
// corpInfoRepository.CurrMongoDbContext.ClearCollection<CorpInfo>(); | |||
// | |||
// | |||
// #region 插入 | |||
// | |||
// var tags = new Dictionary<string, object> | |||
// { | |||
// {"datetime", DateTime.Now}, | |||
// {"array0-1", new object[] {1, true, 66.2D, EnumEmployeeStatusType.Normal, DateTime.Now, ""}}, | |||
// {"array00", null}, | |||
// {"array01", new List<string> {"sss", "bbb"}}, | |||
// {"array02", new List<string[]> {new string[] {"1", "2"}, new string[] {"3", "4"}}}, | |||
// { | |||
// "array03", | |||
// new List<CorpAddressInfo> | |||
// { | |||
// new CorpAddressInfo | |||
// {Address = "ss", Id = DateTime.Now.Ticks, Latitude = 1, Longitude = 2, Remark = ""} | |||
// } | |||
// }, | |||
// }; | |||
// // tags = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(tags.ToJson()); | |||
// //插入单个 | |||
// corpInfoRepository.InsertOneAsync(new CorpInfo | |||
// { | |||
// EnumEmployee = EnumEmployeeStatusType.Normal, | |||
// CorpId = corpId, | |||
// Id = BPAUniqueIdBulder.NextLong(), | |||
// DB = long.MaxValue, | |||
// AddressInfos = new List<CorpAddressInfo> | |||
// { | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府五街", | |||
// Remark = "二号办公地点" | |||
// }, | |||
// }, | |||
// Name = "太阳国1", | |||
// No = "sun1", | |||
// Creator = new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// Tags = tags, | |||
// Phones = new List<string> {"1921682012", "1921682012", "1921682012"} | |||
// }); | |||
// | |||
// corpInfoRepository.InsertOneAsync(new CorpInfo | |||
// { | |||
// CorpId = corpId, | |||
// Id = BPAUniqueIdBulder.NextLong(), | |||
// AddressInfos = new List<CorpAddressInfo> | |||
// { | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府五街", | |||
// Remark = "二号办公地点" | |||
// }, | |||
// }, | |||
// Creator = new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// Name = "太阳国2", | |||
// No = "sun2", | |||
// Tags = new Dictionary<string, object> | |||
// { | |||
// {"string", "string"}, | |||
// {"int", 10}, | |||
// {"double", 20.00}, | |||
// {"datetime", DateTime.Now}, | |||
// {"bool", true}, | |||
// {"array0-1", new object[] {1, true, 66.2D, EnumEmployeeStatusType.Normal, DateTime.Now, ""}}, | |||
// { | |||
// "复杂的", | |||
// new List<CorpAddressInfo> | |||
// { | |||
// new CorpAddressInfo | |||
// { | |||
// Id = DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// } | |||
// } | |||
// }, | |||
// Phones = new List<string> {"1921682013", "1921682014", "1921682015"}, | |||
// Ids = new List<long> {122238324489609220, 124675751317626880, 168259568508141570, 229039077946073100} | |||
// }); | |||
// | |||
// Task.WaitAll(); | |||
// | |||
// var all = corpInfoRepository.Queryable().ToList(); | |||
// | |||
// return; | |||
// | |||
// var insertCorpInfos = new List<CorpInfo>(); | |||
// for (var i = 3; i < 10; i++) | |||
// { | |||
// insertCorpInfos.Add(new CorpInfo | |||
// { | |||
// CorpId = corpId, | |||
// Id = BPAUniqueIdBulder.NextLong(), | |||
// AddressInfos = new List<CorpAddressInfo> | |||
// { | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, | |||
// Address = ",''''''''''' %%%%天府大道天府三街", Remark = "一号办公地点" | |||
// }, | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府五街", | |||
// Remark = "二号办公地点" | |||
// }, | |||
// }, | |||
// Creator = new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// Name = null, | |||
// No = $"sun{i}", | |||
// Tags = new Dictionary<string, object> | |||
// { | |||
// {"string", $"string{i}"}, | |||
// {"int", 10 + i}, | |||
// {"double", 20.00 + 1}, | |||
// {"datetime", DateTime.Now.AddMinutes(i)}, | |||
// {"bool", i % 2}, | |||
// } | |||
// }); | |||
// } | |||
// | |||
// Console.ReadLine(); | |||
// //批量插入 | |||
// corpInfoRepository.InsertMany(insertCorpInfos); | |||
// | |||
// #endregion | |||
// | |||
// var filters = corpInfoRepository.BuilderFilter(); | |||
// var filterDefinitions = new List<FilterDefinition<CorpInfo>> | |||
// { | |||
// filters.Eq("No", "sun1") | |||
// }; | |||
// FilterDefinition<CorpInfo> filterDefinition = filters.And(filterDefinitions); | |||
// var finder = corpInfoRepository.Find(filterDefinition); | |||
// var result = finder.FirstOrDefault(); | |||
// Console.WriteLine("使用 Find 进行查询:"); | |||
// Console.WriteLine(result.ToJson()); | |||
// | |||
// | |||
// #region 查询 Queryable 强烈推荐使用 | |||
// | |||
// Console.WriteLine("使用 Queryable 进行查询 :"); | |||
// var phones = new List<string> {"1921682012", "1921682013", "1921682014"}; | |||
// var ssss = corpInfoRepository.Queryable().Where(x => x.Phones.Any(x => phones.Contains(x))); | |||
// var r2 = ssss.ToList(); | |||
// Console.WriteLine(r2); | |||
// Console.WriteLine(); | |||
// | |||
// var dys = corpInfoRepository.Queryable().Select(x => new A {Name = x.Name}); | |||
// var r = dys.ToList(); | |||
// Console.WriteLine(r); | |||
// Console.WriteLine(); | |||
// | |||
// | |||
// Console.WriteLine("使用 Queryable 进行查询 个别字段:"); | |||
// var dys2 = corpInfoRepository.Queryable().Where(x => x.Id > 0).Select(x => new {x.Id, x.Creator}) | |||
// .FirstOrDefault(); | |||
// Console.WriteLine(dys2.ToJson()); | |||
// Console.WriteLine(); | |||
// | |||
// //使用 Queryable 进行查询 | |||
// var corpSun1 = corpInfoRepository.Queryable().FirstOrDefault(x => x.No == "sun1"); | |||
// var corpSun2 = corpInfoRepository.Queryable().FirstOrDefault(x => x.No == "sun2"); | |||
// Console.WriteLine("使用 Queryable 进行查询:"); | |||
// Console.WriteLine(corpSun2.ToJson()); | |||
// | |||
// | |||
// //WhereIF | |||
// var corpSunpNoRefix = "sun"; | |||
// var corpSuns = corpInfoRepository | |||
// .Queryable() | |||
// .Where(x => x.Id > 0) | |||
// //corpSunpNoRefix.IsNotEmpty()==true 时,才会带上后面的查询添加 | |||
// .WhereIF(corpSunpNoRefix.IsNotEmpty(), x => x.No.Contains(corpSunpNoRefix)) | |||
// .ToList(); | |||
// Console.WriteLine("WhereIF:"); | |||
// Console.WriteLine(corpSuns.ToJson()); | |||
// | |||
// //Queryable 分页查询 带 total | |||
// var paginationResult1 = corpInfoRepository.Queryable() | |||
// .Where(x => x.No.Contains(corpSunpNoRefix)) | |||
// .Pagination(1, 5, out int total); | |||
// | |||
// Console.WriteLine("Queryable 分页查询 带 total:"); | |||
// Console.WriteLine(total); | |||
// Console.WriteLine(paginationResult1.ToJson()); | |||
// | |||
// //Queryable 分页查询 不带 total | |||
// var paginationResult2 = corpInfoRepository.Queryable() | |||
// .Where(x => x.No.Contains(corpSunpNoRefix)) | |||
// .OrderBy(x => x.No) | |||
// .Pagination(1, 5); | |||
// Console.WriteLine("Queryable 分页查询 不带 total:"); | |||
// Console.WriteLine(paginationResult2.ToJson()); | |||
// | |||
// | |||
// //动态字段查询 | |||
// var queryResult1 = corpInfoRepository.Queryable() | |||
// .Where(x => (string) x.Tags["string"] == "string") | |||
// .OrderBy(x => x.No) | |||
// .Pagination(1, 5); | |||
// var queryResult2 = corpInfoRepository.Queryable() | |||
// .Where(x => (DateTime) x.Tags["datetime"] < DateTime.Now) | |||
// .OrderBy(x => x.No) | |||
// .Pagination(1, 5); | |||
// Console.WriteLine("动态字段查询:"); | |||
// Console.WriteLine(queryResult1.ToJson()); | |||
// Console.WriteLine(queryResult2.ToJson()); | |||
// | |||
// //更新下 方便下面left join 查看效果 | |||
// corpInfoRepository.UpdateOne(x => new CorpInfo {No = "sun1"}, x => x.No == "sun11"); | |||
// | |||
// #endregion | |||
// | |||
// #region 更新 | |||
// | |||
// //更新符合条件的第一条数据 更新整个对象 | |||
// corpSun1.Phones.Add("我是新增的"); | |||
// var updateOneResult = corpInfoRepository.UpdateOne(corpSun1, x => x.No == "sun10"); | |||
// Console.WriteLine("更新整个对象:"); | |||
// Console.WriteLine(updateOneResult.ToJson()); | |||
// | |||
// var fieldList = Builders<CorpInfo>.Update.AddToSet("ids", 220827615942565900); | |||
// FilterDefinition<CorpInfo> filter = Builders<CorpInfo>.Filter.Eq("No", "sun2"); | |||
// corpInfoRepository.UpdateOne(filter, fieldList); | |||
// | |||
// corpInfoRepository.UpdateOne(x => new CorpInfo | |||
// { | |||
// Ids = x.Ids.AddToSet((long) 220827615942565900) | |||
// }, x => x.No.StartsWith("sun2")); | |||
// | |||
// | |||
// corpInfoRepository.UpdateOne(x => new CorpInfo | |||
// { | |||
// Phones = x.Phones.AddToSet("sss ' ,\" \\ \\\\ $ @@@ ") | |||
// }, x => x.No.StartsWith("sun2")); | |||
// corpInfoRepository.UpdateOne(x => new CorpInfo | |||
// { | |||
// Phones = x.Phones.AddToSet(new List<string> {"sss", "22222"}) | |||
// }, x => x.No.StartsWith("sun2")); | |||
// | |||
// var sss = corpInfoRepository.UpdateOne(x => new CorpInfo | |||
// { | |||
// //Id = corpSun1.Id, | |||
// CreateDate = DateTime.MinValue, | |||
// Phones = corpSun1.Phones.AddToSet("AddToSet"), | |||
// AddressInfos = corpSun1.AddressInfos.AddToSet(new CorpAddressInfo {Id = 0, Address = "AddToSet"}) | |||
// }, x => x.No.StartsWith("sun2")); | |||
// | |||
// //更新 自定义字段 实体键_id不允许更新 | |||
// corpSun1.Phones.Add("我是新增的222222222222222222"); | |||
// corpSun1.AddressInfos.Add(new CorpAddressInfo {Address = "新增的3"}); | |||
// var updateOneResult2 = corpInfoRepository.UpdateOne(x => new CorpInfo | |||
// { | |||
// //Id = corpSun1.Id, | |||
// CreateDate = DateTime.MinValue, | |||
// Phones = corpSun1.Phones, | |||
// AddressInfos = corpSun1.AddressInfos | |||
// }, x => x.No.StartsWith("sun2")); | |||
// Console.WriteLine("更新 自定义字段:"); | |||
// Console.WriteLine(updateOneResult2.ToJson()); | |||
// | |||
// //更新多个 更新整个对象 | |||
// corpSun1.Phones.Add("UpdateMany 更新整个对象"); | |||
// var updateOneResult3 = corpInfoRepository.UpdateMany(corpSun1, x => x.No == "sun1"); | |||
// Console.WriteLine("更新多个 更新整个对象:"); | |||
// Console.WriteLine(updateOneResult3.ToJson()); | |||
// | |||
// //更新多个 更新整个对象 自定义字段 | |||
// corpSun1.Phones.Add("UpdateMany 自定义字段"); | |||
// var updateOneResult4 = corpInfoRepository.UpdateMany(x => new CorpInfo | |||
// { | |||
// Phones = corpSun1.Phones, | |||
// }, x => x.No.StartsWith("sun")); | |||
// Console.WriteLine("更新多个 自定义字段 :"); | |||
// Console.WriteLine(updateOneResult4.ToJson()); | |||
// | |||
// #endregion | |||
// | |||
// | |||
// #region 删除 | |||
// | |||
// //根据条件删除 一个 | |||
// var deleteResult = corpInfoRepository.DeleteOne(x => x.No == "sun1"); | |||
// Console.WriteLine("根据条件删除 一个:"); | |||
// Console.WriteLine(deleteResult.ToJson()); | |||
// | |||
// //根据条件删除 多个 | |||
// var deleteResult2 = corpInfoRepository.DeleteMany(x => x.No.StartsWith("sun1")); | |||
// Console.WriteLine("根据条件删除 多个:"); | |||
// Console.WriteLine(deleteResult2.ToJson()); | |||
// | |||
// #endregion | |||
// | |||
// //清空 测试数据清空下,一般清空是不要用到这个方法 | |||
// corpInfoRepository.DeleteMany(x => x.Id > 0); | |||
// //清空 测试数据清空下,一般清空是不要用到这个方法 | |||
// //corpInfoRepository.CurrMongoDbContext.ClearCollection<CorpInfo>(); | |||
// } | |||
// | |||
// /// <summary> | |||
// /// 测试Provider | |||
// /// </summary> | |||
// /// <param name="args"></param> | |||
// static void TestMongonDbProvider() | |||
// { | |||
// //Console.WriteLine(1.GetHashCode()); | |||
// //Console.WriteLine(1.GetHashCode()); | |||
// //Console.WriteLine(1.GetHashCode()); | |||
// | |||
// //Console.WriteLine(2.GetHashCode()); | |||
// //Console.WriteLine(2.GetHashCode()); | |||
// //Console.WriteLine(2.GetHashCode()); | |||
// | |||
// //创建provider | |||
// var testMongonDbProvider = new TestMongoDbProvider(new List<MongoDbConfig> {TestDbConfig}); | |||
// //BPATestMongoDbContext 必须要继承 BPAMongoDbContext | |||
// var testDbContext = testMongonDbProvider.GetDbContext(corpId); | |||
// | |||
// //根据企业ID构建文档集名称 | |||
// var corpInfoCollectionName = testDbContext.BuildCollectionName<CorpInfo>(corpId); | |||
// Console.WriteLine(corpInfoCollectionName); | |||
// | |||
// | |||
// //获取文档集操作接口对象, | |||
// var corpInfoCollection = testMongonDbProvider.GetCollection<CorpInfo>(corpId); | |||
// | |||
// //清空 测试数据清空下,一般清空是不要用到这个方法 | |||
// testDbContext.ClearCollection<CorpInfo>(); | |||
// | |||
// #region 插入 | |||
// | |||
// //插入单个 | |||
// corpInfoCollection.InsertOne(new CorpInfo | |||
// { | |||
// Id = BPAUniqueIdBulder.NextLong(), | |||
// AddressInfos = new List<CorpAddressInfo> | |||
// { | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府五街", | |||
// Remark = "二号办公地点" | |||
// }, | |||
// }, | |||
// Creator = new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// Name = "太阳国1", | |||
// No = "sun1", | |||
// Tags = new Dictionary<string, object> | |||
// { | |||
// {"string", null}, | |||
// {"int", null}, | |||
// {"double", null}, | |||
// {"datetime", null}, | |||
// {"bool", null}, | |||
// }, | |||
// Phones = new List<string> {"1921682012", "1921682012", "1921682012"} | |||
// }); | |||
// corpInfoCollection.InsertOne(new CorpInfo | |||
// { | |||
// Id = BPAUniqueIdBulder.NextLong(), | |||
// AddressInfos = new List<CorpAddressInfo> | |||
// { | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府五街", | |||
// Remark = "二号办公地点" | |||
// }, | |||
// }, | |||
// Creator = new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// Name = "太阳国2", | |||
// No = "sun2", | |||
// Tags = new Dictionary<string, object> | |||
// { | |||
// {"string", "string"}, | |||
// {"int", 10}, | |||
// {"double", 20.00}, | |||
// {"datetime", DateTime.Now}, | |||
// {"bool", true}, | |||
// } | |||
// }); | |||
// | |||
// var insertCorpInfos = new List<CorpInfo>(); | |||
// for (var i = 3; i < 10; i++) | |||
// { | |||
// insertCorpInfos.Add(new CorpInfo | |||
// { | |||
// Id = BPAUniqueIdBulder.NextLong(), | |||
// AddressInfos = new List<CorpAddressInfo> | |||
// { | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府五街", | |||
// Remark = "二号办公地点" | |||
// }, | |||
// }, | |||
// Creator = new CorpAddressInfo | |||
// { | |||
// Id = (long) DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", | |||
// Remark = "一号办公地点" | |||
// }, | |||
// Name = $"太阳国{i}", | |||
// No = $"sun{i}", | |||
// Tags = new Dictionary<string, object> | |||
// { | |||
// {"string", $"string{i}"}, | |||
// {"int", 10 + i}, | |||
// {"double", 20.00 + 1}, | |||
// {"datetime", DateTime.Now.AddMinutes(i)}, | |||
// {"bool", i % 2}, | |||
// } | |||
// }); | |||
// } | |||
// | |||
// //批量插入 | |||
// corpInfoCollection.InsertMany(insertCorpInfos); | |||
// | |||
// #endregion | |||
// | |||
// #region 查询 Queryable 强烈推荐使用 | |||
// | |||
// //使用 Queryable 进行查询 | |||
// | |||
// var dys = corpInfoCollection.Queryable().Where(x => x.Id > 0).Select(x => new {x.Creator, x.Id}) | |||
// .FirstOrDefault(); | |||
// Console.WriteLine(dys.ToJson()); | |||
// | |||
// var corpSun1 = corpInfoCollection.Queryable().FirstOrDefault(x => x.No == "sun1"); | |||
// var corpSun2 = corpInfoCollection.Queryable().FirstOrDefault(x => x.No == "sun2"); | |||
// Console.WriteLine("使用 Queryable 进行查询:"); | |||
// Console.WriteLine(corpSun2.ToJson()); | |||
// | |||
// | |||
// //WhereIF | |||
// var corpSunpNoRefix = "sun"; | |||
// var corpSuns = corpInfoCollection | |||
// .Queryable() | |||
// //corpSunpNoRefix.IsNotEmpty()==true 时,才会带上后面的查询添加 | |||
// .WhereIF(corpSunpNoRefix.IsNotEmpty(), x => x.No.Contains(corpSunpNoRefix)) | |||
// .ToList(); | |||
// Console.WriteLine("WhereIF:"); | |||
// Console.WriteLine(corpSuns.ToJson()); | |||
// | |||
// //Queryable 分页查询 带 total | |||
// var paginationResult1 = corpInfoCollection.Queryable() | |||
// .Where(x => x.No.Contains(corpSunpNoRefix)) | |||
// .Pagination(1, 5, out int total); | |||
// | |||
// Console.WriteLine("Queryable 分页查询 带 total:"); | |||
// Console.WriteLine(total); | |||
// Console.WriteLine(paginationResult1.ToJson()); | |||
// | |||
// //Queryable 分页查询 不带 total | |||
// var paginationResult2 = corpInfoCollection.Queryable() | |||
// .Where(x => x.No.Contains(corpSunpNoRefix)) | |||
// .OrderBy(x => x.No) | |||
// .Pagination(1, 5); | |||
// Console.WriteLine("Queryable 分页查询 不带 total:"); | |||
// Console.WriteLine(paginationResult2.ToJson()); | |||
// | |||
// | |||
// //动态字段查询 | |||
// var queryResult1 = corpInfoCollection.Queryable() | |||
// .Where(x => (string) x.Tags["string"] == "string") | |||
// .OrderBy(x => x.No) | |||
// .Pagination(1, 5); | |||
// var queryResult2 = corpInfoCollection.Queryable() | |||
// .Where(x => (DateTime) x.Tags["datetime"] < DateTime.Now) | |||
// .OrderBy(x => x.No) | |||
// .Pagination(1, 5); | |||
// Console.WriteLine("动态字段查询:"); | |||
// Console.WriteLine(queryResult1.ToJson()); | |||
// Console.WriteLine(queryResult2.ToJson()); | |||
// | |||
// //更新下 方便下面left join 查看效果 | |||
// corpInfoCollection.UpdateOne(x => new CorpInfo {No = "sun1"}, x => x.No == "sun11"); | |||
// | |||
// // left join | |||
// var quryable1 = corpInfoCollection.Queryable(); | |||
// var quryable2 = corpInfoCollection.Queryable(); | |||
// var quryable5 = corpInfoCollection.Queryable(); | |||
// var quryable3 = from c1 in quryable1 | |||
// //left join | |||
// join c2 in quryable2 | |||
// on c1.No equals c2.No into temp | |||
// from tt in temp.DefaultIfEmpty() | |||
// join c5 in quryable5 | |||
// on c1.No equals c5.No into temp2 | |||
// from tt2 in temp2.DefaultIfEmpty() | |||
// where c1.No == "sun1" | |||
// select new | |||
// { | |||
// C1Id = c1.Id, | |||
// C1No = c1.No, | |||
// //C2Id = tt.Id, | |||
// //C2No = tt.No, | |||
// //C3Id = tt2.Id, | |||
// //C3No = tt2.No, | |||
// //C2Id = tt == null ? ObjectId.Empty : tt.Id, | |||
// //C2No = tt == null ? string.Empty : tt.No, | |||
// //C3Id = tt2 == null ? ObjectId.Empty : tt2.Id, | |||
// //C3No = tt2 == null ? string.Empty : tt2.No | |||
// }; | |||
// //var quryable3 = from c1 in quryable1 | |||
// // //left join | |||
// // join c2 in quryable2 on c1.No equals c2.No into temp | |||
// // from tt in temp.DefaultIfEmpty() | |||
// // select new { c1, tt }; | |||
// //quryable3 = quryable3.Where(x => x.c1.No == "sun1"); | |||
// //var quryable4 = quryable3.Select(x => new | |||
// //{ | |||
// // C1Id = x.c1.Id, | |||
// // C1No = x.c1.No, | |||
// // C2Id = x.tt == null ? ObjectId.Empty : x.tt.Id, | |||
// // C2No = x.tt == null ? string.Empty : x.tt.No | |||
// //}); | |||
// quryable3 = quryable3.Where(x => x.C1No == "sun1"); | |||
// | |||
// Console.WriteLine(quryable3.ToString()); | |||
// var leftJoinReuslt = quryable3.ToList(); | |||
// Console.WriteLine("left join:"); | |||
// Console.WriteLine(leftJoinReuslt.ToJson()); | |||
// | |||
// #endregion | |||
// | |||
// #region 更新 | |||
// | |||
// //更新符合条件的第一条数据 更新整个对象 | |||
// corpSun1.Phones.Add("我是新增的"); | |||
// var updateOneResult = corpInfoCollection.UpdateOne(corpSun1, x => x.No == "sun10"); | |||
// Console.WriteLine("更新整个对象:"); | |||
// Console.WriteLine(updateOneResult.ToJson()); | |||
// | |||
// //更新 自定义字段 实体键_id不允许更新 | |||
// corpSun1.Phones.Add("我是新增的2"); | |||
// corpSun1.AddressInfos.Each(it => it.Id = (long) DateTime.Now.Ticks); | |||
// corpSun1.AddressInfos.Add(new CorpAddressInfo {Address = "新增的3"}); | |||
// var updateOneResult2 = corpInfoCollection.UpdateOne(x => new CorpInfo | |||
// { | |||
// //Id = corpSun1.Id, | |||
// CreateDate = DateTime.Now.AddDays(50), | |||
// Phones = corpSun1.Phones, | |||
// AddressInfos = corpSun1.AddressInfos | |||
// }, x => x.No.StartsWith("sun2")); | |||
// Console.WriteLine("更新 自定义字段:"); | |||
// Console.WriteLine(updateOneResult2.ToJson()); | |||
// | |||
// //更新多个 更新整个对象 | |||
// corpSun1.Phones.Add("UpdateMany 更新整个对象"); | |||
// var updateOneResult3 = corpInfoCollection.UpdateMany(corpSun1, x => x.No == "sun1"); | |||
// Console.WriteLine("更新多个 更新整个对象:"); | |||
// Console.WriteLine(updateOneResult3.ToJson()); | |||
// | |||
// //更新多个 更新整个对象 自定义字段 | |||
// corpSun1.Phones.Add("UpdateMany 自定义字段"); | |||
// var updateOneResult4 = corpInfoCollection.UpdateMany(x => new CorpInfo | |||
// { | |||
// Phones = corpSun1.Phones, | |||
// }, x => x.No == "sun1"); | |||
// Console.WriteLine("更新多个 自定义字段 :"); | |||
// Console.WriteLine(updateOneResult4.ToJson()); | |||
// | |||
// #endregion | |||
// | |||
// | |||
// #region 删除 | |||
// | |||
// //根据条件删除 一个 | |||
// var deleteResult = corpInfoCollection.DeleteOne(x => x.No == "sun1"); | |||
// Console.WriteLine("根据条件删除 一个:"); | |||
// Console.WriteLine(deleteResult.ToJson()); | |||
// | |||
// //根据条件删除 多个 | |||
// var deleteResult2 = corpInfoCollection.DeleteMany(x => x.No.StartsWith("sun1")); | |||
// Console.WriteLine("根据条件删除 多个:"); | |||
// Console.WriteLine(deleteResult2.ToJson()); | |||
// | |||
// #endregion | |||
// | |||
// //清空 测试数据清空下,一般清空是不要用到这个方法 | |||
// testDbContext.ClearCollection<CorpInfo>(); | |||
// Console.ReadLine(); | |||
// } | |||
// } | |||
// | |||
// public class A | |||
// { | |||
// public string Name { set; get; } | |||
// } | |||
// } | |||
using BPA.Component.ApolloClient; | |||
using BPA.Component.DbClientTester; | |||
using BPA.Component.MongoClientTester.Models; | |||
using BPA.Component.MongoClientTester.Repositorys; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Logging; | |||
namespace BPA.Component.MongoClientTester; | |||
internal class Program | |||
{ | |||
private static async Task Main(string[] args) | |||
{ | |||
var builder = new ConfigurationBuilder(); | |||
builder.AddEnvironmentVariables(); | |||
IConfiguration configuration = builder.Build(); | |||
configuration.AddApolloConfiguration(); | |||
var services = new ServiceCollection(); | |||
services.AddApollo<TestConfig>(); | |||
services.AddLogging(configure => { configure.AddConsole(); }); | |||
services.AddScoped<TestMongoDcClient>(); | |||
services.AddTransient<ICorpInfoRepository, CorpInfoRepository>(); | |||
var serviceProvider = services.BuildServiceProvider(); | |||
var testDbClient = serviceProvider.GetService<TestMongoDcClient>(); | |||
if (testDbClient == null) return; | |||
var userRepository = serviceProvider.GetService<ICorpInfoRepository>(); | |||
var tags = new Dictionary<string, object> | |||
{ | |||
{"datetime", DateTime.Now}, | |||
{"array0-1", new object[] {1, true, 66.2D, Enums.Aaa, DateTime.Now, ""}}, | |||
{"array00", null}, | |||
{"array01", new List<string> {"sss", "bbb"}}, | |||
{"array02", new List<string[]> {new[] {"1", "2"}, new[] {"3", "4"}}}, | |||
{"array03", new List<CorpAddressInfo> {new() {Address = "ss", Id = DateTime.Now.Ticks, Latitude = 1, Longitude = 2, Remark = ""}}}, | |||
}; | |||
await userRepository.AddAsync(new CorpInfo | |||
{ | |||
DB = long.MaxValue, | |||
AddressInfos = new List<CorpAddressInfo> | |||
{ | |||
new() {Id = DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", Remark = "一号办公地点"}, | |||
new() {Id = DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府五街", Remark = "二号办公地点"}, | |||
}, | |||
Name = "太阳国1", | |||
No = "sun1", | |||
Creator = new CorpAddressInfo {Id = DateTime.Now.Ticks, Latitude = 66.52, Longitude = 451.63, Address = "天府大道天府三街", Remark = "一号办公地点"}, | |||
Tags = tags, | |||
Phones = new List<string> {"1921682012", "1921682012", "1921682012"} | |||
}); | |||
} | |||
} | |||
public enum Enums | |||
{ | |||
Aaa = 1, | |||
Bbb = 2 | |||
} |
@@ -3,9 +3,10 @@ | |||
"BPA.Component.LogClientTester": { | |||
"commandName": "Project", | |||
"environmentVariables": { | |||
"APOLLO_META_SERVER_URL": "http://192.168.0.147:7010", | |||
"APOLLO_COMMON_NAMESPACE": "BPA.test.common", | |||
"APP_NAME": "BPA.test" | |||
"ASPNETCORE_ENVIRONMENT": "Development", | |||
"APOLLO_META_SERVER_URL": "http://10.2.1.21:28080", | |||
"APOLLO_COMMON_NAMESPACE": "Dev.Common", | |||
"APP_NAME": "BPA-DEV" | |||
} | |||
} | |||
} |
@@ -1,12 +1,16 @@ | |||
using BPA.Component.MongoClient; | |||
using BPA.Component.MongoClient.Repository; | |||
using BPA.Component.MongoClientTester.Models; | |||
namespace BPA.Component.MongoClientTester.Repositorys | |||
{ | |||
public class CorpInfoRepository : BaseMGRepository<CorpInfo>, ICorpInfoRepository | |||
public class CorpInfoRepository : BaseMongoDbRepository<TestMongoDcClient, CorpInfo>, ICorpInfoRepository | |||
{ | |||
public CorpInfoRepository(TestMongoDbProvider mongoDbProvider) : base(mongoDbProvider) | |||
public CorpInfoRepository(TestMongoDcClient mongoDbClient) : base(mongoDbClient) | |||
{ | |||
} | |||
} | |||
} |
@@ -1,9 +1,10 @@ | |||
using BPA.Component.MongoClient; | |||
using BPA.Component.MongoClient.Repository; | |||
using BPA.Component.MongoClientTester.Models; | |||
namespace BPA.Component.MongoClientTester.Repositorys | |||
{ | |||
public interface ICorpInfoRepository : IMGRepository<CorpInfo> | |||
public interface ICorpInfoRepository : IBaseMongoDbRepository<CorpInfo> | |||
{ | |||
Task<int> AddAsync<TDocument>(TDocument document) where TDocument : class, new(); | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
using BPA.Component.ApolloClient; | |||
using BPA.Component.MongoClient; | |||
using Com.Ctrip.Framework.Apollo; | |||
using Microsoft.Extensions.Configuration; | |||
namespace BPA.Component.DbClientTester; | |||
/// <summary> | |||
/// test项目配置 | |||
/// </summary> | |||
public class TestConfig : ApolloBPAConfig<TestConfig> | |||
{ | |||
[AutoWrite] | |||
public MongoConfig MongoDbForWebApi1Db { get; set; } | |||
public TestConfig(ApolloConfigurationManager apolloConfigurationManager, IConfiguration configuration) : base(apolloConfigurationManager, configuration) | |||
{ | |||
} | |||
} |
@@ -1,24 +0,0 @@ | |||
using BPA.Component.MongoClient; | |||
namespace BPA.Component.MongoClientTester | |||
{ | |||
/// <summary> | |||
/// 测试数据库 TestMongoDbProvider | |||
/// </summary> | |||
public class TestMongoDbProvider : MongoDbProvider | |||
{ | |||
public TestMongoDbProvider(List<MongoDbConfig> mongoDbConfigs) : base(mongoDbConfigs) | |||
{ | |||
} | |||
/// <summary> | |||
/// 根据企业ID获取数据库别名 | |||
/// </summary> | |||
/// <param name="corpId"></param> | |||
/// <returns></returns> | |||
protected override string GetDbAliasByCropId(long corpId) | |||
{ | |||
return "test-01"; | |||
} | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
using BPA.Component.DbClientTester; | |||
using BPA.Component.MongoClient; | |||
using Microsoft.Extensions.Logging; | |||
namespace BPA.Component.MongoClientTester; | |||
public class TestMongoDcClient : BaseMongoDbClient<TestMongoDcClient> | |||
{ | |||
public TestMongoDcClient(TestConfig config, ILogger<TestMongoDcClient> logger = null) | |||
: base(BuildMongoConfig(config.MongoDbForWebApi1Db.ConnectionString, config.MongoDbForWebApi1Db.DatabasesName), logger) | |||
{ | |||
} | |||
} |