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

向Redis添加AppSlider实体时出现自引用循环序列化错误

解决Redis缓存序列化AppSlider实体时的循环引用问题

问题原因

你在Startup.cs中配置的ReferenceLoopHandling.Ignore仅作用于MVC控制器的请求/响应JSON序列化,而Redis缓存客户端使用的是独立的JSON序列化配置,不会自动继承MVC的设置,因此依然会触发循环引用错误。

解决方案

1. 配置Redis缓存客户端的JSON序列化设置

根据你使用的Redis客户端库,单独配置其Newtonsoft.Json序列化器的循环引用处理规则:

示例:使用StackExchange.Redis.Extensions.Newtonsoft

在注册Redis服务时,指定序列化器的设置:

services.AddStackExchangeRedisExtensions<NewtonsoftSerializer>(options =>
{
    options.Configuration = "你的Redis连接字符串";
    options.InstanceName = "你的实例名称";
}, serializerSettings =>
{
    // 添加循环引用忽略配置
    serializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
    // 可添加其他序列化配置,如日期格式、空值处理等
});

示例:自定义IDistributedCache序列化器

如果使用ASP.NET Core内置的IDistributedCache,可以自定义基于Newtonsoft.Json的序列化器:

// 注册自定义序列化器
services.AddSingleton<IDistributedCacheSerializer, NewtonsoftJsonCacheSerializer>();

// 自定义序列化器实现
public class NewtonsoftJsonCacheSerializer : IDistributedCacheSerializer
{
    private readonly JsonSerializerSettings _serializerSettings;

    public NewtonsoftJsonCacheSerializer()
    {
        _serializerSettings = new JsonSerializerSettings
        {
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            // 按需添加其他配置
            DateFormatString = "yyyy-MM-dd HH:mm:ss",
            NullValueHandling = NullValueHandling.Ignore
        };
    }

    public byte[] Serialize<T>(T item)
    {
        var json = JsonConvert.SerializeObject(item, _serializerSettings);
        return Encoding.UTF8.GetBytes(json);
    }

    public T Deserialize<T>(byte[] bytes)
    {
        var json = Encoding.UTF8.GetString(bytes);
        return JsonConvert.DeserializeObject<T>(json, _serializerSettings);
    }
}

2. 使用DTO替代实体直接序列化

创建仅包含缓存所需字段的DTO类,避免携带关联实体,从根源上消除循环引用:

// 定义AppSlider的缓存DTO
public class AppSliderCacheDto
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string ImageUrl { get; set; }
    // 仅保留需要缓存的属性,不包含Action等关联对象
}

// 保存缓存时,将实体映射为DTO
var sliderDto = new AppSliderCacheDto
{
    Id = appSlider.Id,
    Title = appSlider.Title,
    ImageUrl = appSlider.ImageUrl
};
await _redisCacheClient.Db1.AddAsync<AppSliderCacheDto>(cacheKey, sliderDto);

3. 在实体类上标记忽略循环引用属性

通过[JsonIgnore]特性,直接忽略导致循环的关联属性,序列化时会自动跳过这些属性:

public class AppSlider
{
    public int Id { get; set; }
    public string Title { get; set; }

    // 标记忽略Action属性,避免序列化时触发循环
    [JsonIgnore]
    public Action Action { get; set; }
}

// 或者在Action类中忽略AppSliders集合
public class Action
{
    public int Id { get; set; }
    public string Name { get; set; }

    [JsonIgnore]
    public ICollection<AppSlider> AppSliders { get; set; }
}

内容的提问来源于stack exchange,提问作者Robabeh Ghasemi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 04:05:18