使用 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 范围等
我正在尝试将当前通过存储过程发生的 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 范围等