C# connection to SQL database error - c#

I am complete newbie to programming. I have a problem with my program, what I am trying to do is create a register page so that users can register and it will save into the SQL database but I got an error and I dont know what it means, I will paste the whole error message sorry if its not specific. Please explain in simple terms to me if possible thanks.
Here is my code:
protected void registerBtn_Click(object sender, EventArgs e)
{
String conString = #"Data Source=sql-server;Initial Catalog=wa310;Integrated Security=True";
SqlConnection myConnection = new SqlConnection(conString);
string cmd = "INSERT INTO Student( First_Name, Surname, User_ID, Password) VALUES ( '" + fNameTxt.Text + "' , '" + sNameTxt.Text + "','" + userIdTxt.Text + "' ,'" + passwordTxt.Text + "')";
SqlCommand myCommand = new SqlCommand(cmd, myConnection);
try
{
myCommand.Connection = myConnection;
myConnection.Open();
myCommand.ExecuteNonQuery();
Label1.Text = "You have successfully registered";
}
catch (Exception ex)
{
Label1.Text = "Exception in DBHandler" + ex;
}
finally
{
myConnection.Close();
}
}
This is the error I get, again sorry for the long error message:
Exception in DBHandlerSystem.Data.SqlClient.SqlException (0x80131904):
String or binary data would be truncated. The statement has been
terminated. at
System.Data.SqlClient.SqlConnection.OnError(SqlException exception,
Boolean breakConnection, Action1 wrapCloseInAction) at
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException
exception, Boolean breakConnection, Action1 wrapCloseInAction) at
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject
stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,
SqlCommand cmdHandler, SqlDataReader dataStream,
BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject
stateObj, Boolean& dataReady) at
System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String
methodName, Boolean async, Int32 timeout, Boolean asyncWrite) at
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1
completion, String methodName, Boolean sendToPipe, Int32 timeout,
Boolean asyncWrite) at
System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at
OnlineExamCW.Register.registerBtn_Click(Object sender, EventArgs e) in
f:\COMP1551 - Application and Web
Development\OnlineExamCW\OnlineExamCW\Register.aspx.cs:line 31
ClientConnectionId:e08ebbe3-d4be-4a76-a64d-14aadb6e9d4c
Please tell me what this error means. Many thanks.

The error message tells you that something in your input values is too long to be stored in the designated column. Without knowing the size of your columns is difficult to propose a correct solution so, assuming that you have reasonable limits in the database fields like in this hypotethical schema:
First_Name nvarchar(50)
Surname nvarchar(50)
User_ID int
Password nvarchar(16)
then you should limit the max length of your input fields to the same sizes allowed by the datatable fields.
<asp:TextBox ID="fNameTxt" MaxLength="50" Text="" runat="server"/>
.....
and then create your insert command using this approach
protected void registerBtn_Click(object sender, EventArgs e)
{
String conString = "....";
string cmd = #"INSERT INTO Student( First_Name, Surname, User_ID, Password)
VALUES (#first, #surname, #id, #password);"
using(SqlConnection myConnection = new SqlConnection(conString))
using(SqlCommand myCommand = new SqlCommand(cmd, myConnection))
{
myCommand.Parameters.Add(new SqlParameter()
{
ParameterName = "#first",
Value= fNameTxt.Text,
SqlDbType = SqlDbType.NVarChar,
Size = 50
});
myCommand.Parameters.Add(new SqlParameter
{
ParameterName = "#surname",
Value= sNameTxt.Text,
SqlDbType = SqlDbType.NVarChar,
Size = 50
});
myCommand.Parameters.Add(new SqlParameter()
{
ParameterName = "#id",
Value= Convert.ToInt32(userIdTxt.Text),
SqlDbType = SqlDbType.Int
});
myCommand.Parameters.Add(new SqlParameter()
{
ParameterName = "#password",
Value= passwordTxt.Text,
SqlDbType = SqlDbType.NVarChar,
Size = 16
});
myCommand.Connection = myConnection;
myConnection.Open();
if(myCommand.ExecuteNonQuery() > 0)
Label1.Text = "You have successfully registered";
}
}
Notice that in this code I have totally removed the string concatenation approach. This is a very dangerous mode to write sql statements because you could be easily hacked using the Sql Injection technique and your code could fail if someone enters a single quote in the input values (Try for example for a surname like O'Reilly)
There is another point that need a deep redesign. Storing passwords in clear text is considered a very bad practice because a simple look at your database table could reveal the passwords of all your students. But this is a more complex matter. If you are interested search about Password Hashing

It means the data in one or more fields that you are inserting in Student table has more characters than the field allows. Check the length of all fields -First_Name, Surname, User_ID, Password. Either increase the field length in the database or put a limit on data entry page so that the user isn't allowed to enter more than allowed characters in each field.

Related

TSQL create a stored procedure using c#

I am trying to create a procedure(drop a procedure and remake it with new data) in my .net project. When I run the same query in Database "Create New Query" it works fine, but when I try to run it in c#, it gives me an error.
private void makeprocedure()
{
string sqlProcedureCreate = #"
IF(OBJECT_ID('usp_HourData') IS NOT NULL)
DROP PROCEDURE IF EXISTS usp_HourData;
GO
CREATE PROCEDURE usp_HourData
AS
BEGIN
SELECT Employee.[First Name] + ' ' + Employee.[Last Name] AS 'Name',
sum(Time.[Total Hours]) AS 'Total Hours'
, FORMAT(Time.[Time in], 'd', 'en-gb') AS 'Worked On'
FROM Employee
inner join Time on
Employee.ID ='" + getID() + "' and Time.EmployeeIdFK = '" + getID()
+ "' WHERE Time.[Time in] between '" + CalendarStart.SelectedDate + "' and '" + CalendarEnd.SelectedDate
+ #"'GROUP BY FORMAT(Time.[Time in], 'd', 'en-gb') ,Employee.[First Name] + ' ' +Employee.[Last Name];
END
";
using (SqlCommand command = new SqlCommand(sqlProcedureCreate, con))
{
command.CommandType = CommandType.Text; //I tried command.CommandType = CommandType.StoredProcedure;
con.Open();
command.ExecuteNonQuery(); //Compiler says error is on this line
con.Close();
}
}
The error is near "GO" and "CREATE/ALTER PROCEDURE" must go first.
System.Data.SqlClient.SqlException was unhandled by user code
Class=15
ErrorCode=-2146232060
HResult=-2146232060
LineNumber=4
Message=Incorrect syntax near 'GO'.
'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.
Number=102
Procedure=""
Server=(LocalDB)\MSSQLLocalDB
Source=.Net SqlClient Data Provider
State=1
StackTrace:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at WebApplication2.Manager.makeprocedure() in D:\Users\Albin\MyClockIn\WebApplication2\WebApplication2\Manager.aspx.cs:line 209
at WebApplication2.Manager.ButtonSearch_Click(Object sender, EventArgs e) in D:\Users\Albin\MyClockIn\WebApplication2\WebApplication2\Manager.aspx.cs:line 161
at System.Web.UI.WebControls.Button.OnClick(EventArgs e)
at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
InnerException:
How would I go about this error?
This may not be the answer to your question but just an advice about your programming style. These are bad things in your code:
You are concatenating query string. You should use parameters.
You are creating a procedure where query contains data not the parameters. Stored procedure should contain query with parameters and you should pass data to it.
Stored procedures are not supposed to be dropped and recreated each time you access them. I can clearly see you can achieve the same result by just using the select statement. If you are creating stored procedures there must be some data to pass otherwise there is no point in making a stored procedure.
Enough theory, Let's see things in action:
Here is your MakeProcedure (please rename this) Function:
//Rename this function to some useful name
private void makeprocedure()
{
string query = #" SELECT Employee.[First Name] + ' ' + Employee.[Last Name] AS 'Name',
sum(Time.[Total Hours]) AS 'Total Hours'
, FORMAT(Time.[Time in], 'd', 'en-gb') AS 'Worked On'
FROM Employee
inner join Time on
Employee.ID = #EmpId and Time.EmployeeIdFK = #EmpId WHERE Time.[Time in]
between #StartDate and #EndDate GROUP BY FORMAT(Time.[Time in], 'd', 'en-gb'),
Employee.[First Name] + ' ' +Employee.[Last Name];";
using (SqlCommand command = new SqlCommand(query, con))
{
command.CommandType = CommandType.Text;
command.Parameters.AddWithValue("#EmpId", getID());
command.Parameters.AddWithValue("#StartDate", CalendarStart.SelectedDate);
command.Parameters.AddWithValue("#EndDate", CalendarEnd.SelectedDate);
con.Open();
var reader = command.ExecuteReader();
//do something with data in the reader.
con.Close();
}
}

how to use c# variables in sql commands

This is what I want to use;
string insertQuery = #"insert into userinfo (UserName, FirstName, LastName,
E-mail, Password, Country)
values ( '" + uname + "', '" + fname +
"','" + lname + "', '" + email + "')";
where every one of the variables in between the + are string variables with values in them. but when I run this command, I get some incorrect syntax error.
This is the new error i get;
errorSystem.Data.SqlClient.SqlException (0x80131904): String or binary
data would be truncated. The statement has been terminated. at
System.Data.SqlClient.SqlConnection.OnError(SqlException exception,
Boolean breakConnection, Action1 wrapCloseInAction) at
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException
exception, Boolean breakConnection, Action1 wrapCloseInAction) at
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject
stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,
SqlCommand cmdHandler, SqlDataReader dataStream,
BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject
stateObj, Boolean& dataReady) 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, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader
ds) at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method, TaskCompletionSource1 completion, Int32 timeout, Task& task,
Boolean asyncWrite) at
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource1
completion, String methodName, Boolean sendToPipe, Int32 timeout,
Boolean asyncWrite) at
System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at
Registration.RegistrationPage.Button1_Click1(Object sender, EventArgs
e) in c:\Users\kristhnen.jagambrum\Documents\Visual Studio
2012\Projects\Registration\Registration\RegistrationPage.aspx.cs:line
50 ClientConnectionId:6d959e49-5b62-43be-b202-76f7eb1fbd2c
It's very good that you asked - the code that you show is a perfect illustration of two security issues in a single line:
The table structure is an illustration of what lets hackers steal user passwords.
The C# code is what makes SQL injection attacks possible.
Fixing the first problem is hard: you need to learn about password hashing and how to store user info in DB. Here is a Q&A that will help: Best way to store passwords in DB
The second problem is easier - all you need is replacing the injected values with parameter names, and then adding the values for each parameter name:
... // Create SQL command, then set its text
command.CommandTest = #"INSERT INTO userinfo (
UserName, FirstName, LastName, E-mail, Password_hash, Password_salt, Country
) VALUES ( #uname, #fname, #lname, #email, #pwd_hash, #pwd_salt, #country)";
// Bind the parameters
command.Parameters.Add(new SqlParameter("#uname", uname));
command.Parameters.Add(new SqlParameter("#fname", fname));
... // ...and so on
command.ExecuteNonQuery();
The answer is you don't, because it is a bad idea. You should be using SQlCommand instead
Check This out,and there are plenty of examples of how to use it. Appending variables in the way you doing is considered to be the mistake number 3 in the list of 25 most dangerous programming mistakes.
Try something like this, and not use direct parameter in sql command
public const string InsertStmtUsersTable = "insert into userinfo (UserName, FirstName, LastName,
[E-mail], Password, Country) values (#UserName, #FirstName, #LastName,
#[E-mail], #Password, #Country) "
using(SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (SqlCommand command = new SqlCommand(InsertStmtUsersTable, conn))
{
command.CommandType = CommandType.Text;
command.Parameters.Add(new SqlParameter("username", userNameString));
command.Parameters.Add(new SqlParameter("FirstName", FirstNameString));
// Rest of your Parameters here
command.ExecuteNonQuery();
}
}

Error in Inserting data in SQL table

I am trying to insert data in a table (say feedback) with columns from(int) and Message(Varchar(MAX)) via c# code but it is continuously annoying me with errors. Please help, I am desperate.
Table description:
From int,Message Varchar(max)
Code I'm using:
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["SampleConnectionString"].ConnectionString);
con.open;
string query="insert into Feedback (From,Message) values(#frm,#msg)";
SqlCommand comm = new SqlCommand(query, con);
comm.Parameters.AddWithValue("#frm", Convert.ToInt32(TextBoxid.Text));
comm.Parameters.AddWithValue("#msg",TextBoxFeedBack.text);
comm.ExecuteNonQuery();
con.Close();
The Error I'm getting is
System.Data.SqlClient.SqlException (0x80131904): Incorrect syntax near
the keyword 'From'. 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() 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
_Default.Button1_Click(Object sender, EventArgs e) in c:\Users\Ajaz\Documents\Visual Studio
2010\WebSites\WebSite26\Default.aspx.cs:line 29
I'm guessing there's error related to data mismatch. Please help.
Thanks
FROM is a reserved keyword in TSQL. You should use it with square brackets like [FROM]
string query="insert into Feedback ([From],Message) values(#frm,#msg)";
As a general recomendation, don't use reserved keywords for your identifiers and object names in your database.
Also use using statement to dispose your SqlConnection like;
string query = "insert into Feedback ([From],Message) values(#frm,#msg)";
using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["SampleConnectionString"].ConnectionString))
{
SqlCommand comm = new SqlCommand(query, con);
comm.Parameters.AddWithValue("#frm", Convert.ToInt32(TextBoxid.Text));
comm.Parameters.AddWithValue("#msg",TextBoxFeedBack.text);
con.Open();
comm.ExecuteNonQuery();
con.Close();
}
"From" is the reserved word. Surround it by square brackets:
string query="insert into Feedback ([From],Message) values(#frm,#msg)";
Well, the word FROM is a well known keyword in any SQL language existing in the world. If you want to use it (very bad move) then you need to encapsulate it in square brackets
string query="insert into Feedback ([From],Message) values(#frm,#msg)";
Again, don't do that, change the name of the column before having to much code to change.
Otherwise you will have this problem for the lifetime of your app.

SQL Server: invalid object name in query execution

I'm trying to execute an Insert statement, but keep getting a Invalid object name error.
Here's my code:
public string addNewComment(int userID, int pageID, string title, string comment)
{
string query = "INSERT INTO dbo.nokernok_kommentarer (userID, pageID, commentTitle, comment) " +
"VALUES ("+ userID +", "+ pageID +", '"+ title +"', '"+ comment +"')";
adapter.InsertCommand = new SqlCommand(query, connection);
//ExecuteNonQuery retuens number of rows affected
int numRows = adapter.InsertCommand.ExecuteNonQuery();
return numRows.ToString();
}
And here is my error message:
System.Data.SqlClient.SqlException:
Invalid object name
'dbo.nokernok_kommentarer'. 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.RunExecuteNonQueryTds(String
methodName, Boolean async) at
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult
result, String methodName, Boolean
sendToPipe) at
System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at
development.DAL.nokernokDAL.addNewComment(Int32
userID, Int32 pageID, String title,
String comment) in
C:\Inetpub\wwwroot\naaf\DAL\nokernok.cs:line
49
Can anyone help me figure out why I get this error?
UPDATE
I should be using the correct database, because the following query works:
public DataSet getSchools(string countyCode)
{
DataSet ds = new DataSet();
string query = "SELECT * FROM nokernok_skoler WHERE kommunekode LIKE '" + countyCode.Substring(0, 2) + "%' ORDER BY enhetsnavn";
adapter.SelectCommand = new SqlCommand(query, connection);
adapter.Fill(ds);
return ds;
}
My connection string looks like this:
SqlConnection connection = new SqlConnection();
SqlDataAdapter adapter = new SqlDataAdapter();
// class constructor
public nokernokDAL()
{
connection.ConnectionString = EPiServer.Global.EPConfig["EPsConnection"].ToString();
connection.Open();
}
You're probably in the wrong database. Include an initial catalog in your connection string:
Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername; ...
^^^^^^^^^^^^^^^^^^^^^^^^^^
Or specify a three part name:
INSERT INTO myDataBase.dbo.nokernok_kommentarer
^^^^^^^^^^
From the error message, it would appear that the table dbo.nokernok_kommentarer doesn't exist in your database, or it isn't a table and is thus not updatable.
Have you checked that:
You're connecting to the server you think you're connecting to?
You're connecting to the database you think you're connecting to?
You're specifiying the correct catalog (or whatever it's currently called =) i.e. Are you sure it should be dbo. and not somethingElse.?
The table dbo.nokernok_kommentarer exists?
If you copy the SQL out from your code and run it in something like SQL Server Management Studio, does it work without error there?

Conversion failed when converting datetime from character string

I am developing a C# VS 2008 / SQL Server 2005 Express website application. I have tried some of the fixes for this problem but my call stack differs from others. And these fixes did not fix my problem. What steps can I take to troubleshoot this?
Here is my error:
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
And here is the related code. When I debugged this code, "dic" only looped through the 3 column names, but did not look into row values which are stored in "dt", the Data Table.
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!";
}
}
}
Here is my SQL stored proc:
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
The input file has 3 columns. The first two are varchars, but the 3rd one is also varchar I think, but it's represented as "3/11/2010". In this input file, a sample row looks like:
"Benjamin|breakfast|3/11/2010".
And I am trying to convert this date field from a string to a datetime here in my SP. Am I going about it the wrong way?
DataRow:
col1|col2|col3
11|A2|1/10/1978
12|b2|2/10/1978
13|c2|3/10/1978
14|d2|4/10/1978
I think Belousov Pavel is correct. Inside your foreach you assign each dictionary item as a parameter. Each of those parameters are defined as being VarChar. With the information provided it is logical to assume the problem is in the stored procedure.
Can you either post the code of the stored procedure or try and recreate the error inside SQL Management Studio by executing the stored procedure there.
UPDATE...
After looking at your stored procedure the code looks correct. I was able to generate the error message you are getting using the following sql code.
declare #col3 varchar(50)
set #col3 = '|3/11/2010'
declare #temp datetime
set #temp = (select convert(datetime,#col3))
Note that the value of #col3 starts with a pipe character. If you remove the pipe character it works correctly.
I would look closer at the values in the dictionary you are getting you parameter values from. There may be an issue with the way you parsed the data.
UPDATE 2
The code below is not confirmed to work but I think I see what you are trying to do. I assume the DataTable you are passing in has data like this:
col1|col2|col3
11|A2|1/10/1978
12|b2|2/10/1978
13|c2|3/10/1978
14|d2|4/10/1978
If this is the case we don't need the dictionary that was passed in originally. I can also assume that you want the stored procedure to be executed once for each row in the DataTable. The below method is similar to what you where doing although it runs the stored procedure for each row.
What I am not sure from you explanation is if the first row of the DataTable contains the names of the columns, if not no worries then. Hope this makes sense, leave more comments if you have questions.
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;
}
Well, if you do this:
SqlParameter p = cmd.Parameters.AddWithValue(s, dic[s]);
p.SqlDbType = SqlDbType.VarChar;
all your parameters will be of type VARCHAR. This might sound smart at first - it's not.
If you pass dates as varchar, you start getting into the messy business of date/time string formats - unless you always use the ISO-8601 format YYYYMMDD which works on any SQL Server installation, and with any locale / language / date setting. Anything else becomes a gamble. Not the whole world uses the MM/DD/YYYY format as in the US, and depending on your SQL Server's language or date format settings, your date might not be recognized, or even misinterpreted. Just don't do it - it's a mess.
Plus, really - if you have a date/time in your C# code - I would strongly recommend you pass that as a SqlDbType.DateTime to your SQL Server stored proc. You're just gonna save yourself endless hours of debugging and messy conversions and stuf.......
Problem is in stored procedure, I think. May be one of input parameters is DateTime, but you wrote VarChar to this parameter.
UPDATE:
As I can see you don't use DataTable dt in your method AppendDataCT.
You wrote that dic contains values [0]:[col1, col1] [1]:[col2, col2] [2]:[col3, col3]. But it's wrong values... your code is
SqlParameter p = cmd.Parameters.AddWithValue(s, dic[s]);
Then you send to col3 value = col3, as I understand.
May be you wanted to write
SqlParameter p = cmd.Parameters.AddWithValue(s, dt[s]);
or something like this...
You need to loop through the rows of the DataTable to get the data - you're adding the values of dic (your column names for month, day, year??) as SqlParameters..... This is what I'm assuming because the question is pretty scattered....
Note: Not completely functioning code -
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;
}
UPDATE: You will need to handle your own data validation - otherwise, here you go
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();
}
}
In my case I had my INSERT query's values in the wrong order:
INSERT INTO my_table(
status --varchar
, created_on --datetime2
) VALUES (
#created_on --datetime2
, #status --varchar
)

Categories

Resources