从SQL Server数据库获取二进制列

时间:2014-02-03 20:31:28

标签: c# sql sql-server

我需要使用C#从SQL Server数据库导入一个列。

当我使用SQL Server Enterprise时,它显示为<binary>,当我在SQL Server上运行查询时,它会返回正确的二进制值。

然而,当我尝试使用C#进行编码时:

SqlConnection conn = new SqlConnection("Server=portable;Database=data;Integrated Security=true;");
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT bnry FROM RawData", conn);
SqlDataReader reader = cmd.ExecuteReader();

while(reader.Read())
{
    Console.WriteLine(reader. //I do not know what to put here
}

reader.Close();
conn.Close();

当我放reader.GetSqlBinary(0));时,我只会输出很多SqlBinary<4096>个。

当我查看SQL Server查询分析器时,当我尝试相同的命令时,它会获得0x0000..类型的代码。

读者后我应该放什么或者是否有另一种从数据库中获取此数据的方法?

4 个答案:

答案 0 :(得分:1)

您正在返回一个字节数组,因此请使用:

byte[] bytes = (byte[])reader[0];

你从那里做什么取决于字节代表什么。

答案 1 :(得分:0)

您应该从SqlDataReader索引器(MSDN)访问数据。

所以它看起来像这样:

//..
Console.WriteLine((byte[])reader["bnry"]); 
//..

<强>更新

我想我终于找到了问题所在。我们在这里不在同一页面上。我会尽量简单。

首先,您需要了解计算机中的所有信息是作为一堆字节存储在内存中的。直接使用内存中的字节非常麻烦,因此引入了不同的数据类型(intstringImage等)以简化程序员的生活。 .NET中的大多数对象仍然可以以一种或另一种方式转换为其内部表示形式的字节数组。在此转换过程中,您将丢失有关字节数组包含的信息 - 它可以很容易地为Imagestring或甚至int数组。 要从二进制表示中返回,您需要知道字节数组包含什么。

在您的示例中,您尝试直接写出字节数组。由于输出始终需要是文本,因此字节数组需要转换为string。这是通过在字节数组上调用.ToString()函数来完成的。不幸的是,对于复杂对象,.ToString()的默认实现只返回类型名称。这就是所有System.Byte[]SqlBinary<4096>行的来源。

要解决此问题,在显示结果之前,您需要将字节数组转换为必需的类型。在你的情况下,字节数组似乎包含一些文本信息,所以我猜你需要将字节数组转换为string。要做到这一点,您需要知道文本的编码(string存储在内存中的方式)。

基本上,您的代码应如下所示:

SqlConnection conn = new SqlConnection("Server=portable;Database=data;Integrated Security=true;");
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT bnry FROM RawData", conn);
SqlDataReader reader = cmd.ExecuteReader();

while(reader.Read())
{
    var valueAsArray = (byte[])reader["bnry"];

    //as there are different encodings possible, you need to find encoding what works for you
    var valueAsStringDefault = System.Text.Encoding.Default.GetString(valueAsArray);
    Console.WriteLine(valueAsStringDefault);

    //...or...
    var valueAsStringUTF8 = System.Text.Encoding.UTF8.GetString(valueAsArray);
    Console.WriteLine(valueAsStringUTF8);

    //...or...
    var valueAsStringUTF7 = System.Text.Encoding.UTF7.GetString(valueAsArray);
    Console.WriteLine(valueAsStringUTF7);

    //...or any other encoding. Most of them you can find in System.Text.Encoding namespace...
}

reader.Close();
conn.Close();

答案 2 :(得分:0)

更好的方法是使用流,以便在完成时正确处理流(可能通过套接字连接)。所以我会使用GetStream()

using(Stream stream = reader[0].GetStream())
{
  //do your work on the stream here.
}

答案 3 :(得分:0)

鉴于此表

create table dbo.bin_test
(
  c1 binary(8)    not null ,
  c2 binary(8)        null ,
  c3 varbinary(8) not null ,
  c4 varbinary(8)     null ,
)
insert dbo.bin_test values ( 0x1234     , null       , 0x1234     , null       )
insert dbo.bin_test values ( 0x012345678 , 0x12345678 , 0x12345678 , 0x12345678 )

此代码(如果您将使用SQLBinary

string connectString = "Server=localhost;Database=sandbox;Trusted_Connection=True;" ;
using ( SqlConnection connection = new SqlConnection(connectString) )
using ( SqlCommand    cmd        = connection.CreateCommand() )
{

  cmd.CommandText = "select * from dbo.bin_test" ;
  cmd.CommandType = CommandType.Text ;

  connection.Open() ;
  using ( SqlDataReader reader = cmd.ExecuteReader() )
  {
    int row = 0 ;
    while ( reader.Read() )
    {
      for ( int col = 0 ; col < reader.FieldCount ; ++col )
      {
        Console.Write( "row{0,2}, col{1,2}: " , row , col ) ;
        SqlBinary octets = reader.GetSqlBinary(col) ;
        if ( octets.IsNull )
        {
          Console.WriteLine( "{null}");
        }
        else
        {
          Console.WriteLine( "length={0:##0}, {{ {1} }}" , octets.Length , string.Join( " , " , octets.Value.Select(x => string.Format("0x{0:X2}",x)))) ;
        }
      }
      Console.WriteLine() ;
      ++row ;
    }
  }
  connection.Close() ;
}

应该产生:

row 0, col 0: length=8, { 0x12 , 0x34 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 }
row 0, col 1: {null}
row 0, col 2: length=2, { 0x12 , 0x34 }
row 0, col 3: {null}

row 1, col 0: length=8, { 0x00 , 0x12 , 0x34 , 0x56 , 0x78 , 0x00 , 0x00 , 0x00 }
row 1, col 1: length=8, { 0x12 , 0x34 , 0x56 , 0x78 , 0x00 , 0x00 , 0x00 , 0x00 }
row 1, col 2: length=4, { 0x12 , 0x34 , 0x56 , 0x78 }
row 1, col 3: length=4, { 0x12 , 0x34 , 0x56 , 0x78 }

但是如上所述,简单地做这件事可能更简洁:

byte[] octets = reader[0] as byte[] ;
if ( octets == null )
{
  Console.WriteLine( "{null}");
}
else
{
  Console.WriteLine( "length={0:##0}, {{ {1} }}" , octets.Length , string.Join( " , " , octets.Select(x => string.Format("0x{0:X2}",x)))) ;
}

得到相同的结果。