向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
相关产品推荐
相关产品推荐

