Преобразование не удалось при преобразовании даты и времени из строки символов - PullRequest
1 голос
/ 09 июня 2010

Я занимаюсь разработкой приложения для веб-сайта C # VS 2008 / SQL Server 2005 Express.Я пробовал некоторые из исправлений для этой проблемы, но мой стек вызовов отличается от других.И эти исправления не решили мою проблему.Какие шаги я могу предпринять, чтобы устранить эту проблему?

Вот моя ошибка:

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» только просматривал имена трех столбцов, но не просматривал значения строк, которые хранятся в «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!";
            }
        }
    }

Здесь хранится мой SQLproc:

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, но он представлен как «11.03.2010».В этом входном файле пример строки выглядит так: «Бенджамин | завтрак | 11.03.2010».И я пытаюсь преобразовать это поле даты из строки в дату и время здесь, в моем SP.Я поступаю неправильно?

DataRow: col1 | col2 | col3 11 | A2 | 1/10/1978 12 | b2 | 2/10/1978 13 | c2 | 3/10/1978 14 | d2 | 4/10/1978

Ответы [ 4 ]

5 голосов
/ 09 июня 2010

Я думаю, что Белоусов Павел прав.Внутри каждого foreach вы назначаете каждый элемент словаря в качестве параметра.Каждый из этих параметров определяется как VarChar.С учетом предоставленной информации логично предположить, что проблема заключается в хранимой процедуре.

Можно ли опубликовать код хранимой процедуры или попытаться воссоздать ошибку в SQL Management Studio, выполнив хранимую процедуру там.

ОБНОВЛЕНИЕ ...

После просмотра вашей хранимой процедуры код выглядит правильно.Я смог сгенерировать сообщение об ошибке, которое вы получаете, используя следующий код sql.

Declare @ col3 varchar (50)

set @ col3 = '| 3/11/2010'

объявите @temp datetime

set @temp = (выберите convert (datetime, @ col3))

Обратите внимание, что значение @ col3 начинается с символа канала.Если вы удалите символ канала, он будет работать правильно.

Я бы посмотрел поближе на значения в словаре, из которого вы получаете значения параметров.Возможно, проблема связана с тем, как вы анализировали данные.

ОБНОВЛЕНИЕ 2

Код, приведенный ниже, не подтвержден, но я думаю, что вижу, что вы пытаетесьсделать.Я предполагаю, что в передаваемой вами таблице данных есть такие данные:

col1 | col2 | col3 11 | A2 | 1/10/1978 12 | b2 | 2/10/1978 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;
    }
2 голосов
/ 09 июня 2010

Хорошо, если вы сделаете это:

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

все ваши параметры будут иметь тип VARCHAR.Поначалу это может показаться умным - это не так.

Если вы передаете даты как varchar, вы начинаете погружаться в грязный бизнес форматов даты / времени - если вы не всегда используете формат ISO-8601 YYYYMMDD,работает на любой установке SQL Server и с любой настройкой локали / языка / даты.Все остальное становится азартной игрой.Не весь мир использует формат MM / DD / YYYY, как в США, и в зависимости от настроек языка или формата даты в SQL Server ваша дата может быть не распознана или даже неверно истолкована.Только не делайте этого - это беспорядок.

Плюс, действительно - если у вас есть дата / время в вашем коде C # - я бы настоятельно рекомендовал бы васпередайте это как SqlDbType.DateTime вашему хранимому процессу SQL Server.Ты просто будешь спасать себя от бесконечных часов отладки, грязных преобразований и прочего .......

1 голос
/ 09 июня 2010

Вам нужно перебрать строки в 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();
        }
   }
1 голос
/ 09 июня 2010

Проблема в хранимой процедуре, я думаю.Может быть одним из входных параметров является DateTime, но вы написали VarChar для этого параметра.

ОБНОВЛЕНИЕ :

Как я вижу, вы не используете DataTable dt вваш метод AppendDataCT.

Вы написали, что dic содержит значения [0]: [col1, col1] [1]: [col2, col2] [2]: [col3, col3].Но это неправильные значения ... ваш код

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

Затем вы отправляете в col3 значение = col3, как я понимаю.

Может быть, вы хотели написать

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

или как-то так ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...