从山证v2.3.0拷贝
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
using System.Linq.Expressions;
|
||||
using YLErp.Abstract;
|
||||
|
||||
namespace YLErp.Modules.DataCacheModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 通用数据源抽象类
|
||||
/// </summary>
|
||||
abstract class GenericeCachedDataSource<TData> : IDataUpdater, IDataSource, IDataSource<TData>, IDataSourceEvent, IJsonSerializable
|
||||
where TData : class, IDataTraceV2, IDataEntity
|
||||
{
|
||||
protected int _maxId = -1;
|
||||
protected bool _clonable;
|
||||
protected readonly Dictionary<int, TData> _dic;
|
||||
protected DateTime _lastUptime;
|
||||
|
||||
public event EventHandler DataSourceUpdated;
|
||||
|
||||
protected GenericeCachedDataSource()
|
||||
{
|
||||
_dic = new Dictionary<int, TData>();
|
||||
_clonable = typeof(TData).GetInterface(typeof(IClonable<TData>).Name) != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据条数
|
||||
/// </summary>
|
||||
public int Count => _dic.Count;
|
||||
|
||||
public abstract string TableName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据
|
||||
/// </summary>
|
||||
public IQueryable<TData> AsQueryable(Expression<Func<TData, bool>> predicate = null)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (_dic.Count < 1)
|
||||
{
|
||||
return Enumerable.Empty<TData>().AsQueryable();
|
||||
}
|
||||
|
||||
var query = _dic.Values.AsQueryable();
|
||||
|
||||
if (predicate != null)
|
||||
{
|
||||
query = query.Where(predicate);
|
||||
}
|
||||
|
||||
if (_clonable)
|
||||
{
|
||||
return new DataCacheQueryable<TData>(query);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新数据源
|
||||
/// </summary>
|
||||
public virtual void UpdateData(IEnumerable<string> updateKeyIds)
|
||||
{
|
||||
lock (_dic)
|
||||
{
|
||||
InnerUpdateData(updateKeyIds);
|
||||
}
|
||||
}
|
||||
|
||||
private void InnerUpdateData(IEnumerable<string> updateKeyIds)
|
||||
{
|
||||
using (var db = CreateDbContext())
|
||||
{
|
||||
var table = db.Set<TData>().AsNoTracking();
|
||||
|
||||
var minId = _maxId;
|
||||
var maxId = table.Max(n => (int?)n.id) ?? 0;
|
||||
|
||||
//ID更新集合
|
||||
var updateIds = DataConvert.ConvertToInt32Set(updateKeyIds);
|
||||
|
||||
if (maxId < minId)
|
||||
{
|
||||
minId = -1;
|
||||
}
|
||||
|
||||
if (maxId == minId && !updateIds.Any(n => n > 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_lastUptime = DateTime.Now;
|
||||
|
||||
//数据查询
|
||||
var query = table.Where(n => (n.id > minId && n.id <= maxId) || updateIds.Contains(n.id));
|
||||
if (Filter != null)
|
||||
{
|
||||
query = query.Where(Filter);
|
||||
}
|
||||
var datas = query.OrderBy(n => n.id).ToArray();
|
||||
|
||||
datas = PreProcessDatas(datas);
|
||||
|
||||
lock (this)
|
||||
{
|
||||
//更新字典数据
|
||||
foreach (var data in datas)
|
||||
{
|
||||
updateIds.Remove(data.id);
|
||||
_dic[data.id] = data;
|
||||
AfterUpdate?.Invoke(data);
|
||||
}
|
||||
|
||||
//取不到数据的直接从本地字典中删除
|
||||
updateIds.Remove(0);
|
||||
foreach (var id in updateIds)
|
||||
{
|
||||
if (AfterRemove != null && _dic.TryGetValue(id, out var data))
|
||||
{
|
||||
AfterRemove(data);
|
||||
}
|
||||
_dic.Remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
_maxId = maxId;
|
||||
|
||||
DataSourceUpdated?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据KeyID获取数据
|
||||
/// </summary>
|
||||
public virtual TData GetData(int keyId)
|
||||
{
|
||||
if (keyId < 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
lock (this)
|
||||
{
|
||||
if (_dic.TryGetValue(keyId, out TData data))
|
||||
{
|
||||
return _clonable ? ((IClonable<TData>)data).Clone() : data;
|
||||
}
|
||||
|
||||
using (var db = CreateDbContext())
|
||||
{
|
||||
var dbModel = db.Set<TData>().AsNoTracking().FirstOrDefault(n => n.id == keyId);
|
||||
if (dbModel != null)
|
||||
{
|
||||
_dic[dbModel.id] = dbModel;
|
||||
AfterUpdate?.Invoke(dbModel);
|
||||
return _clonable ? ((IClonable<TData>)dbModel).Clone() : dbModel;
|
||||
}
|
||||
return dbModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置数据源
|
||||
/// </summary>
|
||||
public virtual void ResetDataSource()
|
||||
{
|
||||
_maxId = -1;
|
||||
_dic.Clear();
|
||||
}
|
||||
|
||||
//--------用于扩展配置------------------
|
||||
|
||||
/// <summary>
|
||||
/// 数据加载后预处理
|
||||
/// </summary>
|
||||
protected virtual TData[] PreProcessDatas(TData[] datas)
|
||||
{
|
||||
return datas;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询过滤条件
|
||||
/// </summary>
|
||||
public Expression<Func<TData, bool>> Filter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新以后事件处理
|
||||
/// </summary>
|
||||
public Action<TData> AfterUpdate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 删除以后事件处理
|
||||
/// </summary>
|
||||
public Action<TData> AfterRemove { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建数据库上下文(默认使用YLContext)
|
||||
/// </summary>
|
||||
protected virtual DbContext CreateDbContext()
|
||||
{
|
||||
return DbContextFactory.GetYLDbContext();
|
||||
}
|
||||
|
||||
public string ToJson()
|
||||
{
|
||||
return new { _maxId, _lastUptime, _dic }.ToJson();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user