namespace Admin.NET.Core; /// /// 镜像写入方在范围内更新带外源标记的主数据。页面保存不进入该范围,因此会被只读守卫拒绝。 /// public static class MdmMirrorWriteScope { private static readonly AsyncLocal Depth = new(); public static bool IsWriter => Depth.Value > 0; /// /// 页面更新或删除 S0 行时,外源行(source_system 非空且不是 AIDOP_NATIVE)拒绝。 /// 只认 Entity.S0 命名空间,避免中立层实体上的同名列被误拦。 /// public static void RejectPageWrite(object? entity) { if (entity == null || IsWriter) return; var type = entity.GetType(); var ns = type.Namespace ?? string.Empty; if (ns.IndexOf(".Entity.S0", StringComparison.Ordinal) < 0) return; var value = type.GetProperty("SourceSystem")?.GetValue(entity) as string; if (string.IsNullOrWhiteSpace(value)) return; if (string.Equals(value, "AIDOP_NATIVE", StringComparison.OrdinalIgnoreCase)) return; throw new InvalidOperationException($"该记录来自 {value},只读"); } public static IDisposable Enter() { Depth.Value++; return new Popper(); } private sealed class Popper : IDisposable { public void Dispose() { if (Depth.Value > 0) Depth.Value--; } } }