2009-01-08 35 views
21

我試圖從C#.NET 2.0調用存儲過程(在SQL 2005服務器上),使用DateTime作爲SqlParameter的值。存儲過程中的SQL類型是'datetime'。在SqlParameter中爲存儲過程使用DateTime,格式錯誤

從SQL Management Studio執行sproc可以正常工作。但每次我從C#中調用它時,都會收到有關日期格式的錯誤。

當我運行SQL事件探查器來查看調用時,然後複製粘貼exec調用以查看發生了什麼。這是什麼,我已經嘗試我的觀察和注意事項:

1)如果我直接通過DateTimeDateTime或轉換爲SqlDateTime,本場是由單引號的一對周邊,如

@Date_Of_Birth=N''1/8/2009 8:06:17 PM'' 

2)如果我作爲一個字符串傳遞DateTime,我只得到單引號

3)使用SqlDateTime.ToSqlString()不會導致UTC格式的時間字符串(即使轉換爲通用時間後)

4)使用DateTime.ToString()不會導致UTC格式的日期時間字符串。

5)手動設置的DbTypeDateTime不會改變上述觀察結果。

那麼,我的問題是,我是如何讓C#在SqlParameter中通過正確格式化的時間?當然這是一個常見的用例,爲什麼工作很難?我似乎無法DateTime轉換爲字符串,它是SQL compatable(如 '2009-01-08T08:22:45')

編輯

RE:貝麗,代碼實際執行存儲過程如下:

using (SqlCommand sprocCommand = new SqlCommand(sprocName)) 
{ 
    sprocCommand.Connection = transaction.Connection; 
    sprocCommand.Transaction = transaction; 
    sprocCommand.CommandType = System.Data.CommandType.StoredProcedure; 
    sprocCommand.Parameters.AddRange(parameters.ToArray()); 
    sprocCommand.ExecuteNonQuery(); 
} 

要進入更詳細的關於什麼我曾嘗試:

parameters.Add(new SqlParameter("@Date_Of_Birth", DOB)); 

parameters.Add(new SqlParameter("@Date_Of_Birth", DOB.ToUniversalTime())); 

parameters.Add(new SqlParameter("@Date_Of_Birth", 
    DOB.ToUniversalTime().ToString())); 

SqlParameter param = new SqlParameter("@Date_Of_Birth", 
    System.Data.SqlDbType.DateTime); 
param.Value = DOB.ToUniversalTime(); 
parameters.Add(param); 

SqlParameter param = new SqlParameter("@Date_Of_Birth", 
    SqlDbType.DateTime); 
param.Value = new SqlDateTime(DOB.ToUniversalTime()); 
parameters.Add(param); 

parameters.Add(new SqlParameter("@Date_Of_Birth", 
    new SqlDateTime(DOB.ToUniversalTime()).ToSqlString())); 

額外編輯

我認爲最有可能的工作之一:在這個價值

SqlParameter param = new SqlParameter("@Date_Of_Birth", 
    System.Data.SqlDbType.DateTime); 
param.Value = DOB; 

結果在exec調用所看到的SQL事件探查器

@Date_Of_Birth=''2009-01-08 15:08:21:813'' 

如果我修改這是:

@Date_Of_Birth='2009-01-08T15:08:21' 

它的工作,但它不會解析與一對唱歌le引號,並且它不會在日期和時間之間正確地轉換爲DateTime,並且在最後以毫秒爲單位。

更新和成功

我複製/從下面的請求後粘貼上面的代碼。我在這裏和那裏修剪了一些簡潔的東西。結果發現我的問題出在我遺漏的代碼中,我相信你們中的任何一個人都會馬上發現。我在一個交易中包裝了我的存儲過程調用。原來,我根本沒在做transaction.Commit() !!!!!我很慚愧地說,但你知道。

我仍然不知道我從分析器返回的語法是怎麼回事。一位同事用他自己的計算機上的分析器實例觀察,並返回了正確的語法。從我的分析器中看到非常類似的執行情況,顯示了不正確的語法。它充當了一個紅鯡魚,使我相信有一個查詢語法問題,而不是更簡單和真實的答案,這就是我需要提交交易!

我在下面標記了一個正確答案,並在其他人中投了贊成票,因爲他們畢竟回答了問題,即使他們沒有解決我的具體問題(大腦失效問題)。

回答

24

你是如何設置SqlParameter?您應該將SqlDbType property設置爲SqlDbType.DateTime,然後直接將DateTime傳遞給參數(不要轉換爲字符串,然後您需要一堆問題)。

您應該可以將值存入數據庫。如果不是,這裏是如何做到這一點很簡單的例子:

static void Main(string[] args) 
{ 
    // Create the connection. 
    using (SqlConnection connection = new SqlConnection(@"Data Source=...")) 
    { 
     // Open the connection. 
     connection.Open(); 

     // Create the command. 
     using (SqlCommand command = new SqlCommand("xsp_Test", connection)) 
     { 
      // Set the command type. 
      command.CommandType = System.Data.CommandType.StoredProcedure; 

      // Add the parameter. 
      SqlParameter parameter = command.Parameters.Add("@dt", 
       System.Data.SqlDbType.DateTime); 

      // Set the value. 
      parameter.Value = DateTime.Now; 

      // Make the call. 
      command.ExecuteNonQuery(); 
     } 
    } 
} 

我覺得這裏的問題的一部分是,你擔心的事實,時間是UTC不被傳送到SQL Server 。爲此,您不應該這樣做,因爲SQL Server不知道某個特定時間處於特定的區域/時區。

如果你想存儲UTC值,然後將它傳遞到SQL Server(之前轉換爲UTC,除非你的服務器有相同的時區的客戶端代碼生成DateTime,即使在當時,這是一個風險,IMO )。 SQL Server會存儲這個值,當你得到它的時候,如果你想在本地時間顯示它,你必須自己來完成(DateTime這個結構很容易做到)。

就是這麼說,如果執行轉換,然後將轉換後的UTC日期(通過調用ToUniversalTime method而不是轉換爲字符串獲得的日期)傳遞給存儲過程。

當您獲得價值回撥時,請致電ToLocalTime method以獲取當地時區的時間。

0

只需使用:

param.AddWithValue("@Date_Of_Birth",DOB); 

這將需要的所有的問題護理。

+0

不似乎工作 - 每個SQL事件探查器,字符串格式是不正確的,如果我複製粘貼,每邊一對單引號是不要麼有效 – Matt 2009-01-08 21:45:48

2

這是我如何添加參數:當你寫出來DOB沒有引號

sprocCommand.Parameters.Add(New SqlParameter("@Date_Of_Birth",Data.SqlDbType.DateTime)) 
sprocCommand.Parameters("@Date_Of_Birth").Value = DOB 

我假設。

您是否使用第三方控件獲取日期?我從某些文本值的生成方式出現問題。

最後,如果您在不引用DOB的情況下輸入參數的.Value屬性,它會起作用嗎?

0

如果使用Microsoft.ApplicationBlocks.Data它會讓你調用存儲過程單行

SqlHelper.ExecuteNonQuery(ConnectionString, "SprocName", DOB) 

哦,我想casperOne是正確的......如果你想確保在多個時區的正確日期時間然後只需轉換值UTC你之前值發送到SQL Server

SqlHelper.ExecuteNonQuery(ConnectionString, "SprocName", DOB.ToUniversalTime())