Вставка Bytearray в SQL через хранимую процедуру, вызываемую на C#

#c# #sql #sql-server #stored-procedures

#c# #sql #хранимые процедуры #массивы

Вопрос:

Прежде всего, я все перепробовал и не могу понять, почему он не обновит мое поле varbinary должным образом.

из 1728 байт в поле сохраняется только последний байт в массиве байтов…

Я генерирую свой байтовый массив следующим образом:

 public static byte[] StringToByteArray(String hex)
{
    int NumberChars = hex.Length;
    byte[] bytes = new byte[NumberChars / 2];
    for (int i = 0; i < NumberChars; i  = 2)
        bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    return bytes;
}
  

Я также попробовал приведенный ниже:

 public static byte[] ParseHex(string hex)
{
    int offset = hex.StartsWith("0x") ? 2 : 0;
    if ((hex.Length % 2) != 0)
    {
        throw new ArgumentException("Invalid length: "   hex.Length);
    }
    byte[] ret = new byte[(hex.Length - offset) / 2];

    for (int i = 0; i < ret.Length; i  )
    {
        ret[i] = (byte)((ParseNybble(hex[offset]) << 4)
                         | ParseNybble(hex[offset   1]));
        offset  = 2;
    }
    return ret;
}

static int ParseNybble(char c)
{
    if (c >= '0' amp;amp; c <= '9')
    {
        return c - '0';
    }
    if (c >= 'A' amp;amp; c <= 'F')
    {
        return c - 'A'   10;
    }
    if (c >= 'a' amp;amp; c <= 'f')
    {
        return c - 'a'   10;
    }
    throw new ArgumentException("Invalid hex digit: "   c);
}
  

Мой код на c # для сохранения данных таков:

 using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DB_Conn"].ConnectionString))
{
  byte[] to_store = StringToByteArray(inventory);

  //State the Stored Proc and add Values to 'cmd' to pass to the Stored Proc
  SqlCommand cmd = new SqlCommand("_USP_store", conn);
  cmd.CommandType = CommandType.StoredProcedure;
  cmd.Parameters.AddWithValue("@A", TB_A.Text);
  cmd.Parameters.Add("@B", SqlDbType.VarBinary, 1728).Value = to_store;

  try
  {
    // Open Connection and execute Stored Proc
    conn.Open();
    cmd.ExecuteNonQuery();
    C2_Wipe_Message.Text = "Storing success";
    C2_Wipe_Message.ForeColor = Color.FromArgb(0, 0, 255, 0);

  }
  catch
  {
    C2_Wipe_Message.Text = "An error occured..";
    C2_Wipe_Message.ForeColor = Color.FromArgb(0, 255, 0, 0);
  }
  finally
  {
    if (conn.State == System.Data.ConnectionState.Open)
    {
      //Close connection IF open
      conn.Close();
    }
  }
}
  

Я отправил его в виде строки, я отправил его в виде простого двоичного файла, я отправил его в виде массива шестнадцатеричных байтов и т.д.

Я предполагаю использовать цикл while в sql для его хранения, но это не объясняет, почему последний байт всегда сохраняется вместо первого байта массива байтов, пожалуйста, просветите меня, потому что это бесит..

* SQL SP

 @A varchar(10),
@B varbinary(1728)

    AS  

UPDATE Invenotry
SET A = @B
WHERE (Name = @A)
  

Комментарии:

1. Давайте посмотрим на SQL, я ожидаю, что проблема существует, поскольку использование цикла в SQL звучит для меня неправильно.

2. не используя цикл, но я получу процедуру sql

3. Каков тип поля [Invenotry].[A] ?

4. Это поле varchar(10), оно содержит имя. приложение должно иметь поля, для простоты поля A и поля B, поле A содержит имя, поле B содержит удобочитаемый вывод / ввод массива шестнадцатеричных байтов.

5. Смотрите Ответ ниже на основе таблицы, содержащей поля A и B. Если это не так, пожалуйста, опубликуйте определение таблицы для Invenotry

Ответ №1:

Ваш sql должен быть таким:

 UPDATE Invenotry
SET B = @B
WHERE A = @A
  

Вы также можете попробовать полную версию конструктора параметров:

 SqlParamter param = new SqlParameter("@B", SqlDbType.VarBinary, 1728, ParameterDirection.Input, 
     // we have these parameters but they are ignored for input types
     false, 0, 0, null, DataRowVersion.Current, 
     // the data
     to_store);

cmd.Parameters.Add(param);
  

Комментарии:

1. тестируя это сейчас, побочный вопрос: какой способ преобразования шестнадцатеричной строки в байтовый массив вы бы использовали из двух описанных выше способов? или вы бы использовали другой метод в целом?

2. похоже, ему не понравились ‘(‘ и ‘)’ вокруг предложения WHERE, однако я заметил, что моей самой большой проблемой было присвоение полям правильного имени. Теперь я соответствующим образом изменил имена полей, а также присвоил надлежащий размер переменному полю (это было 1726 вместо 1728 ..) Хотя мне все еще интересно, какое преобразование в байтовый массив вы бы порекомендовали

3. Первый кажется более простым, однако он не проверяет начало 0x — ожидаете ли вы увидеть начало 0x ?

4. Я ожидаю, что все, что лучше всего работает с полем базы данных, имеет наименьшие накладные расходы.

5. Я думаю, цель состоит в том, чтобы оба они возвращали одно и то же — я ожидаю, что внутренняя библиотека будет быстрее, но лучший способ узнать это — протестировать оба.