2013-05-15 3 views
0

J'utilise une application C# et il semble qu'il soit prêt à insérer l'image dans ma base de données, mais ma procédure stockée provoque une erreur de conversion implicite. Je lis l'image dans un tableau d'octets et passe le tableau d'octets à ma procédure stockée. Il attend un paramètre varbinary, d'où l'erreur. Donc, je modifie ma procédure stockée à:SQL CONVERT de varbinary à varchar

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 

qui me dit qu'il attend un varchar (mon tableau d'octets) et convertir le tableau dans un fichier varbinary. Eh bien, ma procédure stockée n'aime pas la ligne de conversion que j'ai. mais si je fais simplement

SELECT CONVERT(varchar, GETDATE()); 

cela fonctionne. Toutes les recherches google pointent vers la conversion de la date, presque comme si c'est la seule chose sur laquelle vous pouvez convertir.

+0

Si vous devez ** stocker ** une valeur 'varbinary (max)' - ** pourquoi diable ** n'utilisez-vous pas un 'varbinary (max)' comme ** type de paramètre ** dans le premier endroit?!?!? –

+0

dans ma base de données, le type de données est un varbinary max. Im essayant de permettre à un utilisateur de télécharger une image et l'enregistrer. tous les exemples de cela, lisez l'image à un tableau d'octets. mais quand j'ai essayé de passer mon tableau d'octets à mon proc stocké, il m'a donné l'erreur de conversion. donc j'ai changé le @profileImage pour être un varchar, et dans mon proc stocké j'allais le convertir du tableau d'octets (varchar) au varbinary. – dwarf

+0

Oui - donc si c'est 'varbinary (max)' dans la base de données, alors le paramètre procédure stockée devrait aussi être 'varbinary (max)': '@profileImage varbinary (max)' - alors vous ** don ' J'ai besoin de ** conversions .... –

Répondre

0

Utilisez-vous SQL Server? Si oui, voir cette page pour le type de données SQL pour applications de type de données CLR: http://msdn.microsoft.com/en-us/library/cc716729.aspx

SQL Server char, varchar, nchar et nvarchar tous vers/à partir d'un string C# (si un char[] fonctionnera aussi bien). SQL Server binary and varbinary map to/from a C# octet [] `.

Quel est le problème réel que vous rencontrez? En outre, si vous transmettez des données binaires en tant que varchar à SQL Server, je m'attendrais à ce qu'il soit intégré dans la transformation entre UTF-16 (codage de chaîne interne CLR) et la page de code utilisée par SQL Server.

Une autre chose à noter: votre procédure stockée:

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 

n'est pas SQL juridique. Convert() est une fonction, pas une instruction SQL. Il ne compile même pas. Si vous essayez de convertir votre varchar paramètre @profileImage-varbinary, vous allez devoir faire quelque chose le long des lignes de

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

Si vous êtes procédure stockée a la signature

create procedure dbo.insertPlayerImage 

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

as 
... 

Ensuite, ce code vous fera:

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 ; 
} 

cependant, si vous passez une null pour les données d'image, vous devez modifier la définition de la valeur du paramètre.Quelque chose le long des lignes de:

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

Ou

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

Nicholas Carey, votre une bête. Merci – dwarf

1

Vous devriez pouvoir utiliser varbinary (max) comme type de paramètre. sinon, vous ne configurez pas correctement votre objet de commande db ou vos paramètres avant d'exécuter 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; 
     } 

appel avec quelque chose comme:

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(); 
       } 

      } 
+0

Je vais essayer ceci, ou prendre ce que vous avez et utiliser une variation de celui-ci. J'utilise des tables de données mais n'utilise pas le type de procédure stockée C# – dwarf

+0

CommandType.StoredProcedure indique au pilote ODBC que vous allez appeler une procédure stockée sur le serveur, plutôt que d'interroger directement une table ou une vue. Vous voulez certainement l'utiliser! –

0

OK - vous en avez besoin:

procédure stockée pour obtenir le paramètre comme varbinary(max) de sorte que vous pouvez l'insérer dans une colonne Varbinary(max) dans la table de base de données:

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) 

Code C# pour obtenir le contenu d'un fichier ploaded dans ASP.NET et d'appeler cette procédure stockée:

// 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(); 
} 

Il n'y a vraiment absolument pas besoin à jamais convertir byte[] à tout autre contenu du fichier téléchargé - juste définir la valeur de la varbinary(max) (et retour!) paramètre et appeler cette procédure stockée - c'est tout ce que vous devez faire!

Questions connexes