using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Linq.Expressions;
using System.Security;
using System.Threading;
using Dpz.Core.Infrastructure;
using Dpz.Core.Infrastructure.Entity;
using Microsoft.Extensions.Logging;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
namespace Dpz.Core.MongodbAccess;
public abstract class MongodbAccess
{
private readonly record struct Db(string DatabaseName, IMongoClient Client);
private static readonly Lazy<ConcurrentDictionary<string, Db>> LazyMongoClients = new();
private readonly string _connectionString;
internal MongodbAccess(string? connectionString)
{
if (string.IsNullOrEmpty(connectionString))
{
if (!LazyMongoClients.Value.IsEmpty)
{
_connectionString = LazyMongoClients.Value.First().Key;
return;
}
throw new Exception("mongodb connection string is not configured");
}
_connectionString = connectionString;
TryAddClient(connectionString);
}
/// <summary>
/// 获取Mongodb客户端
/// </summary>
internal IMongoClient Client => LazyMongoClients.Value[_connectionString].Client ??
throw new Exception("IMongoClient value is null");
/// <summary>
/// 获取 MongoDB 数据库
/// </summary>
internal IMongoDatabase Database => Client.GetDatabase(LazyMongoClients.Value[_connectionString].DatabaseName);
protected ILoggerFactory LoggerFactoryDb => LoggerFactory.Create(loggerBuilder =>
loggerBuilder
.AddConsole()
.AddDebug());
internal static IClientSessionHandle StartSession(string? connectionString,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(connectionString))
throw new Exception("connection string has no value");
TryAddClient(connectionString);
return LazyMongoClients.Value[connectionString].Client.StartSession(cancellationToken: cancellationToken);
}
private static void TryAddClient(string connectionString)
{
if (LazyMongoClients is not { IsValueCreated: true } || !LazyMongoClients.Value.ContainsKey(connectionString))
{
var url = MongoUrl.Create(connectionString);
var databaseName = string.IsNullOrEmpty(url.DatabaseName)
? throw new Exception("no database specified")
: url.DatabaseName;
LazyMongoClients.Value.TryAdd(connectionString, new Db(databaseName, new MongoClient(url)));
}
}
}
/// <summary>
/// Mongodb 数据库访问抽象类
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class MongodbAccess<T> : MongodbAccess where T : IBaseEntity, new()
{
public MongodbAccess(string? connectionString) : base(connectionString)
{
}
public MongodbAccess(string? connectionString, string collectionName) : base(connectionString)
{
CollectionName = collectionName;
}
/// <summary>
/// database collection name
/// </summary>
internal readonly string CollectionName = typeof(T).Name;
/// <summary>
/// 获取 该实体中 MongoDB数据库的集合
/// </summary>
public IMongoCollection<T> Collection => Database.GetCollection<T>(CollectionName);
/// <summary>
/// 获取 提供对MongoDB数据查询的Queryable
/// </summary>
/// <returns></returns>
public IMongoQueryable<T> MongoQueryable => Database.GetCollection<T>(CollectionName).AsQueryable(
//update 2020年5月6日 内存限制写入临时文件 https://docs.mongodb.com/manual/reference/command/aggregate/
new AggregateOptions { AllowDiskUse = true });
}