I have a method which updates a table as below :
public static Boolean updateRequest(String _VUserName, DateTime newToDate)
{
SqlConnection conn = getConnection();
SqlCommand command = new SqlCommand();
command.CommandText = "UPDATE Requests SET [To] = #ToDate FROM Requests INNER JOIN "+
"VUsers ON Requests.UserRef = VUsers.VUserID WHERE (VUsers.VUserName = #VUserName)";
command.Parameters.AddWithValue("#ToDate", newToDate);
command.Parameters.AddWithValue("#VUserName", _VUserName);
conn.Open();
try
{
command.ExecuteNonQuery();
return true;
}
catch (Exception)
{
return false;
}
conn.Close();
}
but it failed with _COMPlusExceptionCode = -532459699 exception
any help?
Please check the following link "SQL Server refusing to add a record because it didn't conform to table column specifications"
It looks like it has to do with your update statement. Rather rewrite it like this.
"UPDATE Requests SET [To] = #ToDate WHERE ...
Related
I'd like to be able to generate the DDL for objects of a specific type. The following query will return the DDL for all tables in the schema 'MYSCHEMA'.
SELECT
O.OWNER,
O.OBJECT_TYPE,
O.OBJECT_NAME,
DBMS_METADATA.GET_DDL(OBJECT_TYPE, O.OBJECT_NAME, O.OWNER) As DDL
FROM
ALL_OBJECTS O
WHERE
O.OWNER = 'MYSCHEMA' AND O.OBJECT_TYPE = 'TABLE'
ORDER BY
O.OWNER, O.OBJECT_TYPE, O.OBJECT_NAME
However, I'd like to exclude physical attributes, storage attributes, tablespace, and logging. I know that if I run the following SQL statement prior to the above one that the SQL will be generated as desired, without this extra info.
exec DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE );
I'd like to be able to create a C# function that returns the DDL for a specific OWNER (schema) and object type, such as TABLE. I assume that the first statement, the execution of the stored procedure, sets an option for the current session, so I assume that I need to do the same two steps from a C# program on the same open connection. I am under the impression that DBMS_METADATA.SESSION_TRANSFORM evaluates to -1. I'm not sure about this. When I try to execute the SP using the following C# routine, I get this error:
Unspecified error: E_FAIL(0x80004005)
What do I need to do to be able to execute the two Oracle SQL statements using using C# code?
public DataTable GetDdlForObjectsOfTypeInSchema(string objectType, string owner, string connectionString)
{
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
connection.Open();
////exec DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE );
OleDbCommand command = connection.CreateCommand();
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "DBMS_METADATA.SET_TRANSFORM_PARAM";
command.Parameters.Add(new OleDbParameter("#TRANSFORM_HANDLE", OleDbType.Numeric) { Value = -1 });
command.Parameters.Add(new OleDbParameter("#NAME", OleDbType.VarChar) { Value = "SEGMENT_ATTRIBUTES" });
command.Parameters.Add(new OleDbParameter("#VALUE", OleDbType.Boolean) { Value = false });
try
{
command.ExecuteNonQuery();
}
catch (System.Exception e2)
{
string msg = e2.Message;
}
//Query
command = connection.CreateCommand();
command.Connection = connection;
command.CommandText = #"
SELECT
O.OWNER,
O.OBJECT_TYPE,
O.OBJECT_NAME,
DBMS_METADATA.GET_DDL(REPLACE(OBJECT_TYPE, ' ', '_'), O.OBJECT_NAME, O.OWNER) As DDL
FROM
ALL_OBJECTS O
WHERE
O.OWNER = ? AND O.OBJECT_TYPE = ?
ORDER BY
O.OWNER, O.OBJECT_TYPE, O.OBJECT_NAME
";
var oleDbDataAdapter = new OleDbDataAdapter(command);
DataSet dataset = new DataSet();
command.Parameters.Add(new OleDbParameter("#OWNER", OleDbType.Char) { Value = owner });
command.Parameters.Add(new OleDbParameter("#OBJECT_TYPE", OleDbType.Char) { Value = objectType });
try
{
oleDbDataAdapter.Fill(dataset);
return dataset.Tables[0];
}
catch (System.Exception e)
{
return null;
}
return null;
}
}
you need to execute your 2 statements in one shot. your options are
Create stored procedure
Use anonymous block
Thankfully there is a way to do it without stored procedure - use anonymous block.
And here is a good example
And your code will look like
command.CommandType = CommandType.Text;
command.CommandText = #"
begin
DBMS_METADATA.SET_TRANSFORM_PARAM( DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE );
open :rcursor for
SELECT
O.OWNER,
O.OBJECT_TYPE,
O.OBJECT_NAME,
DBMS_METADATA.GET_DDL(OBJECT_TYPE, O.OBJECT_NAME, O.OWNER) As DDL
FROM
ALL_OBJECTS O
WHERE
O.OWNER = 'MYSCHEMA' AND O.OBJECT_TYPE = 'TABLE'
ORDER BY
O.OWNER, O.OBJECT_TYPE, O.OBJECT_NAME;
end;";
I'm new to using SqlDataAdpter and I'm trying to execute a stored procedure. The stored procedure executes successfully but no rows are returned. I've used SQL Server Profiler to monitor the call and it runs successfully (I can copy and execute the query from profiler without modifying it and get results).
I have the following:
public ActionResult Index()
{
SqlConnection conn = null;
DataSet results = null;
try
{
string connectionString = // ... my connection
conn = new SqlConnection(connectionString );
string query = #"usp_mySP";
conn.Open();
SqlDataAdapter sqlAdpt = new SqlDataAdapter(query, conn);
sqlAdpt.SelectCommand.CommandType = CommandType.StoredProcedure;
var dataDate = new SqlParameter { ParameterName = "#DataDate", Value = DateTime.Now };
var idList = new SqlParameter { ParameterName = "#IDList", Value = "1231,2324,0833" };
sqlAdpt.SelectCommand.Parameters.Add(dataDate);
sqlAdpt.SelectCommand.Parameters.Add(idList);
results = new DataSet();
sqlAdpt.Fill(results);
sqlAdpt.Dispose();
}
catch (SqlException e)
{
throw new Exception("Exception:" + e.Message);
}
finally
{
if (conn != null)
conn.Close();
}
return View(results);
}
When I inspect the DataSet through the debugger, it always returns 0 rows.
Please help with what I'm doing wrong?
Note: I've also tried (but do NOT prefer) executing as a SQL command:
EXEC usp_mySP #DataDate, #IDList
and it didn't work either as I got int to varchar conversion errors.
I think you try to add SqlParameter using SqlCommand like this :
SqlCommand cmd = new SqlCommand();
cmd.parameter.addwithvalue(#DataDate,DateTime.Now);
So the reason was because of set nocount on. I added it to my sp and it works. Thank you everyone for clarifying.
-edit- wrote a clearer explanation of what's not working down bottom. maybe just skip to that.
I'm having an issue with a stored procedure I wrote and getting the result in my c# application, yet when I execute it within MySQL benchmark the result returns fine.
Firstly the procedure is:
CREATE DEFINER=`root`#`localhost` PROCEDURE `GetNextOpponent`(IN p_user_id INT, OUT p_target_id INT, OUT p_target_data MEDIUMBLOB, OUT p_target_rank INT)
BEGIN
DECLARE UserRank INT;
CALL DeleteOldSearches(); /* TODO remove and call on interval instead of every time*/
SET UserRank = (SELECT rank FROM world WHERE user_id = p_user_id);
IF UserRank IS NOT NULL
THEN
SELECT user_id, world_data, rank
INTO p_target_id, p_target_data, p_target_rank
FROM world
WHERE
user_id != p_user_id AND
user_id NOT IN (SELECT target_id FROM searches WHERE user_id = p_user_id) AND
shield < CURRENT_TIMESTAMP
ORDER BY ABS(UserRank - 3)
LIMIT 1;
END IF;
IF p_target_id IS NOT NULL
THEN
INSERT INTO searches (user_id, target_id)
VALUES (p_user_id, p_target_id);
END IF;
/*SELECT TargetID, TargetData, TargetRank;*/
END
Now if I call it in WorkBench with
call battlecraft_test.GetNextOpponent(1, #p_target_id, #p_target_data, #p_target_rank);
select #p_target_id, #p_target_data, #p_target_rank;
I have no issue, get a nice result
'3', BLOB, '2'
However if I execute it in my app with,
public static bool GetNextOpponent(int userID)
{
MySqlConnection conn = null;
try
{
conn = new MySqlConnection(ConnectionString);
conn.Open();
using (var cmd = new MySqlCommand("GetNextOpponent", conn) {CommandType = CommandType.StoredProcedure})
{
cmd.Parameters.Add("#p_user_id", MySqlDbType.Int32).Value = userID;
cmd.Parameters.Add("#p_target_id", MySqlDbType.Int32).Direction = ParameterDirection.Output;
cmd.Parameters.Add("#p_target_data", MySqlDbType.MediumBlob).Direction = ParameterDirection.Output;
cmd.Parameters.Add("#p_target_rank", MySqlDbType.Int32).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
object a = cmd.Parameters["#p_target_id"].Value; // null
object b = cmd.Parameters["#p_target_data"].Value; // null
object c = cmd.Parameters["#p_target_rank"].Value; // null =(
return true;
}
}
catch (Exception ex)
{
Logger.LogError($"Unexpected exception of type {ex.GetType()}: {ex.Message}");
return false;
}
finally
{
conn?.Close();
}
}
The out params are all null.
There are a few interesting cases where I've got results out from my application, for instance most times if I step through each line of code while debugging it works fine, however most of the time nothing happens.
I'm really struggling with this, spent hours on it now - my database knowledge isn't as good as I'd like it to be at the moment and I'm out of ideas, so I'm hoping someone has an idea what it could be.
One of my attempts to fix this I tried not using OUT keywords and instead just returning the field and using ExecuteReader instead yet it still only sometimes works.
If I write another procedure to kind of wrap this procedure like so:
CREATE DEFINER=`root`#`localhost` PROCEDURE `test`(IN p_user_id INT)
BEGIN
call battlecraft_test.GetNextOpponent(p_user_id, #p_target_id, #p_target_data, #p_target_rank);
select #p_target_id, #p_target_data, #p_target_rank;
END
It works when I execute it using Reader, however the first row is always null and the second row has the result. It's a usable workaround but I'd rather get to the cause of it.
Thanks for any response in advance.
-edit-
Even stripping it back I have issues. If I reduce stored procedure to just
CREATE DEFINER=`root`#`localhost` PROCEDURE `GetNextOpponent`(IN p_user_id INT)
BEGIN
SELECT user_id, world_data, rank
FROM world
WHERE
user_id != p_user_id AND
user_id NOT IN (SELECT target_id FROM searches WHERE user_id = p_user_id) AND
shield < CURRENT_TIMESTAMP
ORDER BY ABS((SELECT rank FROM world WHERE user_id = p_user_id) - rank)
LIMIT 1;
END
And then do it as a reader
public static bool GetNextOpponent(int userID)
{
MySqlConnection conn = null;
try
{
conn = new MySqlConnection(ConnectionString);
conn.Open();
using (var cmd = new MySqlCommand("GetNextOpponent", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#p_user_id", MySqlDbType.Int32).Value = userID;
//System.Threading.Thread.Sleep(1000); // Un-commenting this makes it work...
using (var rdr = cmd.ExecuteReader())
{
if (!rdr.Read())
return false; // returns here
var r1 = rdr.GetValue(0); // null
var r2 = rdr.GetValue(1); // null
var r3 = rdr.GetValue(2); // null
return true;
}
}
}
catch (Exception ex)
{
Logger.LogError($"Unexpected exception of type {ex.GetType()}: {ex.Message}");
return false;
}
finally
{
conn?.Close();
}
}
While executing it in workbench still returns a nice result
call battlecraft_test.GetNextOpponent(1);
There are many things to be improved in your code
In the finally block of your try/catch validate and close the connection
Dont use generic Catch as the first level of catch use ("DatabaseSpecificExceptions" or "RunTimeExceptions" or any other Expected expection" and log that to a file or by email to debug furthers
public static bool GetNextOpponent(int userID)
{
MySqlConnection conn = null;
boolean resp ;
//we assume that if fails
resp = false ;
try
{
conn = new MySqlConnection(ConnectionString);
if(conn != null)
{
conn.Open();
using (var cmd = new MySqlCommand("GetNextOpponent", conn) {CommandType = CommandType.StoredProcedure})
{
//Addding parameters to the SQL commands - good comments never hurt
cmd.Parameters.Add("#p_user_id", MySqlDbType.Int32).Value = userID;
cmd.Parameters.Add("#p_target_id", MySqlDbType.Int32).Direction = ParameterDirection.Output;
cmd.Parameters.Add("#p_target_data", MySqlDbType.MediumBlob).Direction = ParameterDirection.Output;
cmd.Parameters.Add("#p_target_rank", MySqlDbType.Int32).Direction = ParameterDirection.Output;
//you are executing a NonQuery but expectin results ??
cmd.ExecuteNonQuery();
//see comments above
object a = cmd.Parameters["#p_target_id"].Value; // null
object b = cmd.Parameters["#p_target_data"].Value; // null
object c = cmd.Parameters["#p_target_rank"].Value; // null =(
//avoid returns in the middle of the flow until debug works
//return true;
resp = true ;
}
}
}
catch (Exception ex)
{
Logger.LogError($"Unexpected exception of type {ex.GetType()}: {ex.Message}");
}
finally
{
if(conn != null)
{
conn?.Close();
}
}
}
I am trying to update a single value into my access .accdb database via a c# winform interface. my SQL statement is:
updateString("UPDATE Password_Table SET Password = '" + confirmnewpasswordTextBox.Text + "' WHERE Password_ID = 'user'");
field-wise it should be correct but whenever i execute the updateString function it only returns zero. may I know what I am doing wrongly in the following example?
public static bool updateString(string SQL)
{
using (var connection = new OleDbConnection(connectionString))
using (var command = connection.CreateCommand())
{
connection.Open();
command.CommandText = SQL;
command.CommandType = CommandType.Text;
try
{
return command.ExecuteNonQuery();
}
catch
{
return -1;//for error
}
}
}
Thank you!!
update:
System.Data.OleDb.OleDbException: Syntax error in UPDATE statement.
hmmm, i still cant figure out what is wrong, my table is Password_Table, and I am trying to update a column called Password where the Password_ID is "user".
update: found the error! turns out that Password is like a restricted keyword and i had to cover it in [ ] before it could work..
There are serious issues with your code. It is vulnerable to SQL injection. You should always use parametrized queries to avoid that. For example:
public static string UpdatePassword(string user, string password)
{
using (var connection = new OleDbConnection(connectionString))
using (var command = connection.CreateCommand())
{
connection.Open();
command.CommandText = "UPDATE Password_Table SET Password = #pwd WHERE Password_ID = #user";
command.Parameters.AddWithValue("#pwd", password);
command.Parameters.AddWithValue("#user", user);
try
{
return command.ExecuteNonQuery();
}
catch
{
return -1;//for error
}
}
}
And then invoke like this:
int rowsAffetected = UpdatePassword("user", confirmnewpasswordTextBox.Text);
Now, if this returns 0 it means that there is no record in your database which matches the Password_ID = user condition and there is nothing to update.
I have been trying to retrieve some information from my database, and also retrieve the return value. I know the Stored Procedure works fine.
The code I use is a modified piece I use for registering the user. It's going wrong at the cmd.ExecuteReader part of my code.
protected void btn_login_Click(object sender, ImageClickEventArgs e)
{
//Actions after Submit button is clicked
Page.Validate(((ImageButton)sender).ValidationGroup);
if (Page.IsValid)
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DbConnectString"].ConnectionString))
{
SqlCommand cmd = new SqlCommand("usp_validateUsers", conn);
//Input Values
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("username", Uname.Text);
cmd.Parameters.AddWithValue("password", pwd.Text);
//Return Values
SqlParameter retParam = cmd.Parameters.Add("#RetVal", SqlDbType.Int);
retParam.Direction = ParameterDirection.ReturnValue;
SqlParameter acsParam = cmd.Parameters.Add("#ac_status", SqlDbType.Int);
acsParam.Direction = ParameterDirection.Output;
SqlParameter nikParam = cmd.Parameters.Add("#memb_name", SqlDbType.VarChar);
nikParam.Direction = ParameterDirection.Output;
try
{
// Open Connection and execute Stored Proc
conn.Open();
///////////SOMETHING GOES WRONG HERE///////////////
cmd.ExecuteReader();
//Retrieve Data
int retVal = (int)retParam.Value;
string nickname = nikParam.Value.ToString();
string ac_stats = acsParam.Value.ToString();
if (retVal != 0)
{
//Invalid Username or password
}
else
{
//Login User
}
}
catch (Exception Error)
{
lbl_login.Text = "An error occured, please try again later";
debug.Text = Error.Message;
}
finally
{
debug.Text = "\n Clossing Connection";
if (conn.State == System.Data.ConnectionState.Open)
{
conn.Close();
}
}
}
}
}
When I just want to receive the return value I simply use cmd.ExecuteScalar(); I know how to receive data when I'm passing the SQL query to the SQL database, but it seems to be different when using Stored Procedures..
EDIT
Probably could improve this code further but it really does what it should do.
ALTER PROCEDURE dbo.usp_validateUsers
#username varchar(10),
#password varchar(10),
#ac_status char(1) OUTPUT,
#memb_name varchar(15) OUTPUT
AS
IF EXISTS(SELECT * FROM MEMB_INFO WHERE (memb___id = #username))
BEGIN
SELECT #ac_status = ac_status, #memb_name = memb_name
FROM MEMB_INFO
WHERE (memb___id = #username) AND (memb__pwd = #password)
RETURN 0
END
ELSE
BEGIN
return 1
END
When I use break points to catch possible exceptions in Visual Studio, It gives me:
String[4]: The Size property has an invalid size of 0
The error you mentioned may be caused by the fact that you're not specifying the size of your VarChar parameters. Instead of having lines like this:
SqlParameter nikParam = cmd.Parameters.Add("#memb_name", SqlDbType.VarChar);
Try this:
SqlParameter nikParam = cmd.Parameters.Add("#memb_name", SqlDbType.VarChar, 15);
You need to create a SqlDataReader.
From Ins and Outs of using Stored Procedures in C#
The SqlDataReader class is used to
read a forward only stream of records
returned from the database. The
SqlDataReader object is not
instantiated directly through a
constructor (hence the lack of the New
key word) but rather through the
ExecuteReader method of the SqlCommand
object. Before calling the
ExecuteReader method the connection to
the database is established using the
Open method of the SqlConnection
object.
Try
SqlDataReader drLogins;
Conn.Open();
drLogins = cmd.ExecuteReader();
Your #ac_status is defined as integer in parameter. change it character or string.
SqlParameter acsParam = cmd.Parameters.Add("#ac_status", SqlDbType.Int);