数据库更新后重载父ReadOnlyBase对象中的子BusinessListBase对象
强制刷新CSLA只读对象子对象的实现方案
1. 核心思路
你的只读对象(A、B)是内存缓存的,当外部微服务直接修改数据库中C的数据后,可通过缓存失效+重新加载或局部刷新子对象两种方式同步数据,结合已有的通知服务,在收到变更通知时执行对应逻辑即可。
2. 方案一:全量清除缓存,下次请求自动加载最新数据
CSLA的ReadOnlyBase默认支持数据门户缓存,你可以通过DataPortal.ClearCache方法清除指定对象的缓存,下次请求该对象时,会重新从数据库拉取包含最新C数据的完整对象。
实现代码
// 通知服务的消息处理方法 public void HandleDatabaseChange(int targetAId) { // 清除A对象的缓存,参数为对象类型和Fetch时用的标识(比如A的ID) Csla.DataPortal.ClearCache(typeof(A), new object[] { targetAId }); // 如果只需要刷新特定B对象,可单独清除B的缓存 // Csla.DataPortal.ClearCache(typeof(B), new object[] { targetBId }); }
这种方式简单直接,无需修改原有业务类,适合不需要实时刷新、允许下次请求同步数据的场景。
3. 方案二:局部刷新子对象(实时更新缓存中的对象)
如果需要实时更新缓存中的对象,不用等下次请求,可以在只读对象中添加内部刷新方法,直接更新子对象集合。
修改业务类代码
// 修改B类,添加刷新CList的方法 public class B : ReadOnlyBase<B> { public int Id { get; private set; } public CList Cs { get; private set; } // 原有数据加载逻辑 private void DataPortal_Fetch(int id) { Id = id; // 从数据库加载对应CList Cs = DataPortal.Fetch<CList>(id); } // 内部刷新方法,供通知处理逻辑调用 internal void RefreshCs() { // 重新从数据库拉取最新的CList并替换原有属性 Cs = DataPortal.Fetch<CList>(Id); // 触发属性变更通知(适配UI绑定或属性监听场景) PropertyHasChanged(nameof(Cs)); } } // CList的加载逻辑补充 public class CList : BusinessListBase<CList, C> { private void DataPortal_Fetch(int bId) { // 从数据库查询属于当前B的所有C数据 using (var db = new YourDbContext()) { var cDataList = db.Cs.Where(c => c.BId == bId).ToList(); foreach (var c in cDataList) { Add(c); } } } }
通知处理逻辑
public class DatabaseChangeNotificationHandler { // 假设通知消息包含关联的B的ID public void HandleCChanged(int relatedBId) { // 从缓存中获取已加载的B对象(自定义内存缓存需自行实现获取逻辑) var cachedB = Csla.ApplicationContext.LocalContext.Get<B>($"B_{relatedBId}"); if (cachedB != null) { // 加锁保证线程安全,避免并发修改缓存对象 lock (cachedB) { cachedB.RefreshCs(); } } // 同时清除缓存,防止后续请求拿到旧数据 Csla.DataPortal.ClearCache(typeof(B), new object[] { relatedBId }); } }
4. 注意事项
- 线程安全:缓存对象可能被多个请求同时访问,刷新时必须加锁,避免并发修改导致的数据异常
- 缓存策略一致性:确保CSLA的缓存配置(如缓存键、过期时间)和通知触发的失效逻辑对齐,避免出现缓存不一致
- 只读对象设计规范:CSLA只读对象建议保持不可变性,局部刷新时应直接替换子对象(如CList),不要修改子对象内部的属性值
内容的提问来源于stack exchange,提问作者user1890098
相关产品推荐
相关产品推荐

