Pārlūkot izejas kodu

提交monogodb代码

dev/1.0.1
stevelee pirms 2 gadiem
vecāks
revīzija
05681b7796
22 mainītis faili ar 285 papildinājumiem un 4479 dzēšanām
  1. +2
    -2
      src/BPA.Component.DbClient/BPA.Component.DbClient/BaseDbClient.cs
  2. +2
    -1
      src/BPA.Component.DbClient/BPA.Component.DbClientTester/TestDbClient.cs
  3. +1
    -1
      src/BPA.Component.LogClient/BPA.Component.LogClientTester/Properties/launchSettings.json
  4. +1
    -0
      src/BPA.Component.MongoClient/BPA.Component.MongoClient/BPA.Component.MongoClient.csproj
  5. +0
    -1580
      src/BPA.Component.MongoClient/BPA.Component.MongoClient/BPA.Component.MongoClient.xml
  6. +0
    -631
      src/BPA.Component.MongoClient/BPA.Component.MongoClient/BaseMGRepository.cs
  7. +49
    -0
      src/BPA.Component.MongoClient/BPA.Component.MongoClient/BaseMongoDbClient.cs
  8. +0
    -425
      src/BPA.Component.MongoClient/BPA.Component.MongoClient/IMGRepository.cs
  9. +2
    -7
      src/BPA.Component.MongoClient/BPA.Component.MongoClient/MongoConfig.cs
  10. +0
    -177
      src/BPA.Component.MongoClient/BPA.Component.MongoClient/MongoDbContext.cs
  11. +0
    -714
      src/BPA.Component.MongoClient/BPA.Component.MongoClient/MongoDbExtensions.cs
  12. +0
    -138
      src/BPA.Component.MongoClient/BPA.Component.MongoClient/MongoDbProvider.cs
  13. +99
    -0
      src/BPA.Component.MongoClient/BPA.Component.MongoClient/Repository/BaseMongoDbRepository.cs
  14. +12
    -0
      src/BPA.Component.MongoClient/BPA.Component.MongoClient/Repository/IBaseMongoDbRepository.cs
  15. +10
    -1
      src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/BPA.Component.MongoClientTester.csproj
  16. +61
    -771
      src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/Program.cs
  17. +4
    -3
      src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/Properties/launchSettings.json
  18. +6
    -2
      src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/Repositorys/CorpInfoRepository.cs
  19. +3
    -2
      src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/Repositorys/ICorpInfoRepository.cs
  20. +20
    -0
      src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/TestConfig.cs
  21. +0
    -24
      src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/TestMongoDbProvider.cs
  22. +13
    -0
      src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/TestMongoDcClient.cs

src/BPA.Component.DbClient/BPA.Component.DbClient/RepositoryModel/BaseDbClient.cs → src/BPA.Component.DbClient/BPA.Component.DbClient/BaseDbClient.cs Parādīt failu

@@ -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;


+ 2
- 1
src/BPA.Component.DbClient/BPA.Component.DbClientTester/TestDbClient.cs Parādīt failu

@@ -1,4 +1,5 @@
using BPA.Component.DbClient.RepositoryModel;
using BPA.Component.DbClient;
using BPA.Component.DbClient.RepositoryModel;
using Microsoft.Extensions.Logging;
using SqlSugar;



+ 1
- 1
src/BPA.Component.LogClient/BPA.Component.LogClientTester/Properties/launchSettings.json Parādīt failu

@@ -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"
}


+ 1
- 0
src/BPA.Component.MongoClient/BPA.Component.MongoClient/BPA.Component.MongoClient.csproj Parādīt failu

@@ -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>


+ 0
- 1580
src/BPA.Component.MongoClient/BPA.Component.MongoClient/BPA.Component.MongoClient.xml
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Parādīt failu


+ 0
- 631
src/BPA.Component.MongoClient/BPA.Component.MongoClient/BaseMGRepository.cs Parādīt failu

@@ -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
}
}

+ 49
- 0
src/BPA.Component.MongoClient/BPA.Component.MongoClient/BaseMongoDbClient.cs Parādīt failu

@@ -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;
}
}

+ 0
- 425
src/BPA.Component.MongoClient/BPA.Component.MongoClient/IMGRepository.cs Parādīt failu

@@ -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
}
}

src/BPA.Component.MongoClient/BPA.Component.MongoClient/MongoDbConfig.cs → src/BPA.Component.MongoClient/BPA.Component.MongoClient/MongoConfig.cs Parādīt failu

@@ -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; }
}

+ 0
- 177
src/BPA.Component.MongoClient/BPA.Component.MongoClient/MongoDbContext.cs Parādīt failu

@@ -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()
{
}
}
}

+ 0
- 714
src/BPA.Component.MongoClient/BPA.Component.MongoClient/MongoDbExtensions.cs Parādīt failu

@@ -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;
}
}
}

+ 0
- 138
src/BPA.Component.MongoClient/BPA.Component.MongoClient/MongoDbProvider.cs Parādīt failu

@@ -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);
}
}
}

+ 99
- 0
src/BPA.Component.MongoClient/BPA.Component.MongoClient/Repository/BaseMongoDbRepository.cs Parādīt failu

@@ -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;
}
}

+ 12
- 0
src/BPA.Component.MongoClient/BPA.Component.MongoClient/Repository/IBaseMongoDbRepository.cs Parādīt failu

@@ -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; }
}
}

+ 10
- 1
src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/BPA.Component.MongoClientTester.csproj Parādīt failu

@@ -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>

+ 61
- 771
src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/Program.cs Parādīt failu

@@ -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
}

+ 4
- 3
src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/Properties/launchSettings.json Parādīt failu

@@ -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"
}
}
}

+ 6
- 2
src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/Repositorys/CorpInfoRepository.cs Parādīt failu

@@ -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)
{
}
}
}

+ 3
- 2
src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/Repositorys/ICorpInfoRepository.cs Parādīt failu

@@ -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();
}
}

+ 20
- 0
src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/TestConfig.cs Parādīt failu

@@ -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)
{
}
}

+ 0
- 24
src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/TestMongoDbProvider.cs Parādīt failu

@@ -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";
}
}
}

+ 13
- 0
src/BPA.Component.MongoClient/BPA.Component.MongoClientTester/TestMongoDcClient.cs Parādīt failu

@@ -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)
{
}
}

Notiek ielāde…
Atcelt
Saglabāt