You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置OData中的Delta<TEntity>以修改其UpdatableProperties属性?

OData Patch调用前过滤Delta不可更新属性的实现方案

以下是三种常用的落地实现方案,可根据自身业务场景选择:

方案1:自定义ActionFilter全局拦截处理

适合需要批量处理所有Patch接口的场景,无需侵入业务代码:

public class DeltaReservedPropertiesFilter : IActionFilter
{
    // 复用你定义的禁止更新字段列表
    private readonly List<string> _reservedProperties = new List<string>() { "ObjectId", "IsDeleted", "DeleterUserId", "DeletionTime", "LastModificationTime", "LastModifierUserId", "CreationTime", "CreatorUserId", "CreatorUser", "TenantId" };

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // 仅处理Patch请求
        if (context.HttpContext.Request.Method != HttpMethod.Patch.Method) return;

        // 匹配参数中的Delta对象
        var deltaParam = context.ActionArguments.FirstOrDefault(arg => arg.Value?.GetType().IsGenericType == true 
            && arg.Value.GetType().GetGenericTypeDefinition() == typeof(Delta<>));
        if (deltaParam.Value == null) return;

        // 反射获取UpdatableProperties集合并移除保留字段
        var updatableProps = deltaParam.Value.GetType().GetProperty("UpdatableProperties")?.GetValue(deltaParam.Value) as ICollection<string>;
        if (updatableProps == null) return;
        foreach (var prop in _reservedProperties)
        {
            updatableProps.Remove(prop);
        }
    }

    public void OnActionExecuted(ActionExecutedContext context) {}
}

在Program.cs中注册Filter即可全局生效:

builder.Services.AddControllers(options =>
{
    options.Filters.Add<DeltaReservedPropertiesFilter>();
});

方案2:封装Delta扩展方法按需调用

适合仅部分接口需要做字段过滤的场景,灵活性更高:

public static class DeltaExtensions
{
    private static readonly List<string> ReservedPropertiesName = new List<string>() { "ObjectId", "IsDeleted", "DeleterUserId", "DeletionTime", "LastModificationTime", "LastModifierUserId", "CreationTime", "CreatorUserId", "CreatorUser", "TenantId" };

    public static void RemoveReservedProperties<T>(this Delta<T> delta) where T : class
    {
        // 移除禁止更新的属性配置
        foreach (var prop in ReservedPropertiesName)
        {
            delta.UpdatableProperties.Remove(prop);
        }
        // 清理客户端已经提交的保留字段值,避免误写入
        var changedProps = delta.GetChangedPropertyNames().ToList();
        foreach (var prop in changedProps.Intersect(ReservedPropertiesName))
        {
            delta.TryUnsetPropertyValue(prop);
        }
    }
}

在Patch方法开头直接调用即可:

public IActionResult Patch([FromODataUri] int key, Delta<MyEntity> delta)
{
    delta.RemoveReservedProperties();
    // 后续原有业务逻辑
}

方案3:基于特性自动识别不可更新字段

避免硬编码属性名,可直接在模型上标记禁止更新的属性:
首先定义标记特性:

[AttributeUsage(AttributeTargets.Property)]
public class NonUpdatableAttribute : Attribute
{
}

在实体模型上标记禁止更新的字段:

public class MyEntity
{
    [NonUpdatable]
    public string ObjectId { get; set; }
    [NonUpdatable]
    public bool IsDeleted { get; set; }
    // 其他字段...
}

在过滤逻辑中动态收集需要移除的字段:

var nonUpdatableProps = typeof(T).GetProperties()
    .Where(p => p.GetCustomAttribute<NonUpdatableAttribute>() != null)
    .Select(p => p.Name)
    .ToList();
// 后续执行移除操作即可

注意事项

  • 移除UpdatableProperties中的字段后,Delta后续执行Patch、TrySetPropertyValue等操作时都会自动忽略这些字段,不会修改实体对应的值
  • 如果需要支持不同角色的可更新字段差异,可以在过滤逻辑中加入当前用户的权限校验,动态生成需要移除的属性列表
  • 建议同时添加已提交保留字段的清理逻辑,避免客户端提交的非法值被误写入数据库

内容的提问来源于stack exchange,提问作者Gaby Jawhar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 12:54:04