using System.Linq.Expressions; using YLErp.Abstract; namespace YLErp.Modules.DataCacheModule { /// /// 通用数据源抽象类 /// abstract class GenericeCachedDataSource : IDataUpdater, IDataSource, IDataSource, IDataSourceEvent, IJsonSerializable where TData : class, IDataTraceV2, IDataEntity { protected int _maxId = -1; protected bool _clonable; protected readonly Dictionary _dic; protected DateTime _lastUptime; public event EventHandler DataSourceUpdated; protected GenericeCachedDataSource() { _dic = new Dictionary(); _clonable = typeof(TData).GetInterface(typeof(IClonable).Name) != null; } /// /// 数据条数 /// public int Count => _dic.Count; public abstract string TableName { get; } /// /// 获取数据 /// public IQueryable AsQueryable(Expression> predicate = null) { lock (this) { if (_dic.Count < 1) { return Enumerable.Empty().AsQueryable(); } var query = _dic.Values.AsQueryable(); if (predicate != null) { query = query.Where(predicate); } if (_clonable) { return new DataCacheQueryable(query); } return query; } } /// /// 更新数据源 /// public virtual void UpdateData(IEnumerable updateKeyIds) { lock (_dic) { InnerUpdateData(updateKeyIds); } } private void InnerUpdateData(IEnumerable updateKeyIds) { using (var db = CreateDbContext()) { var table = db.Set().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); } } /// /// 根据KeyID获取数据 /// public virtual TData GetData(int keyId) { if (keyId < 1) { return null; } lock (this) { if (_dic.TryGetValue(keyId, out TData data)) { return _clonable ? ((IClonable)data).Clone() : data; } using (var db = CreateDbContext()) { var dbModel = db.Set().AsNoTracking().FirstOrDefault(n => n.id == keyId); if (dbModel != null) { _dic[dbModel.id] = dbModel; AfterUpdate?.Invoke(dbModel); return _clonable ? ((IClonable)dbModel).Clone() : dbModel; } return dbModel; } } } /// /// 重置数据源 /// public virtual void ResetDataSource() { _maxId = -1; _dic.Clear(); } //--------用于扩展配置------------------ /// /// 数据加载后预处理 /// protected virtual TData[] PreProcessDatas(TData[] datas) { return datas; } /// /// 查询过滤条件 /// public Expression> Filter { get; set; } /// /// 更新以后事件处理 /// public Action AfterUpdate { get; set; } /// /// 删除以后事件处理 /// public Action AfterRemove { get; set; } /// /// 创建数据库上下文(默认使用YLContext) /// protected virtual DbContext CreateDbContext() { return DbContextFactory.GetYLDbContext(); } public string ToJson() { return new { _maxId, _lastUptime, _dic }.ToJson(); } } }