2013-05-15 82 views
0

我正在使用C#應用程序,它看起來像準備好插入圖像到我的數據庫,但我的存儲過程吐出一個隱式轉換錯誤。我將圖像讀入一個字節數組並將字節數組傳遞給我的存儲過程。它期望varbinary參數,因此是錯誤。所以,我改變我的存儲過程是:從varbinary到varchar的SQL CONVERT

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

它的工作原理。所有谷歌搜索都指向轉換日期,就好像它是唯一可以使用轉換的東西。

+0

如果你需要**存儲一個varbinary(max)值 - **爲什麼地球上**你沒有使用'varbinary(max)'作爲**參數類型**地點?!?!? –

+0

在我的數據庫中,數據類型是varbinary max。即時通訊嘗試允許用戶上傳圖片並保存。所有的例子,讀取圖片到一個字節數組。但是當我試圖將我的字節數組傳遞給我存儲的proc時,它給了我轉換錯誤。所以我改變@profileImage是一個varchar,並且在我存儲的proc中,我將它從字節數組(varchar)轉換爲varbinary。 – dwarf

+0

是的 - 所以如果它是數據庫中的varbinary(max),那麼存儲過程參數應該也是** varbinary(max)':'@profileImage varbinary(max)' - 那麼你**不要' t需要**任何轉換.... –

回答

0

你使用SQL Server:

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

的東西,如打電話了嗎?如果是這樣,看到這個網頁的SQL數據類型CLR數據類型映射:http://msdn.microsoft.com/en-us/library/cc716729.aspx

SQL服務器charvarcharncharnvarchar都映射到/從C#string(雖然char[]也能發揮作用)。

SQL Server binary and varbinary map to/from a C# byte []`。

你遇到的實際問題是什麼?另外,如果你將二進制數據作爲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參數轉換@profileImagevarbinary,你將不得不做沿着

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) ; 
+0

尼古拉斯凱莉,你的一頭野獸。謝謝 – dwarf

1

您應該可以使用varbinary(max)作爲參數類型。如果沒有,那麼在發出執行前你沒有正確地設置你的db命令對象或參數。

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

我會嘗試這種做法,或採取您所擁有的,並使用它的變體。我使用數據表但不使用c#存儲過程類型 – dwarf

+0

CommandType.StoredProcedure通知ODBC驅動程序您將調用服務器上的存儲過程,而不是直接查詢表或視圖。你一定要使用它! –

0

OK - 你需要這樣的:

存儲過程來獲取參數爲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#代碼ploaded在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)的值(和回來了!)參數並調用存儲過程 - 這就是你需要做的!