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 and
VARBINARYmap 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)
параметр и вызов этой хранимой процедуры - это все, что вам нужно сделать!