使用实体框架

时间:2015-05-06 13:47:40

标签: c# sql-server entity-framework encoding

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

我不能简单地将实体框架传递给HEX字符串 - 它知道它应该是byte[]

我无法弄清楚如何将十六进制字符串转换为byte[],这与SQL Server在后端的操作完全相同。

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

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

是否存在实体框架技巧或其他一些选项,只是继续让SQL Server进行转换?我无法更改SQL Server中的数据类型,我宁愿不创建一个虚拟存储过程,只需接收一个字符串并返回varbinary

对于那些感兴趣的人,生成的示例十六进制字符串是0x1C3307260C18。 出于本讨论的目的,如何生成此字符串并不重要 - 因为它是与安全性相关的代码,所以我无法发布创建它的确切过程。

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

1 个答案:

答案 0 :(得分:0)

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

这可能不是作者的意图。

但是,你可以通过反向做出完全相同的事情 - Encoding.GetEncoding("iso-8859-1").GetBytes(hexstring)

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

如果你想保留“错误的”代码,那就没问题了,并且SQL服务器做了同样的事情(假设服务器的内容对应于ISO-8859-1)。如果你想修复它并实际保存二进制字符串0x1C3307260C18,你需要更难转换(或者只修复你的解密方法以返回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永远不应该返回到0-15范围之外等。