使用 entity framework 将十六进制字符串作为 varbinary 保存到 sql

Saving Hex string into sql as varbinary using entity framework

我正在尝试将当前通过存储过程发生的 table 插入替换为非常简单的 Entity Framework 命令。问题是数据以加密字符串开始,然后在传递给存储过程之前变成十六进制字符串。存储过程需要 varbinary(50) 并且可能只是将 HEX 字符串即时转换为 varbinary

我不能简单地传递 Entity Framework HEX 字符串 - 它知道它应该是 byte[]!

我想不通的是如何将十六进制字符串转换为 byte[],这将与 SQL 服务器在后端执行的操作完全相同。

我已经确定了服务器使用的编码 SQL,并且能够将 byte[] 转换回我开始使用的加密字符串:

System.Text.Encoding.GetEncoding("iso-8859-1").GetString(bytes)

是否有 Entity Framework 技巧或其他一些选项来继续让 SQL 服务器进行转换?我无法更改 SQL 服务器中的数据类型,并且我不想创建一个只接受字符串和 returns varbinary.

的虚拟存储过程

对于那些感兴趣的人,生成的示例十六进制字符串是 0x1C3307260C18。 出于本次讨论的目的,这个字符串的生成方式无关紧要 - 因为它是与安全相关的代码,所以我无法 post 创建它的确切过程。

我需要知道的是,创建此字符串后,如何使用 C# 复制 SQL 服务器将此字符串转换为 varbinary 等效字符串的过程?顺便说一句,在 SQL 服务器中查看 table 时,二进制数据以这种精确的十六进制形式呈现。因此,将字符串 0x1C3307260C18 传递给 SQL 会导致它被存储为 varbinary,并且它在查询中呈现完全相同:0x1C3307260C18.

如果你可以通过 Encoding.GetEncoding("iso-8859-1").GetString(bytes) 得到原始的十六进制字符串,很明显原始代码实际上并没有使用十六进制字符串的二进制表示 - 它只是将 文本转换varbinary!

这可能不是作者的本意。

但是,您可以通过相反的方式得到完全相同的结果 - Encoding.GetEncoding("iso-8859-1").GetBytes(hexstring)

问题可能源于引用十六进制字符串 - 0x1C3307260C18 是一个非常好的 varbinary 值,但 '0x1C3307260C18'varchar - 当转换为 varbinary,它只是使用字符串->字节转换规则进行转换(所以基本上只是应用给定的编码)。

如果您想保留 "wrong" 代码,那很好,并且与 SQL 服务器执行相同的操作(假设服务器的排序规则对应于 ISO-8859-1)。如果你想修复它并实际保存二进制字符串 0x1C3307260C18,你需要更难地转换它(或者只是将你的解密方法修复为 return byte[] 而不是 string:)):

Func<char, int> getHex = c =>
 {
   var p = c - '0';
   if (p < 10) return p;

   return (char.ToUpperInvariant(c) - 'A') + 10;
 };

var hexString = "0x1C3307260C18";
if (!hexString.StartsWith("0x")) { return null; } // Fail in some way

var bytes = new byte[hexString.Length / 2 - 1];
for (int i = 0; i < bytes.Length; i++)
{
  bytes[i] = 
   (byte)
    (
     (getHex(hexString[(i + 1) * 2]) << 4) 
     | getHex(hexString[(i + 1) * 2 + 1])
    );
}

bytes.Select(i => i.ToString("X2")).Dump();

通常,使用 Convert.ToByte(str, 16) 会更好,但是对于像解析十六进制字符串这样简单的事情,做这么多 Substring 可能是一种浪费:)

当然,最后一行只是为了验证它是否有效;您还希望使 getHex 函数成为一种方法,而不是使其保持匿名。根据您的要求,您可能想要添加额外的错误检查 - 例如getHex 绝不能 return 超出 0-15 范围等