2010-06-09 34 views
0

我正在開發C#VS 2008/SQL Server 2005 Express網站應用程序。我已經嘗試了一些這個問題的修復,但我的調用堆棧不同於其他。而這些修復並沒有解決我的問題。我可以採取哪些措施來解決此問題?從字符串轉換datetime時轉換失敗

這是我的錯誤:

System.Data.SqlClient.SqlException was caught 
    Message="Conversion failed when converting datetime from character string." 
    Source=".Net SqlClient Data Provider" 
    ErrorCode=-2146232060 

    LineNumber=10 
    Number=241 
    Procedure="AppendDataCT" 
    Server="\\\\.\\pipe\\772EF469-84F1-43\\tsql\\query" 
    State=1 
    StackTrace: 
     at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) 
     at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 
     at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) 
     at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 
     at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) 
     at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) 
     at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) 
     at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) 
     at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() 
     at ADONET_namespace.ADONET_methods.AppendDataCT(DataTable dt, Dictionary`2 dic) in c:\Documents and Settings\Admin\My Documents\Visual Studio 2008\WebSites\Jerry\App_Code\ADONET methods.cs:line 102 

這裏是相關的代碼。當我調試這段代碼時,「dic」只會遍歷3列名稱,但不會查看存儲在數據表「dt」中的行值。

public static string AppendDataCT(DataTable dt, Dictionary<string, string> dic) 
{ 
    if (dic.Count != 3) 
     throw new ArgumentOutOfRangeException("dic can only have 3 parameters"); 

    string connString = ConfigurationManager.ConnectionStrings["AW3_string"].ConnectionString; 
    string errorMsg; 

    try 
    {    
     using (SqlConnection conn2 = new SqlConnection(connString)) 
     { 
      using (SqlCommand cmd = conn2.CreateCommand()) 
      { 
       cmd.CommandText = "dbo.AppendDataCT"; 
       cmd.CommandType = CommandType.StoredProcedure; 
       cmd.Connection = conn2; 
       foreach (string s in dic.Keys) 
       { 
        SqlParameter p = cmd.Parameters.AddWithValue(s, dic[s]); 
        p.SqlDbType = SqlDbType.VarChar; 
       } 

       conn2.Open(); 
       cmd.ExecuteNonQuery(); 
       conn2.Close(); 
       errorMsg = "The Person.ContactType table was successfully updated!"; 
      } 
     } 
    } 

這裏是我的SQL存儲過程:

ALTER PROCEDURE [dbo].[AppendDataCT] 
@col1 VARCHAR(50), 
@col2 VARCHAR(50), 
@col3 VARCHAR(50) 
AS 
BEGIN 
SET NOCOUNT ON; 
DECLARE @TEMP DATETIME 
SET @TEMP = (SELECT CONVERT (DATETIME, @col3)) 

INSERT INTO Person.ContactType (Name, ModifiedDate) 
VALUES(@col2, @TEMP) 
END 

輸入文件有3列。前兩個是varchars,但第三個也是我認爲的varchar,但它表示爲「3/11/2010」。在此輸入文件中,樣本行如下所示: 「Benjamin | breakfast | 3/11/2010」。 而我試圖將這個日期字段從一個字符串轉換爲我的SP中的日期時間。我是否以錯誤的方式去做?

的DataRow: COL1 | COL2 | COL3 11 | A2 | 1978年1月10日 12 | B2 | 1978年2月10日 13 | C2 | 1978年3月10日 14 | D2 | 4/10/1978

+4

您的代碼混淆了我。爲什麼你要傳遞一個固定數量項目的字典,然後在期待datetime類型時使用'VarChar'參數類型? – 2010-06-09 17:40:57

+0

您在Dctionary dic中持有哪些類型的數據以及DataTable中有哪些數據?我有一個假設和一個答案,但需要確認。 – TheGeekYouNeed 2010-06-09 17:54:26

+0

字典詞典包含3列標題; DataTable包含來自輸​​入文件的行值。 喬恩,我想讀取日期字段作爲varchar。 查看最新的代碼和評論。 – salvationishere 2010-06-09 22:04:23

回答

4

我覺得別洛烏索夫帕維爾是正確的。在您的foreach中,您將每個字典項目分配爲一個參數。每個參數都被定義爲VarChar。使用提供的信息,假設問題出現在存儲過程中是合理的。

您可以發佈存儲過程的代碼,也可以嘗試通過在那裏執行存儲過程來重新創建SQL Management Studio中的錯誤。

UPDATE ...

看你的存儲過程後的代碼看起來是正確的。我能夠使用下面的sql代碼生成錯誤消息。

DECLARE @ COL3 VARCHAR(50)

組@ COL3 = '| 3/11/2010'

聲明@temp日期時間

設置@temp =(選擇轉換(日期時間,@ COL3))

注意的@用豎線COL3開始值。如果你刪除管道字符,它可以正常工作。

我會看在你是讓你從參數值字典中的值接近。解析數據的方式可能存在問題。

更新2

下面的代碼未確認工作,但我想我明白你正在嘗試做的。我假設DataTable中你傳遞了這樣的數據:

COL1 | COL2 | COL3 11 | A2 | 1978年1月10日 12 | B2 | 1978年2月10日 13 | C2 | 3/10/1978 14 | d2 | 4/10/1978

如果是這種情況,我們不需要最初傳入的字典。我還可以假設你想爲DataTable中的每一行執行一次存儲過程。下面的方法類似於你在做什麼,儘管它爲每一行運行存儲過程。

什麼我不知道從你的解釋是,如果數據表的第一行包含列的名稱,如果不是那麼無後顧之憂。希望這是有道理的,如果你有問題,留下更多的評論。

public static string TestMethod(DataTable dt) 
    { 
     string connString = ""; 
     string errorMsg = string.Empty; 

     try 
     { 
      //loop through each row of the datatable. Not sure if the column names is a row. 
      foreach (DataRow row in dt.Rows) 
      { 
       using (SqlConnection conn2 = new SqlConnection(connString)) 
       { 
        using (SqlCommand cmd = conn2.CreateCommand()) 
        { 
         cmd.CommandText = "dbo.AppendDataCT"; 
         cmd.CommandType = CommandType.StoredProcedure; 
         cmd.Connection = conn2; 

         cmd.Parameters.Add(new SqlParameter() { ParameterName = "@col1", SqlDbType = SqlDbType.VarChar, Value = row[0] }); 
         cmd.Parameters.Add(new SqlParameter() { ParameterName = "@col2", SqlDbType = SqlDbType.VarChar, Value = row[1] }); 
         cmd.Parameters.Add(new SqlParameter() { ParameterName = "@col3", SqlDbType = SqlDbType.VarChar, Value = row[2] }); 

         conn2.Open(); 
         cmd.ExecuteNonQuery(); 
         conn2.Close(); 
        } 
       }     
      } 
      errorMsg = "The Person.ContactType table was successfully updated!"; 
     } 
     catch 
     { 
     } 

     return errorMsg; 
    } 
+0

你會看看我的SP代碼結尾 – salvationishere 2010-06-09 22:05:01

+0

謝謝Dev,但我該如何在SP中做到這一點?你在暗示我改變了什麼? – salvationishere 2010-06-09 23:12:41

+0

現在不要認爲它是SP的問題。請調試C#代碼並檢查字典對象(dic)中的值。我敢打賭,日期的價值已經超過了日期,導致了轉換錯誤。 – DevDave 2010-06-09 23:30:52

1

問題出在存儲過程中,我想。可能是輸入參數之一是DateTime,但是您將VarChar寫入此參數。

UPDATE

我可以看到你不要在你的方法AppendDataCT使用DataTable dt

您寫的dic包含值[0]:[col1,col1] [1]:[col2,col2] [2]:[col3,col3]。但它是錯誤的值...你的代碼是

SqlParameter p = cmd.Parameters.AddWithValue(s, dic[s]); 

然後你發送到col3 value = col3,據我所知。

可能是你想寫

SqlParameter p = cmd.Parameters.AddWithValue(s, dt[s]); 

或這樣的事情...

+0

請您看看我的SP代碼嗎? – salvationishere 2010-06-09 22:06:09

+0

我試過了,但後來發現有錯誤: foreach(dt)中的字符串// dt.Keys) SqlParameter p = cmd.Parameters.AddWithValue(s,dt); // [S]); p.SqlDbType = SqlDbType.VarChar; } foreach語句無法對'System.Data.DataTable'類型的變量進行操作,因爲'System.Data.DataTable'不包含'GetEnumerator'的公共定義 – salvationishere 2010-06-11 05:23:29

+0

對於每個應使用dic,並且在AddWithValue中 - DT。 – 2010-06-11 06:16:10

2

好吧,如果你這樣做:

SqlParameter p = cmd.Parameters.AddWithValue(s, dic[s]); 
p.SqlDbType = SqlDbType.VarChar; 

所有的參數都將是VARCHAR類型。這聽起來很聰明 - 事實並非如此。

如果您將日期作爲varchar傳遞,您將開始進入日期/時間字符串格式的混亂業務 - 除非您始終使用適用於任何SQL Server安裝的ISO-8601格式YYYYMMDD以及任何語言環境/語言/日期設置。其他任何事情都會成爲賭博。並不是像美國一樣使用MM/DD/YYYY格式,並且根據您的SQL Server的語言或日期格式設置,您的日期可能無法識別,甚至被誤解。只是不要這樣做 - 這是一團糟。

另外,真的 - 如果你的日期/時間在你的C#代碼 - 我會強烈建議您傳遞,作爲SqlDbType.DateTime到您的SQL Server存儲過程。你只是想救調試和凌亂的轉換,並塞入自己的無數個小時.......

+0

你最後可以看看我的SP代碼嗎? – salvationishere 2010-06-09 22:04:41

+0

@Salvationishere:將這些樣本轉換爲DATETIME,只要您的服務器將「美國英語」設置爲其語言,就可以使用**。我不認爲這三個樣本會造成麻煩......其他一些條目必須以某種方式關閉 – 2010-06-10 05:10:40

+0

是的,英語被設置爲其語言 – salvationishere 2010-06-10 11:55:54

1

您可以通過DataTable的行需要循環獲取數據 - 您要添加DIC的值(您的月份,日期,年份的列名稱)作爲SqlParameters .....這就是我所假設的,因爲問題很分散....

注:不完全起作用的代碼 -

foreach(DataRow dr in dt.Rows) 
{ 
    DateTime date = new DateTime(); 

    foreach(string s in dic.Keys) 
    { 
     switch(dic[s]) 
     { 
      case "Month": 
       date.Month = dr[dic[s]]; 
       break; 
      case "Day": 
       date.Day = dr[dic[s]]; 
       break; 
      case "Year": 
       date.Year = dr[dic[s]]; 
       break; 
     } 

    } 

    // If valid date 
    SqlParameter p = cmd.Parameters.AddWithValue("Date", date); 
    p.SqlDbType = SqlDbType.DateTime;  


} 

更新:您將需要處理自己的數據驗證 - 否則,在這裏你去

using (SqlConnection conn2 = new SqlConnection(connString)) 
    { 
     using (SqlCommand cmd = conn2.CreateCommand()) 
     { 
      conn2.Open();    


      foreach(DataRow dr in dt.Rows) 
      { 
       SqlParameter col1 = cmd.Parameters.AddWithValue(dic[0], dr[0].ToString()); 
       SqlParameter col2 = cmd.Parameters.AddWithValue(dic[1], dr[1].ToString()); 
       SqlParameter col3 = cmd.Parameters.AddWithValue(dic[2], Convert.ToDateTime(dr[2])); 

       cmd.ExecuteNonQuery(); 

      } 

      conn2.Close(); 
     } 
    } 
+0

謝謝,但您是否請查看我的SP代碼? – salvationishere 2010-06-09 22:05:30

相關問題