提交代码
This commit is contained in:
parent
c6ab491746
commit
d16a678b8b
|
|
@ -5,31 +5,27 @@ using CloudGaming.DtoModel;
|
|||
using HuanMeng.DotNetCore.AttributeExtend;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
namespace CloudGaming.Api.Controllers;
|
||||
|
||||
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
||||
|
||||
namespace CloudGaming.Api.Controllers
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class AppController : CloudGamingControllerBase
|
||||
{
|
||||
public AppController(IServiceProvider _serviceProvider) : base(_serviceProvider)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class AppController : CloudGamingControllerBase
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<AppConfigDto> GetAppConfigAsync()
|
||||
{
|
||||
public AppController(IServiceProvider _serviceProvider) : base(_serviceProvider)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<AppConfigDto> GetAppConfigAsync()
|
||||
{
|
||||
AppConfigBLL appConfigBLL = new AppConfigBLL(ServiceProvider);
|
||||
var appConfig = await appConfigBLL.GetAppConfig();
|
||||
return appConfig;
|
||||
}
|
||||
|
||||
|
||||
AppConfigBLL appConfigBLL = new AppConfigBLL(ServiceProvider);
|
||||
var appConfig = await appConfigBLL.GetAppConfig();
|
||||
return appConfig;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,318 +12,314 @@ using HuanMeng.DotNetCore.CacheHelper;
|
|||
using System.Collections.Concurrent;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace CloudGaming.Code.Cache
|
||||
namespace CloudGaming.Code.Cache;
|
||||
|
||||
/// <summary>
|
||||
/// 缓存数据表
|
||||
/// </summary>
|
||||
public class CloudGamingCache
|
||||
{
|
||||
/// <summary>
|
||||
/// 缓存数据表
|
||||
/// </summary>
|
||||
public class CloudGamingCache
|
||||
private readonly CloudGamingBase _gamingBase;
|
||||
|
||||
public CloudGamingCache(CloudGamingBase gamingBase)
|
||||
{
|
||||
private readonly CloudGamingBase _gamingBase;
|
||||
_gamingBase = gamingBase;
|
||||
}
|
||||
|
||||
public CloudGamingCache(CloudGamingBase gamingBase)
|
||||
#region 通用缓存获取方法
|
||||
|
||||
/// <summary>
|
||||
/// 通用缓存获取方法,适用于所有类型
|
||||
/// </summary>
|
||||
private List<T> GetCacheList<T>(ref CommonDataEntityCache<T>? cache, Expression<Func<T, bool>>? expWhere = null) where T : class
|
||||
{
|
||||
if (cache == null)
|
||||
{
|
||||
_gamingBase = gamingBase;
|
||||
cache = CloudGamingCacheExtend.GetDataEntityCache(_gamingBase, expWhere);
|
||||
}
|
||||
return cache.DataList ?? new List<T>();
|
||||
}
|
||||
|
||||
#region 通用缓存获取方法
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 通用缓存获取方法,适用于所有类型
|
||||
/// </summary>
|
||||
private List<T> GetCacheList<T>(ref CommonDataEntityCache<T>? cache, Expression<Func<T, bool>>? expWhere = null) where T : class
|
||||
#region 图片缓存表
|
||||
|
||||
private CommonDataEntityCache<T_App_Image>? _appImageCache;
|
||||
|
||||
/// <summary>
|
||||
/// 图片缓存列表
|
||||
/// </summary>
|
||||
public List<T_App_Image> AppImageList => GetCacheList(ref _appImageCache);
|
||||
|
||||
#endregion
|
||||
|
||||
#region 配置缓存表
|
||||
|
||||
private CommonDataEntityCache<AppConfigCache>? _appConfigCache;
|
||||
|
||||
/// <summary>
|
||||
/// 配置缓存列表
|
||||
/// </summary>
|
||||
public List<AppConfigCache> AppConfigList
|
||||
{
|
||||
get
|
||||
{
|
||||
if (cache == null)
|
||||
if (_appConfigCache == null)
|
||||
{
|
||||
cache = CloudGamingCacheExtend.GetDataEntityCache(_gamingBase, expWhere);
|
||||
_appConfigCache = new AppConfigEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper, _gamingBase.AppConfig);
|
||||
}
|
||||
return cache.DataList ?? new List<T>();
|
||||
return _appConfigCache.DataList ?? new List<AppConfigCache>();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 图片缓存表
|
||||
#endregion
|
||||
|
||||
private CommonDataEntityCache<T_App_Image>? _appImageCache;
|
||||
#region 首页缓存表
|
||||
|
||||
/// <summary>
|
||||
/// 图片缓存列表
|
||||
/// </summary>
|
||||
public List<T_App_Image> AppImageList => GetCacheList(ref _appImageCache);
|
||||
private CommonDataEntityCache<T_Epg_CategoryCfg>? _epgCategoryCfg;
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// 菜单分类
|
||||
/// </summary>
|
||||
public List<T_Epg_CategoryCfg> EpgCategoryCfg => GetCacheList(ref _epgCategoryCfg, it => it.IsOnline);
|
||||
#endregion
|
||||
|
||||
#region 配置缓存表
|
||||
|
||||
private CommonDataEntityCache<AppConfigCache>? _appConfigCache;
|
||||
private GameEntityCache? gameEntityCache;
|
||||
|
||||
/// <summary>
|
||||
/// 配置缓存列表
|
||||
/// </summary>
|
||||
public List<AppConfigCache> AppConfigList
|
||||
/// <summary>
|
||||
/// 游戏缓存
|
||||
/// </summary>
|
||||
public GameEntityCache GameEntityCache
|
||||
{
|
||||
get
|
||||
{
|
||||
get
|
||||
if (gameEntityCache == null)
|
||||
{
|
||||
if (_appConfigCache == null)
|
||||
{
|
||||
_appConfigCache = new AppConfigEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper, _gamingBase.AppConfig);
|
||||
}
|
||||
return _appConfigCache.DataList ?? new List<AppConfigCache>();
|
||||
gameEntityCache = new GameEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper, _gamingBase.AppConfig);
|
||||
}
|
||||
return gameEntityCache;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 首页缓存表
|
||||
|
||||
private CommonDataEntityCache<T_Epg_CategoryCfg>? _epgCategoryCfg;
|
||||
|
||||
/// <summary>
|
||||
/// 菜单分类
|
||||
/// </summary>
|
||||
public List<T_Epg_CategoryCfg> EpgCategoryCfg => GetCacheList(ref _epgCategoryCfg, it => it.IsOnline);
|
||||
#endregion
|
||||
|
||||
|
||||
private GameEntityCache? gameEntityCache;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏缓存
|
||||
/// </summary>
|
||||
public GameEntityCache GameEntityCache
|
||||
}
|
||||
/// <summary>
|
||||
/// 游戏列表
|
||||
/// </summary>
|
||||
public List<GameInfo> GameInfos
|
||||
{
|
||||
get
|
||||
{
|
||||
get
|
||||
{
|
||||
if (gameEntityCache == null)
|
||||
{
|
||||
gameEntityCache = new GameEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper, _gamingBase.AppConfig);
|
||||
}
|
||||
return gameEntityCache;
|
||||
}
|
||||
|
||||
return GameEntityCache?.DataList ?? new List<GameInfo>();
|
||||
}
|
||||
/// <summary>
|
||||
/// 游戏列表
|
||||
/// </summary>
|
||||
public List<GameInfo> GameInfos
|
||||
}
|
||||
|
||||
#region 图片缓存
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private ImageEntityCache imageEntityCache;
|
||||
|
||||
/// <summary>
|
||||
/// 图片缓存
|
||||
/// </summary>
|
||||
public ImageEntityCache ImageEntityCache
|
||||
{
|
||||
get
|
||||
{
|
||||
get
|
||||
if (imageEntityCache == null)
|
||||
{
|
||||
|
||||
return GameEntityCache?.DataList ?? new List<GameInfo>();
|
||||
imageEntityCache = new ImageEntityCache(_gamingBase.Dao, _gamingBase.AppConfig, _gamingBase.RedisCache, _gamingBase.AppRequestInfo);
|
||||
}
|
||||
return imageEntityCache;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 图片缓存
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private ProductCacheEntityCache productCacheEntityCache;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private ImageEntityCache imageEntityCache;
|
||||
|
||||
/// <summary>
|
||||
/// 图片缓存
|
||||
/// </summary>
|
||||
public ImageEntityCache ImageEntityCache
|
||||
/// <summary>
|
||||
/// 产品缓存
|
||||
/// </summary>
|
||||
public ProductCacheEntityCache ProductCacheEntityCache
|
||||
{
|
||||
get
|
||||
{
|
||||
get
|
||||
if (productCacheEntityCache == null)
|
||||
{
|
||||
if (imageEntityCache == null)
|
||||
{
|
||||
imageEntityCache = new ImageEntityCache(_gamingBase.Dao, _gamingBase.AppConfig, _gamingBase.RedisCache, _gamingBase.AppRequestInfo);
|
||||
}
|
||||
return imageEntityCache;
|
||||
productCacheEntityCache = new ProductCacheEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper);
|
||||
}
|
||||
return productCacheEntityCache;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private ProductCacheEntityCache productCacheEntityCache;
|
||||
|
||||
/// <summary>
|
||||
/// 产品缓存
|
||||
/// </summary>
|
||||
public ProductCacheEntityCache ProductCacheEntityCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (productCacheEntityCache == null)
|
||||
{
|
||||
productCacheEntityCache = new ProductCacheEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper);
|
||||
}
|
||||
return productCacheEntityCache;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 产品列表
|
||||
/// </summary>
|
||||
public List<ProductCache> ProductCacheList
|
||||
{
|
||||
get
|
||||
{
|
||||
return ProductCacheEntityCache.DataList ?? new List<ProductCache>();
|
||||
}
|
||||
}
|
||||
|
||||
#region 七天签到
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private SevenDayEntityCache sevenDayEntityCache;
|
||||
|
||||
/// <summary>
|
||||
/// 七天签到缓存
|
||||
/// </summary>
|
||||
public SevenDayEntityCache SevenDayEntityCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (sevenDayEntityCache == null)
|
||||
{
|
||||
sevenDayEntityCache = new SevenDayEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper);
|
||||
}
|
||||
return sevenDayEntityCache;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 七天签到列表
|
||||
/// </summary>
|
||||
public List<SevenDayCache> SevenDayList
|
||||
{
|
||||
get
|
||||
{
|
||||
return SevenDayEntityCache.DataList ?? new List<SevenDayCache>();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 兑换码
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private RedemptionCodeEntityCache redemptionCodeEntityCache;
|
||||
|
||||
/// <summary>
|
||||
/// 兑换码缓存
|
||||
/// </summary>
|
||||
public RedemptionCodeEntityCache RedemptionCodeEntityCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (redemptionCodeEntityCache == null)
|
||||
{
|
||||
redemptionCodeEntityCache = new RedemptionCodeEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper);
|
||||
}
|
||||
return redemptionCodeEntityCache;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 兑换码列表
|
||||
/// </summary>
|
||||
public List<RedemptionCodeCache> RedemptionCodeList
|
||||
{
|
||||
get
|
||||
{
|
||||
return RedemptionCodeEntityCache.DataList ?? new List<RedemptionCodeCache>();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
#region 首页缓存表
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 游戏缓存扩展
|
||||
/// 产品列表
|
||||
/// </summary>
|
||||
public static class CloudGamingCacheExtend
|
||||
public List<ProductCache> ProductCacheList
|
||||
{
|
||||
private static readonly ConcurrentDictionary<Type, object> ExtCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||
private static readonly ConcurrentDictionary<Type, object> GameCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||
private static readonly ConcurrentDictionary<Type, object> AppCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||
private static readonly ConcurrentDictionary<Type, object> UserCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||
|
||||
/// <summary>
|
||||
/// 命名空间与缓存映射
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, (ConcurrentDictionary<Type, object> cacheList, AppDataBaseType dbType)> NamespaceMapping;
|
||||
|
||||
static CloudGamingCacheExtend()
|
||||
get
|
||||
{
|
||||
NamespaceMapping = new Dictionary<string, (ConcurrentDictionary<Type, object> cacheList, AppDataBaseType dbType)>
|
||||
{
|
||||
{ "CloudGaming.GameModel.Db.Db_Ext", (ExtCacheLockList, AppDataBaseType.Ext) },
|
||||
{ "CloudGaming.GameModel.Db.Db_Game", (GameCacheLockList, AppDataBaseType.Game) },
|
||||
{ "CloudGaming.Model.DbSqlServer.Db_Phone", (AppCacheLockList, AppDataBaseType.App) },
|
||||
{ "CloudGaming.Model.DbSqlServer.Db_User", (UserCacheLockList, AppDataBaseType.User) }
|
||||
};
|
||||
return ProductCacheEntityCache.DataList ?? new List<ProductCache>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取实体缓存
|
||||
/// </summary>
|
||||
public static CommonDataEntityCache<T> GetDataEntityCache<T>(CloudGamingBase cloudGamingBase, Expression<Func<T, bool>>? expWhere = null, int cacheTime = 36000) where T : class
|
||||
#region 七天签到
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private SevenDayEntityCache sevenDayEntityCache;
|
||||
|
||||
/// <summary>
|
||||
/// 七天签到缓存
|
||||
/// </summary>
|
||||
public SevenDayEntityCache SevenDayEntityCache
|
||||
{
|
||||
get
|
||||
{
|
||||
var typeLock = typeof(T);
|
||||
var namespaceKey = typeLock.Namespace;
|
||||
|
||||
if (namespaceKey == null || !NamespaceMapping.ContainsKey(namespaceKey))
|
||||
if (sevenDayEntityCache == null)
|
||||
{
|
||||
throw new Exception($"缓存数据不存在或命名空间不匹配:{namespaceKey}");
|
||||
sevenDayEntityCache = new SevenDayEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper);
|
||||
}
|
||||
|
||||
var (cacheList, dbType) = NamespaceMapping[namespaceKey];
|
||||
object cacheLock = GetOrAddCacheLock(typeLock, cacheList);
|
||||
CacheBaseConfig cacheBaseConfig = cloudGamingBase.ToCacheBaseConfig(dbType);
|
||||
|
||||
return new DataBaseEntityCache<T>(cacheBaseConfig, cacheLock, expWhere: expWhere, cacheTime: cacheTime);
|
||||
return sevenDayEntityCache;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或添加缓存锁对象
|
||||
/// </summary>
|
||||
private static object GetOrAddCacheLock(Type typeLock, ConcurrentDictionary<Type, object> cacheList)
|
||||
/// <summary>
|
||||
/// 七天签到列表
|
||||
/// </summary>
|
||||
public List<SevenDayCache> SevenDayList
|
||||
{
|
||||
get
|
||||
{
|
||||
return cacheList.GetOrAdd(typeLock, _ =>
|
||||
return SevenDayEntityCache.DataList ?? new List<SevenDayCache>();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 兑换码
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private RedemptionCodeEntityCache redemptionCodeEntityCache;
|
||||
|
||||
/// <summary>
|
||||
/// 兑换码缓存
|
||||
/// </summary>
|
||||
public RedemptionCodeEntityCache RedemptionCodeEntityCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (redemptionCodeEntityCache == null)
|
||||
{
|
||||
Log($"没有找到锁对象 ==> {typeLock.Name}");
|
||||
return new object();
|
||||
});
|
||||
redemptionCodeEntityCache = new RedemptionCodeEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper);
|
||||
}
|
||||
return redemptionCodeEntityCache;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 兑换码列表
|
||||
/// </summary>
|
||||
public List<RedemptionCodeCache> RedemptionCodeList
|
||||
{
|
||||
get
|
||||
{
|
||||
return RedemptionCodeEntityCache.DataList ?? new List<RedemptionCodeCache>();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 首页缓存表
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 游戏缓存扩展
|
||||
/// </summary>
|
||||
public static class CloudGamingCacheExtend
|
||||
{
|
||||
private static readonly ConcurrentDictionary<Type, object> ExtCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||
private static readonly ConcurrentDictionary<Type, object> GameCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||
private static readonly ConcurrentDictionary<Type, object> AppCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||
private static readonly ConcurrentDictionary<Type, object> UserCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||
|
||||
/// <summary>
|
||||
/// 命名空间与缓存映射
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, (ConcurrentDictionary<Type, object> cacheList, AppDataBaseType dbType)> NamespaceMapping;
|
||||
|
||||
static CloudGamingCacheExtend()
|
||||
{
|
||||
NamespaceMapping = new Dictionary<string, (ConcurrentDictionary<Type, object> cacheList, AppDataBaseType dbType)>
|
||||
{
|
||||
{ "CloudGaming.GameModel.Db.Db_Ext", (ExtCacheLockList, AppDataBaseType.Ext) },
|
||||
{ "CloudGaming.GameModel.Db.Db_Game", (GameCacheLockList, AppDataBaseType.Game) },
|
||||
{ "CloudGaming.Model.DbSqlServer.Db_Phone", (AppCacheLockList, AppDataBaseType.App) },
|
||||
{ "CloudGaming.Model.DbSqlServer.Db_User", (UserCacheLockList, AppDataBaseType.User) }
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取实体缓存
|
||||
/// </summary>
|
||||
public static CommonDataEntityCache<T> GetDataEntityCache<T>(CloudGamingBase cloudGamingBase, Expression<Func<T, bool>>? expWhere = null, int cacheTime = 36000) where T : class
|
||||
{
|
||||
var typeLock = typeof(T);
|
||||
var namespaceKey = typeLock.Namespace;
|
||||
|
||||
if (namespaceKey == null || !NamespaceMapping.ContainsKey(namespaceKey))
|
||||
{
|
||||
throw new Exception($"缓存数据不存在或命名空间不匹配:{namespaceKey}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据数据库类型生成缓存配置
|
||||
/// </summary>
|
||||
public static CacheBaseConfig ToCacheBaseConfig(this CloudGamingBase cloudGamingBase, AppDataBaseType appDataBaseType)
|
||||
{
|
||||
return appDataBaseType switch
|
||||
{
|
||||
AppDataBaseType.App => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoPhone.Context },
|
||||
AppDataBaseType.User => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoUser.Context },
|
||||
AppDataBaseType.Ext => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoExt.Context },
|
||||
AppDataBaseType.Game => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoGame.Context },
|
||||
_ => throw new Exception("未找到对应的数据连接")
|
||||
};
|
||||
}
|
||||
var (cacheList, dbType) = NamespaceMapping[namespaceKey];
|
||||
object cacheLock = GetOrAddCacheLock(typeLock, cacheList);
|
||||
CacheBaseConfig cacheBaseConfig = cloudGamingBase.ToCacheBaseConfig(dbType);
|
||||
|
||||
/// <summary>
|
||||
/// 日志方法
|
||||
/// </summary>
|
||||
private static void Log(string message)
|
||||
return new DataBaseEntityCache<T>(cacheBaseConfig, cacheLock, expWhere: expWhere, cacheTime: cacheTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或添加缓存锁对象
|
||||
/// </summary>
|
||||
private static object GetOrAddCacheLock(Type typeLock, ConcurrentDictionary<Type, object> cacheList)
|
||||
{
|
||||
return cacheList.GetOrAdd(typeLock, _ =>
|
||||
{
|
||||
// 替换为其他日志记录系统,例如 NLog, Serilog 等
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
Log($"没有找到锁对象 ==> {typeLock.Name}");
|
||||
return new object();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据数据库类型生成缓存配置
|
||||
/// </summary>
|
||||
public static CacheBaseConfig ToCacheBaseConfig(this CloudGamingBase cloudGamingBase, AppDataBaseType appDataBaseType)
|
||||
{
|
||||
return appDataBaseType switch
|
||||
{
|
||||
AppDataBaseType.App => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoPhone.Context },
|
||||
AppDataBaseType.User => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoUser.Context },
|
||||
AppDataBaseType.Ext => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoExt.Context },
|
||||
AppDataBaseType.Game => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoGame.Context },
|
||||
_ => throw new Exception("未找到对应的数据连接")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志方法
|
||||
/// </summary>
|
||||
private static void Log(string message)
|
||||
{
|
||||
// 替换为其他日志记录系统,例如 NLog, Serilog 等
|
||||
//Console.WriteLine(message);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,213 +1,210 @@
|
|||
using AutoMapper;
|
||||
|
||||
using CloudGaming.Code.AppExtend;
|
||||
using CloudGaming.Code.DataAccess;
|
||||
using CloudGaming.DtoModel.Game;
|
||||
|
||||
using HuanMeng.DotNetCore.CacheHelper;
|
||||
using HuanMeng.DotNetCore.CacheHelper.Contract;
|
||||
using HuanMeng.DotNetCore.Redis;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using StackExchange.Redis;
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
namespace CloudGaming.Code.Cache.Special;
|
||||
|
||||
namespace CloudGaming.Code.Cache.Special
|
||||
/// <summary>
|
||||
/// 图片缓存表
|
||||
/// </summary>
|
||||
/// <param name="dao"></param>
|
||||
/// <param name="appConfig"></param>
|
||||
/// <param name="database"></param>
|
||||
/// <param name="mapper"></param>
|
||||
/// <param name="appRequestConfig"></param>
|
||||
public class ImageEntityCache(DAO dao, AppConfig appConfig, IDatabase database, AppRequestConfig appRequestConfig) : ICacheClearData, ICacheReloadData
|
||||
{
|
||||
/// <summary>
|
||||
/// 图片缓存表
|
||||
/// 是否加载过图片
|
||||
/// </summary>
|
||||
/// <param name="dao"></param>
|
||||
/// <param name="appConfig"></param>
|
||||
/// <param name="database"></param>
|
||||
/// <param name="mapper"></param>
|
||||
/// <param name="appRequestConfig"></param>
|
||||
public class ImageEntityCache(DAO dao, AppConfig appConfig, IDatabase database, AppRequestConfig appRequestConfig) : ICacheClearData, ICacheReloadData
|
||||
public static bool IsLoadImage { get; set; } = false;
|
||||
/// <summary>
|
||||
/// 本地内存图片缓存key
|
||||
/// </summary>
|
||||
private string key = $"{appConfig.Identifier}:App:Image";
|
||||
/// <summary>
|
||||
/// redis图片缓存key
|
||||
/// </summary>
|
||||
private string redisKey = $"App:Image";
|
||||
/// <summary>
|
||||
/// 当前使用的图片key
|
||||
/// </summary>
|
||||
ConcurrentDictionary<string, ConcurrentDictionary<int, string>>? ImageData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="language"></param>
|
||||
/// <returns></returns>
|
||||
public ConcurrentDictionary<int, string> this[string language]
|
||||
{
|
||||
public static bool IsLoadImage { get; set; } = false;
|
||||
private string key = $"{appConfig.Identifier}:App:Image";
|
||||
private string redisKey = $"App:Image";
|
||||
ConcurrentDictionary<string, ConcurrentDictionary<int, string>>? ImageData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="language"></param>
|
||||
/// <returns></returns>
|
||||
public ConcurrentDictionary<int, string> this[string language]
|
||||
get
|
||||
{
|
||||
get
|
||||
if (string.IsNullOrEmpty(language))
|
||||
{
|
||||
language = appRequestConfig.Language;
|
||||
}
|
||||
if (ImageData != null && ImageData.TryGetValue(language, out var images))
|
||||
{
|
||||
if (string.IsNullOrEmpty(language))
|
||||
{
|
||||
language = appRequestConfig.Language;
|
||||
}
|
||||
if (ImageData != null && ImageData.TryGetValue(language, out var images))
|
||||
{
|
||||
return images;
|
||||
}
|
||||
ImageData = MemoryCacheHelper.GetCache<ConcurrentDictionary<string, ConcurrentDictionary<int, string>>>(key);
|
||||
if (ImageData == null)
|
||||
{
|
||||
ImageData = new ConcurrentDictionary<string, ConcurrentDictionary<int, string>>();
|
||||
|
||||
}
|
||||
if (!ImageData.TryGetValue(language, out images))
|
||||
{
|
||||
ImageData.TryAdd(language, images = new ConcurrentDictionary<int, string>());
|
||||
MemoryCacheHelper.SetCache(key, ImageData, 60 * 60 * 24);
|
||||
}
|
||||
|
||||
return images;
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="language"></param>
|
||||
/// <param name="imageId"></param>
|
||||
/// <returns></returns>
|
||||
public string this[string language, int imageId]
|
||||
{
|
||||
get
|
||||
ImageData = MemoryCacheHelper.GetCache<ConcurrentDictionary<string, ConcurrentDictionary<int, string>>>(key);
|
||||
if (ImageData == null)
|
||||
{
|
||||
if (imageId == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var _imageData = this[language];
|
||||
if (_imageData == null)
|
||||
{
|
||||
_imageData = new ConcurrentDictionary<int, string>();
|
||||
}
|
||||
if (!_imageData.TryGetValue(imageId, out var imageUrl))
|
||||
{
|
||||
var imageValue = database.StringGet($"{redisKey}:{language}:{imageId}");
|
||||
if (imageValue.IsNullOrEmpty)
|
||||
{
|
||||
imageValue = database.StringGet($"{redisKey}:default:{imageId}");
|
||||
}
|
||||
if (!IsLoadImage && imageValue.IsNullOrEmpty)
|
||||
{
|
||||
if (!database.KeyExists(redisKey))
|
||||
{
|
||||
ImageData = LoadImage(dao, appConfig);
|
||||
MemoryCacheHelper.SetCache(key, ImageData, 60 * 60 * 24);
|
||||
IsLoadImage = true;
|
||||
_imageData = ImageData[language];
|
||||
if (!_imageData.TryGetValue(imageId, out imageUrl))
|
||||
{
|
||||
imageUrl = "";
|
||||
}
|
||||
return imageUrl;
|
||||
}
|
||||
}
|
||||
imageUrl = imageValue;
|
||||
_imageData.TryAdd(imageId, imageUrl);
|
||||
//if (!_imageData.TryGetValue(imageId, out imageUrl))
|
||||
//{
|
||||
// if (string.IsNullOrEmpty(imageUrl))
|
||||
// {
|
||||
// imageUrl = "";
|
||||
// }
|
||||
ImageData = new ConcurrentDictionary<string, ConcurrentDictionary<int, string>>();
|
||||
|
||||
//}//imageValue.ToString();
|
||||
|
||||
//MemoryCacheHelper.SetCache(key, ImageData, 60 * 60 * 24);
|
||||
|
||||
}
|
||||
return imageUrl;
|
||||
}
|
||||
}
|
||||
|
||||
public ConcurrentDictionary<string, ConcurrentDictionary<int, string>> LoadImage(DAO dao, AppConfig appConfig)
|
||||
{
|
||||
// 初始化_data字典
|
||||
ConcurrentDictionary<string, ConcurrentDictionary<int, string>> _data = new ConcurrentDictionary<string, ConcurrentDictionary<int, string>>();
|
||||
|
||||
// 获取图像列表
|
||||
var imageList = dao.DaoExt.Context.T_App_Image
|
||||
.Where(it => !string.IsNullOrEmpty(it.Url))
|
||||
.AsNoTracking()
|
||||
.Select(it => new { it.ImageId, it.Language, it.Url })
|
||||
.ToList();
|
||||
|
||||
// 设置默认语言
|
||||
if (string.IsNullOrEmpty(appConfig.DefaultLanguage))
|
||||
if (!ImageData.TryGetValue(language, out images))
|
||||
{
|
||||
appConfig.DefaultLanguage = "zh";
|
||||
ImageData.TryAdd(language, images = new ConcurrentDictionary<int, string>());
|
||||
//内存中缓存
|
||||
MemoryCacheHelper.SetCache(key, ImageData, 60 * 60 * 24);
|
||||
}
|
||||
|
||||
// 创建默认语言的图像字典
|
||||
var defaultImage = imageList
|
||||
.Where(it => it.Language == appConfig.DefaultLanguage)
|
||||
.GroupBy(it => it.ImageId)
|
||||
.ToDictionary(group => group.Key, group => appConfig.AliyunConfig.ImagePrefix + group.Last().Url);
|
||||
|
||||
// 遍历图像列表,填充_data字典
|
||||
foreach (var item in imageList)
|
||||
{
|
||||
// 尝试获取语言字典,如果不存在则创建
|
||||
if (!_data.TryGetValue(item.Language, out var languageImage))
|
||||
{
|
||||
languageImage = new ConcurrentDictionary<int, string>();
|
||||
_data[item.Language] = languageImage;
|
||||
}
|
||||
|
||||
// 设置图像URL
|
||||
languageImage[item.ImageId] = appConfig.AliyunConfig.ImagePrefix + item.Url;
|
||||
|
||||
// 如果默认图像字典中没有此ImageId,加入默认图像字典
|
||||
if (!defaultImage.ContainsKey(item.ImageId))
|
||||
{
|
||||
defaultImage[item.ImageId] = appConfig.AliyunConfig.ImagePrefix + item.Url;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新默认语言的图像字典
|
||||
_data["default"] = new ConcurrentDictionary<int, string>(defaultImage);
|
||||
foreach (var item in _data.Keys)
|
||||
{
|
||||
foreach (var image in _data[item])
|
||||
{
|
||||
string _redisKey = $"{redisKey}:{item}:{image.Key}";
|
||||
database.StringSet(_redisKey, image.Value, TimeSpan.FromDays(1));
|
||||
}
|
||||
}
|
||||
database.StringSet(redisKey, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromDays(1));
|
||||
return _data;
|
||||
}
|
||||
|
||||
public string this[int imageId]
|
||||
{
|
||||
get
|
||||
{
|
||||
var imageUrl = this[appRequestConfig.Language, imageId];
|
||||
return imageUrl;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ClearData()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void ReloadData()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return images;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="language"></param>
|
||||
/// <param name="imageId"></param>
|
||||
/// <returns></returns>
|
||||
public string this[string language, int imageId]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (imageId == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var _imageData = this[language];
|
||||
if (_imageData == null)
|
||||
{
|
||||
_imageData = new ConcurrentDictionary<int, string>();
|
||||
}
|
||||
if (!_imageData.TryGetValue(imageId, out var imageUrl))
|
||||
{
|
||||
var imageValue = database.StringGet($"{redisKey}:{language}:{imageId}");
|
||||
if (imageValue.IsNullOrEmpty)
|
||||
{
|
||||
imageValue = database.StringGet($"{redisKey}:default:{imageId}");
|
||||
}
|
||||
if (!IsLoadImage && imageValue.IsNullOrEmpty)
|
||||
{
|
||||
if (!database.KeyExists(redisKey))
|
||||
{
|
||||
ImageData = LoadImage(dao, appConfig);
|
||||
MemoryCacheHelper.SetCache(key, ImageData, 60 * 60 * 24);
|
||||
IsLoadImage = true;
|
||||
_imageData = ImageData[language];
|
||||
if (!_imageData.TryGetValue(imageId, out imageUrl))
|
||||
{
|
||||
imageUrl = "";
|
||||
}
|
||||
return imageUrl;
|
||||
}
|
||||
}
|
||||
imageUrl = imageValue;
|
||||
_imageData.TryAdd(imageId, imageUrl);
|
||||
}
|
||||
return imageUrl;
|
||||
}
|
||||
}
|
||||
|
||||
public ConcurrentDictionary<string, ConcurrentDictionary<int, string>> LoadImage(DAO dao, AppConfig appConfig)
|
||||
{
|
||||
// 初始化_data字典
|
||||
ConcurrentDictionary<string, ConcurrentDictionary<int, string>> _data = new ConcurrentDictionary<string, ConcurrentDictionary<int, string>>();
|
||||
|
||||
// 获取图像列表
|
||||
var imageList = dao.DaoExt.Context.T_App_Image
|
||||
.Where(it => !string.IsNullOrEmpty(it.Url))
|
||||
.AsNoTracking()
|
||||
.Select(it => new { it.ImageId, it.Language, it.Url })
|
||||
.ToList();
|
||||
|
||||
// 设置默认语言
|
||||
if (string.IsNullOrEmpty(appConfig.DefaultLanguage))
|
||||
{
|
||||
appConfig.DefaultLanguage = "zh";
|
||||
}
|
||||
|
||||
// 创建默认语言的图像字典
|
||||
var defaultImage = imageList
|
||||
.Where(it => it.Language == appConfig.DefaultLanguage)
|
||||
.GroupBy(it => it.ImageId)
|
||||
.ToDictionary(group => group.Key, group => appConfig.AliyunConfig.ImagePrefix + group.Last().Url);
|
||||
|
||||
// 遍历图像列表,填充_data字典
|
||||
foreach (var item in imageList)
|
||||
{
|
||||
// 尝试获取语言字典,如果不存在则创建
|
||||
if (!_data.TryGetValue(item.Language, out var languageImage))
|
||||
{
|
||||
languageImage = new ConcurrentDictionary<int, string>();
|
||||
_data[item.Language] = languageImage;
|
||||
}
|
||||
|
||||
// 设置图像URL
|
||||
languageImage[item.ImageId] = appConfig.AliyunConfig.ImagePrefix + item.Url;
|
||||
|
||||
// 如果默认图像字典中没有此ImageId,加入默认图像字典
|
||||
if (!defaultImage.ContainsKey(item.ImageId))
|
||||
{
|
||||
defaultImage[item.ImageId] = appConfig.AliyunConfig.ImagePrefix + item.Url;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新默认语言的图像字典
|
||||
_data["default"] = new ConcurrentDictionary<int, string>(defaultImage);
|
||||
foreach (var item in _data.Keys)
|
||||
{
|
||||
foreach (var image in _data[item])
|
||||
{
|
||||
string _redisKey = $"{redisKey}:{item}:{image.Key}";
|
||||
database.StringSet(_redisKey, image.Value, TimeSpan.FromDays(1));
|
||||
}
|
||||
}
|
||||
database.StringSet(redisKey, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromDays(1));
|
||||
return _data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取图片
|
||||
/// </summary>
|
||||
/// <param name="imageId"></param>
|
||||
/// <returns></returns>
|
||||
public string this[int imageId]
|
||||
{
|
||||
get
|
||||
{
|
||||
var imageUrl = this[appRequestConfig.Language, imageId];
|
||||
return imageUrl;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除缓存
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public bool ClearData()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重新加载缓存
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public void ReloadData()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user