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();
}
}
Related
Error is
The type of column 'MemberHId' is not supported. The type is 'SqlHierarchyId'.
In both the server the datatype is same "HierarchyId".
I am just using the ADO.Net.
The assembly is Microsoft.SqlServer.ManagedDTS version- 13.0.0.0
We are using Azure Sql.
Tried with different versions of sql assemblies
DataTable dt = new DataTable();
dt.Columns.Add("Code", typeof(string));
dt.Columns.Add("Description", typeof(string));
dt.Columns.Add("NodeId", typeof(int));
dt.Columns.Add("MemberHId", typeof(SqlHierarchyId));
dt.Columns.Add("Level", typeof(int));
//Getting the data from serverAPI which is returning the data in the columns without null records.
dt=apicall();
SqlParameter returnParameter = cmd.Parameters.Add("RetVal", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.ReturnValue;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = spName;
cmd.Parameters.AddWithValue("#MemberH", dt);
cmd.CommandTimeout = 0;
cmd.Connection.Open();
cmd.ExecuteNonQuery();// Its failing here
My Sp consists of table type param #MemberHType and the procedure returns rows with these columns:
Name | Type
------------+----------
Code | varchar
Description | varchar
NodeID | smallint
MemberHId | hierarchyid
Level | smallint
This is the procedure:
alter PROCEDURE [dbo].[InsertHierarchyData]
(
#MemberHType MemberH READONLY
)
AS
truncate table test
BEGIN TRY
insert into test values ('start select')
--create table test (errormessage varchar(1000))
IF EXISTS (SELECT TOP 1 1 FROM #MemberHType)
BEGIN
insert into test values ('Inside first Insert start')
INSERT INTO HierarchyStaging
(
Code
,[Description]
,NodeID
,MemberhHId
,[Level]
)
SELECT
Code
,[Description]
,NodeId
,MemberhHId
,[Level]
FROM #MemberHType
insert into test values ('Inside first Insert end')
END
END TRY
BEGIN CATCH
SELECT #comment = ERROR_MESSAGE()
,#Status = 'Error'
SET #comment = CONVERT(NVARCHAR(3000),#Comment) + ' Error Severity: ' + CAST(ERROR_SEVERITY() AS varchar(25)) + ' Error state: 30'
GOTO ErrorHandler
END CATCH
The Column in c# is SqlHierarchyId.
Stack-trace:
at System.Data.SqlClient.TdsParser.TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc, Boolean sync, TaskCompletionSource`1 completion, Int32 startRpc, Int32 startParam)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
If I understand the documentation correctly, you can't use SqlHierarchyId as the data type of a DataColumn.
It doesn't appear in the System.Data.SqlTypes Namespace, and it also doesn't appear in the SQL Server Data Type Mappings table, which means there's no documented built in conversion between SQL Server's HierarchyId and a built in type in the .Net framework. (of course, undocumented features have been known to exist in SQL Server, but I wouldn't recommend relying on that).
What you can do, however, is to convert the HierarchyId to nvarchar using a simple cast in T-SQL when you read it into your c# application (which internally is calling the ToString() method):
CAST(MemberhHId AS nvarchar(4000)) as MemberHId
and convert it back using cast when you insert the data (which internally is calling the Parse() method):
CAST(MemberHId AS hierarchyid)
I have a C# code which throws me a SQLException with message Error Converting data type varchar to int. Funny thing is I dont have any conversion or INT variables in my code. My stored procedure works fine on its own via SSMS.
Here is the C# bit
string[] envData = new string[4];
string dbCon = "";
dbCon = "Database=" + "TestData";
dbCon = dbCon + ";Server=" + "DEV";
dbCon = dbCon + ";Trusted_Connection=Yes;";
using (SqlConnection Con = new SqlConnection(dbCon))
{
Con.Open();
//using (SqlTransaction tr = Con.BeginTransaction("GetEnvironmentInfo"))
//{
string spEnvironmentInfo = #"ELog.GetEnvironmentInfo";
SqlCommand cmd = new SqlCommand(spEnvironmentInfo, Con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#oElogBaseDir", DbType.String));
cmd.Parameters["#oElogBaseDir"].Direction = ParameterDirection.Output;
cmd.Parameters.Add(new SqlParameter("#oElogFinancialMonthDir", DbType.String));
cmd.Parameters["#oElogFinancialMonthDir"].Direction = ParameterDirection.Output;
cmd.Parameters.Add(new SqlParameter("#oElogFinancialYear", DbType.String));
cmd.Parameters["#oElogFinancialYear"].Direction = ParameterDirection.Output;
cmd.Parameters.Add(new SqlParameter("#oElogEmailAccount", DbType.String));
cmd.Parameters["#oElogEmailAccount"].Direction = ParameterDirection.Output;
try
{
cmd.ExecuteNonQuery();
envData[0] = cmd.Parameters["#oElogBaseDir"].Value.ToString();
envData[1] = cmd.Parameters["#oElogFinancialMonthDir"].Value.ToString();
envData[2] = cmd.Parameters["#oElogFinancialYear"].Value.ToString();
envData[3] = cmd.Parameters["#oElogEmailAccount"].Value.ToString();
//tr.Commit();
}
catch (System.Exception ex)
{
//tr.Rollback("GetEnvironmentInfo");
throw ex;
//return null;
}
//}
}
Response.Write(envData[0].ToString());
Response.Write(envData[1].ToString());
Response.Write(envData[2].ToString());
Response.Write(envData[3].ToString());
and here is the sql part
ALTER PROCEDURE [ELog].[GetEnvironmentInfo]
#oELogBaseDir VARCHAR(MAX) OUTPUT,
#oELogFinancialMonthDir VARCHAR(MAX) OUTPUT,
#oELogFinancialYear VARCHAR(MAX) OUTPUT,
#oElogEmailAccount VARCHAR(MAX) OUTPUT
AS
BEGIN
SELECT
#oELogBaseDir = e.ELogBaseDir,
#oELogFinancialMonthDir = e.ELogFinancialMonthDir,
#oELogFinancialYear = e.ELogFinancialYear,
#oElogEmailAccount = e.ElogEmailAccount
FROM SSISMeta.Environment e
WHERE e.SQLServerInstance = ##SERVERNAME
END
Here is the stack trace
[SqlException (0x80131904): Error converting data type varchar to int.]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +2442126
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +5736904
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +628
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +3731
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +225
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds, Boolean describeParameterEncryptionRequest) +2026
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite) +375
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite) +337
System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +280
WebTest_Replacement_OutlookVB.Test_Home.btnReadEmail_Click(Object sender, EventArgs e) in \\LocalDev\Random\WebTest_Replacement_OutlookVB\Test_Home.aspx.cs:70
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +9692746
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +108
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +12
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +15
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +35
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3562
Table schema
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
SET ANSI_PADDING ON
GO
CREATE TABLE [SSISMeta].[Environment] (
[SK_EnvironmentID] [smallint] IDENTITY(1, 1) NOT NULL,
[IsProduction] [bit] NOT NULL,
[SQLServerInstance] [varchar](100) COLLATE Latin1_General_CI_AS NOT NULL,
[BaseDirPath] [varchar](4000) COLLATE Latin1_General_CI_AS NOT NULL,
[CreatedTimeStamp] [datetime] NOT NULL,
[LastUpdatedTimeStamp] [datetime] NOT NULL,
[ModifiedBYUser] [varchar](100) COLLATE Latin1_General_CI_AS NOT NULL,
[SharedBaseDir] [varchar](4000) COLLATE Latin1_General_CI_AS NOT NULL,
[SharedT2ODir] [varchar](4000) COLLATE Latin1_General_CI_AS NULL,
[ELogBaseDir] [varchar](4000) COLLATE Latin1_General_CI_AS NOT NULL,
[ELogFinancialMonthDir] [varchar](250) COLLATE Latin1_General_CI_AS NOT NULL,
[ELogFinancialYear] [varchar](250) COLLATE Latin1_General_CI_AS NOT NULL,
[ElogEmailAccount] [varchar](250) COLLATE Latin1_General_CI_AS NOT NULL,
CONSTRAINT [PK_Environment]
PRIMARY KEY
CLUSTERED
([SK_EnvironmentID])
ON [SSISMeta_Data_Fg]
) ON [SSISMeta_Data_Fg]
GO
ALTER TABLE [SSISMeta].[Environment]
ADD
CONSTRAINT [DF_Environment_CreatedTimestamp]
DEFAULT (getdate()) FOR [CreatedTimeStamp]
GO
ALTER TABLE [SSISMeta].[Environment]
ADD
CONSTRAINT [DF_Environment_LastUpdatedTimestamp]
DEFAULT (getdate()) FOR [LastUpdatedTimeStamp]
GO
ALTER TABLE [SSISMeta].[Environment]
ADD
CONSTRAINT [DF_Environment_ModifiedByUser]
DEFAULT (suser_sname()) FOR [ModifiedBYUser]
GO
ALTER TABLE [SSISMeta].[Environment] SET (LOCK_ESCALATION = TABLE)
GO
I knew it was going to be something silly, I need to use SqlDbType not DbType.
Works fine now
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.
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();
}
}
I'm writing a project in C# where i use ADO.NET to connect to my SQL Server 2012 database. My database (among other things ) has two columns. the first column represent latitude of a point and the second one represents the longitude. I use a procedure that check if two rectangles on the map intercept each the other. The column reply returns 1 value that is either 0 or 1.
edit: in this example i run it only with numbers, i plan to add variables later
my procedure works fine if i run it on SQL query. But drops error if i run using ADO.net
as SQL query procedure is :
DECLARE #g geography;
DECLARE #h geography;
DECLARE #s geography;
SET #g = geography::STGeomFromText('POLYGON((39.692 23.483, 23.483 39.671, 24.095 39.493, 23.466 39.800,39.692 23.483))', 4326);
SET #h = geography::STGeomFromText('POLYGON((39.800096 23.296509, 39.628961 23.128967,39.43195 23.510742 ,39.7093 23.859558,39.800096 23.296509))', 4326);
SET #h =#h.MakeValid();
SET #g = #g.MakeValid();
SELECT #g.STIntersects(#h) as reply
/*==============================================================================================================
//------------------------ AS ADO.NET procedure is : -------------------------------
SqlDataReader rdr = null;
SqlConnection conn = new SqlConnection("Data Source=AGIS-PC;Initial Catalog=ship_maps;Integrated Security=True");// create a connection object
String commandString = #"DECLARE #g geography;
DECLARE #h geography;
DECLARE #s geography;
SET #h =#h.MakeValid();
SET #g = #g.MakeValid();
SET #g = geography::STGeomFromText('POLYGON((39.692 23.483, 23.483 39.671, 24.095 39.493, 23.466 39.800,39.692 23.483))', 4326);
SET #h = geography::STGeomFromText('POLYGON((39.800096 23.296509, 39.628961 23.128967,39.43195 23.510742 ,39.7093 23.859558,39.800096 23.296509))', 4326);
SET #h =#h.MakeValid();
SET #g = #g.MakeValid();
SELECT #g.STIntersects(#h) as reply";
SqlCommand cmd = new SqlCommand(commandString, conn);
try
{
// open the connection
conn.Open();
// 1. get an instance of the SqlDataReader
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
// get the results of each column
string vessel_name = (string)rdr["reply"];
TextBox1.Text += " " + vessel_name;
// .....
}//while
}
finally
{
//...........
}
//=========================================================
he error is something with makevalid() i guess. I had similar error in the initial query at sql , then i insert makevalid() and it worked.
edit : it occurs at rdr = cmd.ExecuteReader();
Stack Trace:
[SqlException (0x80131904): A .NET Framework error occurred during execution of user-defined routine or aggregate "geography":
System.ArgumentException: 24200: The specified input does not represent a valid geography instance. Use MakeValid to convert the instance to a valid instance. Note that MakeValid may cause the points of a spatial instance to shift slightly.
System.ArgumentException:
at Microsoft.SqlServer.Types.SqlGeography..ctor(GeoData g, Int32 srid)
at Microsoft.SqlServer.Types.SqlGeography.GeographyFromText(OpenGisType type, SqlChars taggedText, Int32 srid)
.
A .NET Framework error occurred during execution of user-defined routine or aggregate "geography":
Microsoft.SqlServer.Types.GLArgumentException: 24205: The specified input does not represent a valid geography instance because it exceeds a single hemisphere. Each geography instance must fit inside a single hemisphere. A common reason for this error is that a polygon has the wrong ring orientation. To create a larger than hemisphere geography instance, upgrade the version of SQL Server and change the database compatibility level to at least 110.
Microsoft.SqlServer.Types.GLArgumentException:
at Microsoft.SqlServer.Types.GLNativeMethods.GeodeticIsValid(GeoData& g, Double eccentricity, Boolean forceKatmai)
at Microsoft.SqlServer.Types.SqlGeography.IsValidExpensive(Boolean forceKatmai)
at Microsoft.SqlServer.Types.SqlGeography..ctor(GeoData g, Int32 srid)
at Microsoft.SqlServer.Types.SqlGeography.GeographyFromText(OpenGisType type, SqlChars taggedText, Int32 srid)
.]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +2084358
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +5096328
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +234
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +2294
System.Data.SqlClient.SqlDataReader.ConsumeMetaData() +33
System.Data.SqlClient.SqlDataReader.get_MetaData() +86
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +311
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +987
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +162
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +141
System.Data.SqlClient.SqlCommand.ExecuteReader() +89
gmaps.Button11_Click(Object sender, EventArgs e) +185
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +118
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +112
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5563
please advise, or if this is for another topic tell me. I'm a beginner with SQL
There are many issues with your code....
1.) You're calling MakeValid() on #g and #h when they are uninitialised variables:
DECLARE #g geography;
DECLARE #h geography;
SET #h = #h.MakeValid();
SET #g = #g.MakeValid();
2.) What is #s for? It's never used...
3.) #g is an invalid, self-intersecting polygon. The appropriate valid instance to represent this pointset is MULTIPOLYGON (((23.483 39.671, 39.692 23.483, 23.721 39.602, 23.483 39.671)), ((23.466 39.8, 23.721 39.602, 24.095 39.493, 23.466 39.8)))
4.) #h has the incorrect ring orientation (that is, assuming that you're not trying to create a Polygon that covers 99% of the earth's surface). It should be POLYGON((39.43195 23.510742, 39.628961 23.128967, 39.800096 23.296509, 39.7093 23.859558, 39.43195 23.510742))
So, your SQL query should be:
DECLARE #g geography;
DECLARE #h geography;
SET #g = geography::STGeomFromText('MULTIPOLYGON (((23.483 39.671, 39.692 23.483, 23.721 39.602, 23.483 39.671)), ((23.466 39.8, 23.721 39.602, 24.095 39.493, 23.466 39.8)))', 4326);
SET #h = geography::STGeomFromText('POLYGON((39.43195 23.510742, 39.628961 23.128967, 39.800096 23.296509, 39.7093 23.859558, 39.43195 23.510742))', 4326);
SELECT #g.STIntersects(#h) as reply;
Which gives the result '1', as represented in SQL Server Spatial Results tab shown below:
Pro Spatial with SQL Server 2012