MySQL / ASP.NET Stored Procedures - asp.net

Hopefully this is not a ServerFault question...
I'm working forward on migrating a project from storing data in XML Serialization to a MySQL database. I'm using the example provided me from a previous question answered yesterday.
Connecting using phpMyAdmin and MySQL Workbench I've created a Stored Procedure called 'sprocOrderSelectSingleItem'. It seems to work well with MySQL for all I can tell. When I run the SHOW CREATE PROCEDURE sprocOrderSelectSingleItem it returns the following:
CREATE DEFINER=username#% PROCEDURE sprocOrderSelectSingleItem(IN orderID INTEGER)
BEGIN SELECT * FROM tblOrders WHERE ID=orderID; END
My cooperative ASP.NET code goes something like this:
public static Order GetItem(int ID)
{
Order objOrder = null;
using (OdbcConnection objConnection = new OdbcConnection(Utils.ApplicationConfiguration.ConnectionString))
{
OdbcCommand objCommand = new OdbcCommand("sprocOrderSelectSingleItem", objConnection);
objCommand.CommandType = CommandType.StoredProcedure;
objCommand.Parameters.AddWithValue("orderID", ID);
objConnection.Open();
using (OdbcDataReader objReader = objCommand.ExecuteReader())
{
if (objReader.Read())
{
objOrder = FillDataRecord(objReader);
}
objReader.Close();
}
objConnection.Close();
}
return objOrder;
}
When I view the page I get the following error message:
ERROR [42000] [MySQL][ODBC 5.1 Driver][mysqld-5.0.77]You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'sprocOrderSelectSingleItem' at line 1
Really not catching on to what could be missing or going wrong. Are there any additional tests I should/could be running to confirm things are working on the MySQL side? Am I missing a step to pass the Stored Procedure call correctly in ASP.NET? The code breaks at the line of:
using (OdbcDataReader objReader = objCommand.ExecuteReader())
Replacing the line of
OdbcCommand objCommand = new OdbcCommand("sprocOrderSelectSingleItem", objConnection);
with this instead
OdbcCommand objCommand = new OdbcCommand("SELECT * FROM tblOrders WHERE ID=" + ID + ";", objConnection);
and everything works as expected.
Thanks for any help you guys can provide.

Your can run an execute on sprocOrderSelectSingleItem in Mysql directly with the ID parameter.
It will show that your StoredProc run correctly.
Here is a sample code in C# that call a stored proc.
OdbcCommand salesCMD = new OdbcCommand("{ CALL SalesByCategory(?) }", nwindConn);
salesCMD.CommandType = CommandType.StoredProcedure;
OdbcParameter myParm = salesCMD.Parameters.Add("#CategoryName", OdbcType.VarChar, 15);
myParm.Value = "Beverages";
OdbcDataReader myReader = salesCMD.ExecuteReader();
Look at the "Call" in the OdbcCommand and the "?" for the parameter that is later supplied with a value.

Can you try something like below:
OdbcCommand cmd = new OdbcCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "{call LoadCustCliOrders(?,?,?,?)}";
cmd.Parameters.Add("CUST_ID",OdbcType.Int);
cmd.Parameters.Add("CLIENT_ID",OdbcType.Int);
cmd.Parameters.Add("DATE_FROM",OdbcType.Date);
cmd.Parameters.Add("DATE_TO",OdbcType.Date);
...
cmd.Parameters["CUST_ID"].Value = _CustId;
cmd.Parameters["CLIENT_ID"].Value = _ClientId;
cmd.Parameters["DATE_FROM"].Value = _DateFrom;
cmd.Parameters["DATE_TO"].Value = _DateTo;
cmd.ExecuteReader

Are you sure that you are using the same username or user with the same access privileges.
I think you need to add the word "CALL" before the stored proc.
It should be CALL sprocOrderSelectSingleItem and try.

Related

Can't Update Database from ASP.NET Webform

I can't get an ASP.NET webform to update a database. I'm trying to edit an existing record in the database. The webform populates the data from the record into the form. The user then changes data and updates the record in the database when the form is submitted.
The problem is that nothing is changed in the database when a modified form is submitted. What am I doing wrong here? The SQL works in MSSQL Management Studio.
Thanks.
private void SaveToDatabase ()
{
using (SqlConnection conn = new SqlConnection (_connectionString_Bluebook))
{
conn.Open ();
string sql = #"update Companies
set CompanyName=#CompanyName, AccountNo=#AccountNo
where AccountNo=" + _accountNo;
using (SqlCommand command = new SqlCommand (sql, conn))
{
command.Parameters.Add (new SqlParameter ("#CompanyName", TextBox_CompanyName.Text));
command.Parameters.Add (new SqlParameter ("#AccountNo", TextBox_Account.Text));
command.ExecuteNonQuery ();
}
conn.Close ();
}
}
Try adding a parameter for the original account number to your query. The example below uses strongly-typed parameters for security and performance, taking a guess at your actual SQL data types and column lengths, which you should change to your actual definitions.
private void SaveToDatabase()
{
using (SqlConnection conn = new SqlConnection(_connectionString_Bluebook))
{
conn.Open();
string sql = #"update dbo.Companies
set CompanyName=#CompanyName, AccountNo=#AccountNo
where AccountNo=#OriginalAccountNo;
IF ##ROWCOUNT = 0 RAISERROR('Account number %s not found',16,1,#OriginalAccountNo)";
using (SqlCommand command = new SqlCommand(sql, conn))
{
command.Parameters.Add(new SqlParameter("#CompanyName",SqlDbType.VarChar,100).Value = TextBox_CompanyName.Text;
command.Parameters.Add(new SqlParameter("#AccountNo", SqlDbType.Char, 10).Value = TextBox_Account.Text;
command.Parameters.Add(new SqlParameter("#OriginalAccountNo", SqlDbType.Char, 10).Value = _accountNo;
command.ExecuteNonQuery();
}
}
}
If the row is still not updated as expected, make sure _accountNo contains the proper value.
EDIT:
I added a RAISERROR statement to the SQL batch to facilitate this, which you could leave in the code if the not found condition should never occur.
If the SQL Params are not working, then try this way:
comm = new SqlCommand("update student_detail set s_name= '" + txtname.Text + "', age= "+txtage.Text+" , course=' " + txtcourse.Text + "' where roll_no = " + txtrn.Text + " ", conn);
Try to place the debugger and provide the exact error of the compiler

Invalid cast exception on remote server Guid to string

I have this code in my project:
string userId = Membership.GetUser(username).ProviderUserKey.ToString();
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("UPDATE aspnet_Membership SET IsLockedOut = 0, LastLockoutDate = #LastLockedOutDate WHERE UserId = #Userid", conn);
cmd.Parameters.Add("#LastLockedOutDate", SqlDbType.DateTime).Value = DateTime.Now;
cmd.Parameters.Add("#Userid", SqlDbType.VarChar, 255).Value = userId;
int rowsAffected = 0;
conn.Open();
rowsAffected = cmd.ExecuteNonQuery();
This works fantastic on my local machine. The user gets unlocked no problem. But for some reason when I deploy it to a demo site on the remote server I get this error:
InvalidCastException: Failed to convert parameter value from a Guid to a String
It's failing on the cmd.ExecuteNonQuery line. I tried changing the parameter to a uniqueidentifier and passing the actual guid but that didn't work either.
Anybody know why this would work locally but not on a remote server? Or know of a way I can modify the code to possibly work?
Rather than trying to manually unlock the user could you not use :-
var oUser = Membership.GetUser(username);
oUser.UnlockUser();
Membership.UpdateUser(oUser);
This allows the .NET process to do all the heavy lifting for you.
[Edit to answer the original question]
Guid gUserID = (Guid)Membership.GetUser(username).ProviderUserKey;
if (gUserID != Guid.Empty)
{
using (
var oConn =
new SqlConnection(connectionString)
{
oConn.Open();
using (SqlCommand oCmd = oConn.CreateCommand())
{
oCmd.CommandType = CommandType.Text;
oCmd.CommandText = "UPDATE aspnet_Membership SET IsLockedOut = 0, LastLockoutDate = #LastLockedOutDate WHERE UserId = #gUserID";
oCmd.Parameters.Add(new SqlParameter("#gUserID", gUserID));
oCmd.Parameters.Add(new SqlParameter("#LastLockedOutDate", DateTime.UtcNow));
oCmd.ExecuteNonQuery();
}
}
}
It may also be worth changing your DateTime.Now to DateTime.UtcNow so that if you ever have to move timezones or share with other machines out of your location you are all on a equivilent time.
If you get an error thrown on the ProviderUserKey then chances are either the user doesn't exist or the UserID isn't a GUID after all.
Maybe you can try something like
cmd.Parameters.Add("#Userid", SqlDbType.Guid).Value = new Guid(userId);
Sorry for the lame answering my own question but I resolved this. I stripped the custom membership provider out and just used the default membershipUser.UnlockUser(); and it works great. The custom provider wasn't actually doing anything anyway. I think it was developed for features that aren't being used anymore.

Execute SQL stored using ado.net

I am using ado.net to access sql server I have costum Stored Procedure I am executing it using ado.net :
SqlCommand command = new SqlCommand("Custom",con);
and i am sending the parameters like this :
command.Parameters.Add(new SqlParameter("#Parm1",SqlDbType.Int,0,"Parm1"));
command.Parameters.Add(new SqlParameter("#Parm2",SqlDbType.Int,0,"Parm2"))
it dose not work and it did not give me an error as well it is the first time to work without DAL generator
Please, use this pattern:
SqlCommand command = new SqlCommand("nameOfMyStoredProcedure", mySqlConnectionObject);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#ID", SqlDbType.Int);
command.Parameters["#ID"].Value = customerID;
to make it work add this line before set the params :
command.CommandType = CommandType.StoredProcedure;
and set the params using :
command.Parameters[0].Value=4;
command.Parameters[1].Value=2;
:)

oraclehelper filldataset or another way to get SYS_REFCURSOR values at ASP.NET

To whom it may respond to,
We are developing our project using .net framework 4.0,Oracle 11gR2. The problem is that , we have to use Oraclehelper class, no other options, and we can't get SYS_REFCURSOR values . When googled ,
we have catched some pages writing about filldataset method of oraclehelper class, but this class doesn't exist in our Oraclehelper class.
Any workarounds, templates, examples etc. to get SYS_REFCURSOR values via Oraclehelper class?
Thank you for your concern,
Best Regards,
Kayhan YÜKSEL
assuming you are using the sourceforge.net/projects/oraclehelpernet "oraclehelper" it is build ontop of ODP (ie Oracle.DataAccess.Client)
all you would need to do is:
(this is from http://download.oracle.com/docs/cd/B28359_01/win.111/b28375/featRefCursor.htm)
String cmdTxt1 = "begin open :1 for select col1 from test; end;";
OracleCommand cmd = new OracleCommand(cmdTxt1, conn);
OracleParameter outRefPrm = cmd.Parameters.Add("outRefPrm",
OracleDbType.RefCursor, DBNull.Value, ParameterDirection.Output);
cmd.ExecuteNonQuery(); // Execute the anonymous PL/SQL block
You can also look in %oracle_home%\client_1\odp.net\samples\4\RefCursor for 7 examples (this is when ODP is installed that is)
Since the OracleHelper just creates a wrapper around ODP, all you need to do is create the parameter as OracleDbType.RefCursor and pass it into the call (be it an execute non-query or datareader or whatnot)
now to do this via a procedure:
PROCEDURE Get1CurOut(p_cursor1 out refCursor) is
BEGIN
OPEN p_cursor1 for select * from emp;
END Get1CurOut;
and to the C#
OracleCommand cmd = new OracleCommand("Get1CurOut", con);
cmd.CommandType = CommandType.StoredProcedure;
// Bind
OracleParameter oparam = cmd.Parameters.Add("refcursor", OracleDbType.RefCursor);
oparam.Direction = ParameterDirection.Output;
try
{
// Execute command; Have the parameters populated
cmd.ExecuteNonQuery();
// Create the OracleDataAdapter
OracleDataAdapter da = new OracleDataAdapter(cmd);
// Populate a DataSet with refcursor1.
DataSet ds = new DataSet();
da.Fill(ds, "refcursor1", (OracleRefCursor)(cmd.Parameters["refcursor1"].Value));
// Print out the field count the REF Cursor
Console.WriteLine("Field count: " + ds.Tables["refcursor1"].Columns.Count);
}
this is lifted (with slight modification) from %oracle_home%\client_1\odp.net\samples\4\RefCursor\sample1.cs
here is an (untested) OracleHelper example:
string connectionString = "User Id=scott;Password=tiger;Data Source=oracle";
CommandType commandType = CommandType.StoredProcedure;
string commandText = "Get1CurOut";
OracleParameter oparam = cmd.Parameters.Add("refcursor", OracleDbType.RefCursor);
oparam.Direction = ParameterDirection.Output;
OracleDataReader reader;
reader = OracleHelper.ExecuteReader(connectionString, commandType, commandText, oparam) ;
// show the first row
reader.Read();
// Print out SCOTT.EMP EMPNO column
Console.WriteLine("EMPNO: {0}", reader.GetDecimal(0));
// Print out SCOTT.EMP ENAME column
Console.WriteLine("ENAME: {0}", reader.GetString(1));

Preventing SQL Injection in ASP.Net

I have this code
UPDATE OPENQUERY (db,'SELECT * FROM table WHERE ref = ''"+ Ref +"'' AND bookno = ''"+ Session("number") +"'' ')
How would I prevent SQL Injections on this?
UPDATE
Here's what i'm trying
SqlCommand cmd = new SqlCommand("Select * from Table where ref=#ref", con);
cmd.Parameters.AddWithValue("#ref", 34);
For some reason everything I try and add it doesn't seem to work I keep getting SQL Command mentioned below.
The error is this
'SqlCommand' is a type and cannot be used as an expression
I'm taking over someone else's work so this is all new to me and I would like do things the right way so if anyone can provide any more help on how to make my query above safe from SQL injections then please do.
UPDATE NO 2
I added in the code as VasilP said like this
Dim dbQuery As [String] = "SELECT * FROM table WHERE ref = '" & Tools.SQLSafeString(Ref) & "' AND bookno = '" & Tools.SQLSafeString(Session("number")) & "'"
But I get an error Tools is not declared do I need to specify a certain namespace for it to work?
UPDATE
Has anyone got any ideas on the best of getting my query safe from SQL injection without the errors that i'm experiencing?
UPDATE
I now have it so it work without the parameters bit here's my updated source code any idea why it won't add the parameter value?
Dim conn As SqlConnection = New SqlConnection("server='server1'; user id='w'; password='w'; database='w'; pooling='false'")
conn.Open()
Dim query As New SqlCommand("Select * from openquery (db, 'Select * from table where investor = #investor ') ", conn)
query.Parameters.AddWithValue("#investor", 69836)
dgBookings.DataSource = query.ExecuteReader
dgBookings.DataBind()
It works like this
Dim conn As SqlConnection = New SqlConnection("server='server1'; user id='w'; password='w'; database='w'; pooling='false'")
conn.Open()
Dim query As New SqlCommand("Select * from openquery (db, 'Select * from table where investor = 69836') ", conn)
dgBookings.DataSource = query.ExecuteReader
dgBookings.DataBind()
The error i'm getting is this
An error occurred while preparing a query for execution against OLE DB provider 'MSDASQL'.
And it's because it isn't replacing the #investor with the 69836
Any ideas?
SOLUTION
Here is how I solved my problem
Dim conn As SqlConnection = New SqlConnection("server='h'; user id='w'; password='w'; database='w'; pooling='false'")
conn.Open()
Dim query As New SqlCommand("DECLARE #investor varchar(10), #sql varchar(1000) Select #investor = 69836 select #sql = 'SELECT * FROM OPENQUERY(db,''SELECT * FROM table WHERE investor = ''''' + #investor + ''''''')' EXEC(#sql)", conn)
dgBookings.DataSource = query.ExecuteReader
dgBookings.DataBind()
Now I can write queries without the worry of SQL injection
Try using a parameterized query here is a link http://www.aspnet101.com/2007/03/parameterized-queries-in-asp-net/
Also, do not use OpenQuery... use the this to run the select
SELECT * FROM db...table WHERE ref = #ref AND bookno = #bookno
More articles describing some of your options:
http://support.microsoft.com/kb/314520
What is the T-SQL syntax to connect to another SQL Server?
Edited
Note: Your original question was asking about distributed queries and Linked servers. This new statement does not reference a distributed query. I can only assume you are directly connecting to the database now. Here is an example that should work.
Here is another reference site for using SqlCommand.Parameters
SqlCommand cmd = new SqlCommand("Select * from Table where ref=#ref", con);
cmd.Parameters.Add("#ref", SqlDbType.Int);
cmd.Parameters["#ref"] = 34;
Edited:
Ok Jamie taylor I will try to answer your question again.
You are using OpenQuery becuase you are probably using a linked DB
Basically the problem is the OpenQuery Method takes a string you cannot pass a variable as part of the string you sent to OpenQuery.
You can format your query like this instead. The notation follows servername.databasename.schemaname.tablename. If you are using a linked server via odbc then omit databasename and schemaname, as illustrated below
Dim conn As SqlConnection = New SqlConnection("your SQL Connection String")
Dim cmd As SqlCommand = conn.CreateCommand()
cmd.CommandText = "Select * db...table where investor = #investor"
Dim parameter As SqlParameter = cmd.CreateParameter()
parameter.DbType = SqlDbType.Int
parameter.ParameterName = "#investor"
parameter.Direction = ParameterDirection.Input
parameter.Value = 34
Use parameters instead of concatenating your SQL query.
Assuming your database engine being SQL Server, here's a piece of code which I hope will help.
Using connection As SqlConnection = new SqlConnection("connectionString")
connection.Open()
Using command As SqlCommand = connection.CreateCommand()
string sqlStatement = "select * from table where ref = #ref and bookno = #bookno";
command.CommandText = sqlStatement
command.CommandType = CommandType.Text
Dim refParam As SqlDataParameter = command.CreateParameter()
refParam.Direction = ParameterDirection.Input
refParam.Name = "#ref"
refParam.Value = Ref
Dim booknoParam As SqlDataParameter = command.CreateParameter()
booknoParam.Direction = ParameterDirection.Input
booknoParam.Name = "#bookno"
booknoParam.Value = Session("number")
Try
Dim reader As SqlDataReader = command.ExecuteQuery()
' Do your reading job here...'
Finally
command.Dispose()
connection.Dispose()
End Try
End Using
End Using
To sum it all up, avoid SQL statement concatenation at all cost, and use parameterized quesries!
Here is an interesting link that brings you through SQL injection problem resolution on MSDN:
How To: Protect From SQL Injection in ASP.NET
use sqlparameters like:
SqlCommand cmd = new SqlCommand("Select * from Table where id=#id", con);
cmd.Parameters.AddWithValue("#id", 34);
you can use parameterized queries.
http://www.functionx.com/aspnet/sqlserver/parameterized.htm
SqlCommand cmd = new SqlCommand("Select * from Table where ref=#ref", con);
cmd.Parameters.AddWithValue("#ref", 34);
it does not work because it is written in C#, not VB.
Try something like
Dim cmd As New SqlCommand("Select * from Table where ref=#ref", con)
cmd.Parameters.AddWithValue("ref", 34)
My preferred way is to let Visual Studio handle it all by creating a DAL:
http://www.asp.net/data-access/tutorials/creating-a-data-access-layer-cs
Use LINQ. It parametrizes queries automatically.
Check out ORM as an alternative (very good way to go if you are building something medium-sized or big). It takes a little time to configure it, but then development becomes VERY fast. You choose from the native, Linq to SQL or Entity Framework, OR, try any other ORM which works with .NET.

Resources