【问题标题】:Why redis with protobuf is saving empty arrays as null?为什么带有protobuf的redis将空数组保存为null?
【发布时间】:2020-02-17 07:45:45
【问题描述】:

我正在使用 protobuf-net 2.3.3 在 redis 服务器 2.8.2103 上维护一个应用程序> 使用 StackExchange.Redis 1.2.6

对于像这样的对象:

[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class Cachable { Foo[] Foos { get; set; } }

当我使用简单的保存时:

using (var memoryStream = new MemoryStream())
{
    Serializer.Serialize(memoryStream, cachable);
    database.HashSetAsync("category", "key", memoryStream.ToArray());
}

然后检索:

var response = database.HashGet("category", "key");
if (!response.HasValue) return null;
using (var memoryStream = new MemoryStream(response, false))
{
    return Serializer.Deserialize<Cachable>(memoryStream);
}

如果缓存数组Foos 有一个空实例,如new Foo[0],一旦Cachable 被反序列化,数组就变成null。 这会改变应用程序某些部分的行为并产生错误。
这种行为是预期的吗?有什么办法可以改吗?

【问题讨论】:

    标签: c# redis protobuf-net stackexchange.redis


    【解决方案1】:

    这里真正的问题是Foo[0]null 吗?如果是这样:

    • protobuf 没有null的概念;它不能表示和存储 null,因此默认情况下,protobuf-net skips null 值,这 本质上 是一个空数组
    • 带有“空包装原语”的轻微警告,protobuf 没有“空”序列的概念;在 .proto 术语中,您正在谈论一个具有零元素的 repeated 字段,这意味着:它根本不存在于有效负载中根本
    • 如果它不存在于有效负载中,则永远不会反序列化任何东西 - 因为有效负载中永远不会有任何东西告诉它反序列化李>

    所以:

    • 避免使用null,除非您指的是可选子元素;绝对避免在列表/数组/等中使用null
    • 不要假设空列表/数组/等会被库初始化为非空值

    IMO,对于第二点,以下是合理和务实的:

    Foo[] Foos { get; set; } = Array.Empty<Foo>();
    

    (避免了初始化为null的问题)

    【讨论】:

      猜你喜欢
      • 2021-09-15
      • 2017-03-11
      • 1970-01-01
      • 2013-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多