SQL CONVERT из varbinary в varchar

Я использую приложение на C# и похоже, что оно готово для вставки изображения в мою базу данных, но моя хранимая процедура выдает неявную ошибку преобразования. Я считал изображение в байтовый массив и передал байтовый массив в мою хранимую процедуру. Это ожидает varbinary параметр, отсюда и ошибка. Поэтому я изменяю свою хранимую процедуру следующим образом:

ALTER PROCEDURE insertPlayerImage 
      @playerID varchar(9), 
      @profileImage varchar(max), 
      @pending char(1)
AS
    CONVERT(varbinary(max), @profileImage)

INSERT INTO PlayerImage(playerID, profileImage, pending)
VALUES(@playerID, @profileImage, @pending)
GO

что говорит мне, что ожидает varchar (мой байтовый массив) и преобразовать массив в varbinary файл. Что ж, моей хранимой процедуре не нравится строка преобразования, которую я имею. но если я просто сделаю

SELECT CONVERT(varchar, GETDATE());  

оно работает. Все поиски в Google указывают на конвертацию даты, как будто это единственное, что вы можете использовать для конвертации.

3 ответа

Решение

Вы используете SQL Server? Если это так, см. Эту страницу для сопоставления типов данных SQL и CLR: http://msdn.microsoft.com/en-us/library/cc716729.aspx

SQL Server char, varchar, nchar а также nvarchar все карты в / из C# string (хотя char[] будет работать так же).

SQL Server binary andVARBINARYmap to/from a C#байт []`.

Какая у вас проблема?

Кроме того, если вы передаете двоичные данные как varchar в SQL Server, я ожидаю, что они будут преобразованы в преобразование между UTF-16 (кодирование внутренней строки CLR) в любую кодовую страницу, используемую SQL Server.

Еще одна вещь, которую стоит отметить: ваша хранимая процедура:

ALTER PROCEDURE insertPlayerImage 
  @playerID varchar(9), 
  @profileImage varchar(max), 
  @pending char(1)
AS

  CONVERT(varbinary(max), @profileImage)

  INSERT INTO PlayerImage
  ( playerID , profileImage , pending )
  VALUES
  ( @playerID , @profileImage , @pending )

GO

не законный SQL. Convert() это функция, а не оператор SQL. Это даже не компилируется. Если вы пытаетесь конвертировать ваши varchar параметр @profileImage в varbinaryвам придется что-то делать по

 declare @image varbinary(max)
 set @image = convert(varbinary(max),@profileImage)

Если вы хранимая процедура имеет подпись

create procedure dbo.insertPlayerImage

  @playerId     varchar(9) ,
  @profileImage varbinary(max) ,
  @pending      char(1)

as
...

Тогда этот код сделает вас:

public int insertProfileImage( string playerId , byte[] profileImage , bool pending )
{
  if ( string.IsNullOrWhiteSpace(playerId) ) throw new ArgumentException("playerId" ) ;
  if ( profileImage == null || profileImage.Length < 1 ) throw new ArgumentException("profileImage") ;

  int rowCount ;

  string connectString = GetConnectString() ;
  using ( SqlConnection connection = new SqlConnection(connectString) )
  using ( SqlCommand command = connection.CreateCommand() )
  {

    command.CommandType = CommandType.StoredProcedure ;
    command.CommandText = "dbo.insertPlayerImage" ;

    command.Parameters.AddWithValue( "@playerId"     , playerId            ) ;
    command.Parameters.AddWithValue( "@profileImage" , profileImage        ) ;
    command.Parameters.AddWithValue( "@pending"      , pending ? "Y" : "N" ) ;

    rowCount = command.ExecuteNonQuery() ;

  }

  return rowCount ;
}

Однако, если вы передаете null для данных изображения вам нужно изменить способ установки значения параметра. Что-то вроде:

command.Parameters.AddWithValue( "@profileImage" , profileImage != null ? (object)profileImage : (object)DBNull.Value ) ;

Или же

SqlParameter p = new SqlParameter( "@profileImage" , SqlDbType.VarBinary ) ;
p.Value = DBNull.Value ;
if ( profileImage != null )
{
  p.Value = profileImage ;
}
command.Parameters.Add( p ) ;

Вы должны быть в состоянии использовать varbinary(max) в качестве типа параметра. если нет, то вы неправильно настраиваете объект или параметры команды d b перед выполнением Execute.

 public DataTable ExecuteParameterizedStoredProcedureObjects(string procedureName, Dictionary<string, object> parameters)
        {
            var dataTable = new DataTable();
            var _sqlConnection = new SqlConnection(_connectionString);
            var cmd = new SqlCommand(procedureName, _sqlConnection);
            cmd.CommandType = CommandType.StoredProcedure;

            var da = new SqlDataAdapter(cmd);
            foreach (var entry in parameters)
            {
                cmd.Parameters.Add(entry.Key, entry.Value);
            }

            try
            {
                _sqlConnection.Open();
                da.Fill(dataTable);
            }
            catch (Exception ex)
            {
                var errorText = string.Format("Occ Repository ExecuteQuery Error : QueryString={0} :: Error={1}", procedureName, ex.Message);
                throw new Exception(errorText, ex);
            }
            finally
            {
                da.Dispose();
                _sqlConnection.Dispose();
            }

            return dataTable;
        }

Назовите это что-то вроде:

 foreach (var record in missingGridEntries)
             {
                 var parameters = new Dictionary<string, object>();
                 parameters.Add("@DataID",int.Parse(record.NodeId));
                 var results = _llDb.ExecuteParameterizedStoredProcedureObjects("listFullPath",parameters);

                 foreach(DataRow dataRow in results.Rows)
                 {
                     record.NodePath = dataRow["fullpath"].ToString();
                     record.NodeFilename = dataRow["name"].ToString();
                 }

             }

ОК - вам нужно это:

Хранимая процедура для получения параметра как varbinary(max) так что вы можете вставить его в Varbinary(max) столбец в таблице базы данных:

CREATE PROCEDURE insertPlayerImage 
      @playerID varchar(9), 
      @profileImage varbinary(max), 
      @pending char(1)
AS
    CONVERT(varbinary(max), @profileImage)

    INSERT INTO PlayerImage(playerID, profileImage, pending)
    VALUES(@playerID, @profileImage, @pending)

Код C# для получения содержимого файла, загруженного в ASP.NET и вызова этой хранимой процедуры:

// set up connection and command
using(SqlConnection conn = new SqlConnection("your-connection-string-here"))
using(SqlCommand cmd = new SqlCommand("dbo.insertPlayerImage"))
{
    // define parameters
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@playerID", SqlDbType.VarChar, 9);
    cmd.Parameters.Add("@playerImage", SqlDbType.VarBinary, -1);
    cmd.Parameters.Add("@pending", SqlDbType.Char, 1);

    // set the parameter values
    cmd.Parameters["@playerID"].Value = Session["playerID"].ToString();
    cmd.Parameters["@playerImage"].Value = uplImage.FileBytes;
    cmd.Parameters["@pending"].Value = "Y";

    // open connection, execute stored procedure, close connection
    conn.Open();
    cmd.ExecuteNonQuery();
    conn.Close();
}

Там действительно абсолютно не нужно конвертировать содержимое загруженного файла из byte[] к чему-либо еще (и обратно!) - просто установите значение varbinary(max) параметр и вызов этой хранимой процедуры - это все, что вам нужно сделать!

Другие вопросы по тегам