将 CodeFirst 的 属性 保存到 EFCore 中的 Base64 字符串,但从 EFCore 读回 X509Certificate2?

Save CodeFirst's property to Base64 string in EFCore but read back X509Certificate2 from EFCore?

ThirdParty 模型包含 属性 Certificate。它是供源代码使用的 X509Certificate2 数据类型,但 EFCore 不支持它,这意味着我必须将其转换为 Base64 string 以便 EFCore 数据库存储。然后在从 EFCore 数据库读取时将其转换回 X509Certificate2

我们如何指示 EFCore 使用任何 属性 映射器自动执行此操作?

public class ThirdParty
{
   public Guid ThirdPartyId { get; set; }
   public X509Certificate2 Certificate { get; set; }
   public string RawData { get; set; }
   public DateTime CreatedDate { get; set; }
}

var certificate1 = new X509Certificate();
var thirdParty = new ThirdParty() { Certificate = certificate }
var certificate2 = thirdParty.Certificate;

一种方法是添加一个额外的未映射属性,它将return X509Certificate2 对象创建从数据库中读取的 Base64 string。 因此 CertificateString 属性 仅用于保存和读取数据上下文,而 Certificate 属性 用于您的其他逻辑。

public class ThirdParty
{
    private X509Certificate2 _certificate;



    public Guid ThirdPartyId { get; set; }

    // to write in data context only - only set it in production code
    public string CertificateString 
    {
        get
        {
            // return the Base64 string - is just pseudo code
            return _certificate?.ToString();
        }    
        set
        {
            _certificate = new X509Certificate2(value);
        }
    }

    // not mapped for data context - to read from data context only - only read fro
    public X509Certificate2 Certificate
    {
        get
        {
            if (string.IsNullOrWhiteSpace(CertificateString))
            {
                return default(X509Certificate2);
            }

            return new X509Certificate2(CertificateString);
        }    
        private set
        {
            // will be set by CertificateString
        }
    }

    public string RawData { get; set; }

    public DateTime CreatedDate { get; set; }
}

要不映射 属性,您可以在 Fluent API.

中使用 [NotMapped] 作为数据注释或 .Ignore(p => p.PropertyName)

我会做这样的事情,如果您在序列化证书时遇到问题,可以查看 Why does Json.NET fail to serialize a X509Certificate2?

public class Configuration : IEntityTypeConfiguration<ThirdParty>
{
    public void Configure(EntityTypeBuilder<ThirdParty> builder)
    {
        // This Converter will perform the conversion to and from Json to the desired type
        builder.Property(e => e.Certificate).HasConversion(
            v => JsonConvert.SerializeObject(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }),
            v => JsonConvert.DeserializeObject<X509Certificate2>(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }));
    }
}