如何在Cosmos DB中处理实体变更实现软删除,兼容无DeletedAt旧数据?
方案1:调整查询逻辑,无需修改现有数据
这是成本最低的临时适配方案,只需要修改泛型仓储的查询条件,兼容无DeletedAt属性的旧文档即可:
把原查询代码:
return await Queryable.Where(x => x.DeletedAt == null).Where(predicate).ToListAsync();
修改为同时匹配「无DeletedAt属性」或「DeletedAt值为null」的文档:
return await Queryable .Where(x => x.DeletedAt == null || !EF.IsPropertyDefined(x, nameof(Entity.DeletedAt))) .Where(predicate) .ToListAsync();
如果使用的EF Core版本低于7.0不支持EF.IsPropertyDefined,也可以用Cosmos DB LINQ提供器原生的扩展方法:
using Microsoft.Azure.Cosmos.Linq; // 查询条件改为 .Where(x => x.DeletedAt == null || !CosmosLinqExtensions.IsDefined(x.DeletedAt))
该逻辑完全贴合Cosmos DB的查询规则,旧文档不会再被过滤,新写入的带DeletedAt属性的文档也能正常走软删除逻辑。
方案2:批量补全旧文档属性,一劳永逸
如果不想长期维护特殊的查询条件,可以一次性给所有缺失DeletedAt属性的旧文档补值,后续就可以继续用原来的查询逻辑:
- 可以直接在Azure门户的Cosmos DB数据资源管理器中执行JavaScript批量更新脚本,无需额外开发处理程序
- 也可以写一次性的处理程序,用Cosmos DB SDK执行带过滤的查询,匹配所有没有
DeletedAt属性的文档,新增DeletedAt = null的属性后批量更新 - 几千条数据的处理量很小,用批量操作或者存储过程几分钟就能完成,不会影响线上业务
原理说明
你遇到的问题是Cosmos DB的无模式特性导致的:关系型数据库中只要表结构加了可空列,所有旧行默认会填充null值;但Cosmos DB的文档查询中,DeletedAt == null只会命中明确存在该属性且值为null的文档,完全没有该属性的文档不会被匹配到,所以才会出现旧数据全部被过滤的情况。
内容的提问来源于stack exchange,提问作者aevitas
相关产品推荐
相关产品推荐

