I've got a function that stores temporary information generated for every user authenticated in the system. This 'session ID' is a string stored in a Sessions table, along the original ID of the user which authenticated and was given said session identifier.
The function to remove/deauthenticate/invalidate an existing session first checks if the user exists through another method implemented as follows:
int userId = 0;
SqlCeCommand cmd = new SqlCeCommand();
SqlCeParameterCollection sqlParams = cmd.Parameters;
sqlParams.AddWithValue("#User", userName);
cmd.Connection = this.conn;
cmd.CommandText = "SELECT Id FROM Users WHERE (Username = #User)";
userId = (int) cmd.ExecuteScalar()
cmd.Dispose();
Afterwards it tries to find an existing session for that user, which is to be removed (via a different method again):
SqlCeCommand cmd = new SqlCeCommand();
SqlCeParameterCollection sqlParams = cmd.Parameters;
sqlParams.AddWithValue("#SID", mysession);
sqlParams.AddWithValue("#UID", myuserid);
cmd.Connection = this.Connection;
cmd.CommandText = "SELECT Id FROM UserSessions WHERE (SessionID = #SID) AND (User_Id = #UID)";
int foo = cmd.ExecuteNonQuery();
...which fails. No exception is raised unfortunately. So I added an insecure equivalent using a non parametrized query string:
cmd.CommandText = String.Format("SELECT Id FROM UserSessions WHERE (SessionID = '{0}') AND (User_Id = {1})", mysession, myuserid);
cmd.Prepare();
int bar = cmd.ExecuteNonQuery();
Added a breakpoint, paused, copy pasted the query into the Visual Studio Query tool and voila, it indeed worked. But after continuing, that query in the code failed as well. I'm unable to find the culprit of this annoying issue since no exception is raised and everything seems correct. The data exists, the parameters are provided in proper types (string and int) and I'm out of things to check. The connection is open and so forth.
Any clues from anyone around? Thanks!
Update: Mea culpa, missed the fact that the function used ExecuteScalar until I modified it for testing. It does use ExecuteScalar and returns null, just in case.
You're using ExecuteNonQuery:
int foo = cmd.ExecuteNonQuery();
... but you're clearly trying to execute a query (a SELECT)! Use ExecuteScalar again, as you did in the first code, or ExecuteReader and look through the results appropriately. If you stick with ExecuteScalar, you should first check whether the result is null to indicate no results.
ExecuteNonQuery returns the number of rows affected by an UPDATE/INSERT/DELETE command - which is what it's intended for. I suspect it's returning -1 for you, as documented:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.
(Emphasis mine.)
Use set [] to avoid ambiguity with database keyword.
cmd.CommandText = "SELECT [Id] FROM [Users] WHERE ([Username] = #User)";
and use ExecuteScalar() or ExecureReader() method when working with SELECT statements.
Related
I'm having trouble with a simple SELECT query, I cannot see why it isn't working.
Here is the code:
conn.Open();
string GetPayrollQuery = "SELECT PayrollNo FROM [Employee] WHERE (FirstName + ' ' + LastName) = #Name";
OleDbCommand GetPayroll = new OleDbCommand(GetPayrollQuery, conn);
GetPayroll.Parameters.AddWithValue("#Name", OleDbType.VarChar).Value = cbbEmployees.Text;
var GotPayroll = GetPayroll.ExecuteNonQuery();
MessageBox.Show(GotPayroll.ToString());
return Convert.ToInt32(GotPayroll);
The code runs fine however it isn't extracting the data. Can anyone see why this would be?
I bet #name is coming as "MikeSmith" instead of "Mike Smith".
3 things:
try to open SQL profiler and check what you are executing on database
check database collation, is it case sensitive?
remove executenonquery (it's must used with update, delete, not select) and try executescalar (if one result for one row is exptected, otherwise try to fill a datatable or use datareader)
Make sure the same query runs in SQL using those parameter values.
Change GetPayroll.ExecuteNonQuery() to GetPayroll.ExecuteScalar() so to return a single result.
Change GetPayroll.Parameters.AddWithValue("#Name", OleDbType.VarChar).Value = cbbEmployees.Text; to GetPayroll.Parameters.AddWithValue("#Name", cbbEmployees.Text);
Use cbbEmployees.SelectedText. Fixes the problem.
I have a C# app with have to use SQL Server database with 1 table (All_Data) and 5 columns (ID, Name, Surename, Age,Location)
Before inserting a new row how can I find out or get the value of the last ID in the table
I have a following code but it,a not work well
string query = "SELECT MAX(ID) FROM All_Data";
SqlCommand comSelect;
comSelect = new SqlCommand(query, connection);
int ID = (int)comSelect.ExecuteScalar();
ERROR message:
ExecuteScalar: Connection property has not been initialized
Please help me
First, from your code it is not clear what is the value of the variable connection.
From the error message it seems that you don't have initialized this variable and thus you get the error. (connection = new SqlConnection(....);)
However, this is not the correct way to handle this scenario.
You need to make the ID column an IDENTITY column and then don't try to retrieve its value before executing any INSERT.
An IDENTITY column receives its value directly from the database when there is a new record to insert. And letting the database code work on this data it is the best option if you want to be safe from concurrency issues.
If you need to retrieve the ID value after an INSERT query because you need it as a Foreign Key in other tables or for your own code, then you could simply use the T-SQL command
SELECT SCOPE_IDENTITY()
For example, suppose you have to insert a record in that table, and you want to know the IDENTITY value assigned to the ID column
string query = #"INSERT INTO All_Data(Name,Surename,Age,Location)
VALUES(#name, #surname, #age, #loc);
SELECT SCOPE_IDENTITY()";
using(SqlConnection connection = new SqlConnection(connectionString))
using(SqlCommand cmd = new SqlCommand(query, connection))
{
connection.Open();
cmd.Parameters.AddWithValue("#name", yourNameValue);
.... other parameters ...
int newID = Convert.ToInt32(cmd.ExecuteScalar());
}
As you can see, this code doesn't try to pass a value for the ID column. It pass just the other fields with a parameterized query. But at the end of the first query there is a call to SELECT SCOPE_IDENTITY() and this returns whatever value the database has assigned to the column ID (of course you should have set the IDENTITY property on the field).
This will work correctly in multiuser and concurrent scenario
The error fires when the command doesn't have a connection. Please check connection is open.
Error saysExecuteScalar: Connectio property has not been initialized
double Check your connection string whether it is defined properly. You can check here to know how to define connection string.
you have not opened connection so open it before use :
comSelect = new SqlCommand(query, connection);
connection.Open();
int ID = (int)comSelect.ExecuteScalar();
connection.Close();
SqlDataSource myQuiz = new SqlDataSource();
myQuiz.ConnectionString = ConfigurationManager.ConnectionStrings["yafnet"].ToString();
myQuiz.InsertCommand = "INSERT INTO [QuizTable]([Quiz_Title],[Quiz_Description]) VALUES (#Quiz_Title,#Quiz_Description)";
myQuiz.InsertParameters.Add("Quiz_Title",Quiz_Title.Text);
myQuiz.InsertParameters.Add("Quiz_Description",Quiz_Description.Text);
myQuiz.Insert();
Response.Redirect("QuizQuests.aspx");
Is there a way to get back the automatically generated ID of the new row and put it in a local variable?
Thanks a lot in advance,
Adrian
Use
SELECT IDENT_CURRENT(‘QuizTable’)
It returns the last IDENTITY value produced in a table, regardless of the connection that created the value, and regardless of the scope of the statement that produced the value.
IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. IDENT_CURRENT returns the identity value generated for a specific table in any session and any scope.
If you want to be 100% sure that you really get the identity from your insert in your actual QuizTable, you should use SCOPE_IDENTITY() (as already mentioned by Luiggi Mendoza in his comment), and not ##IDENTITY or IDENT_CURRENT.
##IDENTITY might not work because it will return the identity from the last insert that happened from your connection. So if there is a trigger on your QuizTable which inserts a row in another table that has an identity column as well, ##IDENTITY will return the value from that second insert, and not that of the original insert into the QuizTable .
IDENT_CURRENT will return the last identity value for your table (and only for your table, so it doesn't matter if there are triggers like the one in the previous example).
But it returns the last identity value for any session. So if another row is inserted from another session between your INSERT and your IDENT_CURRENT, you'll get the identity value from that row, not from yours.
#Adrian De Barro: hi you can use following code to get inserted record id and save in variable
in your sqlquery add following statement:
return ##IDENTITY
and your C# code will be as follows:
SqlConnection cn = new
SqlConnection(ConfigurationManager.AppSettings["ConnectionString"]);
cn.Open();
SqlCommand cmd = new SqlCommand(procname, cn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter str = new SqlParameter("name", SqlDbType.VarChar);
str.Direction = ParameterDirection.ReturnValue;
foreach (SqlParameter par in param)
{
cmd.Parameters.Add(par);
}
string name = Convert.ToString(cmd.ExecuteScalar());
cmd.Dispose();
cn.Close();
return name;
I'm using the MySql Connector .net, and I need to get the insert id generated by the last query. Now, I assume the return value of MySqlHelper.ExecuteNonQuery should be the last insert id, but it just returns 1.
The code I'm using is:
int insertID = MySqlHelper.ExecuteNonQuery(Global.ConnectionString,
"INSERT INTO test SET var = #var", paramArray);
However insertID is always 1. I tried creating a MySql connection and opening/closing manually which resulted in the same behaviour
Just use LastInsertedId field
MySqlCommand dbcmd = _conn.CreateCommand();
dbcmd.CommandText = sqlCommandString;
dbcmd.ExecuteNonQuery();
long imageId = dbcmd.LastInsertedId;
1 is the no of records effected by the query here only one row is inserted so 1 returns
for getting id of the inserted row you must use scope_identity() in sqlserver and LAST_INSERT_ID() in MySql
Try to use this query to get last inserted id -
SELECT LAST_INSERT_ID();
Then, run DbCommand.ExecuteReader method to get IDataReader -
command.CommandText = "SELECT LAST_INSERT_ID()";
IDataReader reader = command.ExecuteReader();
...and get information from the reader -
if (reader != null && reader.Read())
long id = reader.GetInt64(0);
...do not forget to close the reader;-)
I had the same problem, and after some testing, I found out that the problem seem to be the connection method; you are using a connection string.
This is of course to make use of the automatic connection pool reuse, but in this case it gave me trouble.
The final solution for me is to create a new connection, execute the insert query, and then execute the last_insert_id(). On the same connection.
Without using the same connection, last_insert_id() might return anything, I don't know why, but guess it looses track of things as it can be different connections.
Example:
MySqlConnection connection = new MySqlConnection(ConnectionString);
connection.Open();
int res = MySqlHelper.ExecuteNonQuery(
connection,
"INSERT INTO games (col1,col2) VALUES (1,2);");
object ores = MySqlHelper.ExecuteScalar(
connection,
"SELECT LAST_INSERT_ID();");
if (ores != null)
{
// Odd, I got ulong here.
ulong qkwl = (ulong)ores;
int Id = (int)qkwl;
}
I hope this helps someone!
I know this is an old post, but I have been facing the same issue as Snorvarg. Using MySqlHelper, and using a connection string instead of a Connection object (to allow MySqlHelper to use connection pooling), SELECT LAST_INSERT_ID() would often give me the ID of the previous query that was executed, or other times it would return zero. I would then have to call SELECT LAST_INSERT_ID() a second time to get the correct ID.
My solution was to encapsulate everything between the query that's being executed, and the calling of SELECT LAST_INSERT_ID() in a TransactionScope. This forces MySqlHelper to stick to one connection instead of opening two separate connections.
So:
string sql = "INSERT INTO games (col1,col2) VALUES (1,2);");
string connectionString = "some connection string";
using (TransactionScope scope = new TransactionScope)
{
int rowsAffected = MySqlHelper.ExecuteNonQuery(connectionString, sql);
object id = MySqlHelper.ExecuteScalar(connectionString, "SELECT LAST_INSERT_ID();");
scope.Complete();
}
try below working solution in repository .
string query = $"INSERT INTO `users`(`lastname`, `firstname`, `email`, `createdate`, `isdeleted`) " +
$"VALUES ('{userEntity.LastName}','{userEntity.FirstName}','{userEntity.Email}','{userEntity.CreateDate}',{userEntity.IsDeleted});" +
$"SELECT LAST_INSERT_ID();";
var res= _db.ExecuteScalar(query);
return (int)(UInt64)res;
I think nothing's wrong with the connection because when I open it, it does not throw any error. So I guess the error is when I'm executing a command. This is my code:
OleDbCommand cmd = new OleDbCommand("SELECT * FROM cars", conn);
cmd.CommandType = CommandType.Text;
int numbers = cmd.ExecuteNonQuery();
I tried using a message box to display the value of numbers but the result is always 0. The table cars contains 5 records. So why am I not getting the correct results?..
To the anonymous downvoter, the key part of the OP:
I tried using a message box to display the value of numbers but the
result is always 0. The table cars contains 5 records. So why am I not
getting the correct results?..
The OP is obviously trying to get a count of records in the table (a scalar aggregate) and not all of the table data.
My answer:
That's because your query is returning a table and not a scalar value and you're calling the incorrect function. Your query should be should be:
"SELECT COUNT(*) FROM cars"
And ExecuteNonQuery doesn't actually expect any results to be returned. (You usually run insert, update and delete operations with ExecuteNonQuery.) You should be using ExecuteScalar which expects a single-valued result such as count(*).
All together now:
OleDbCommand cmd = new OleDbCommand("SELECT count(*) FROM cars", conn);
cmd.CommandType = CommandType.Text;
int numbers = cmd.ExecuteScalar();
Try using ExecuteScalar that should give you the count. ExecuteNonQuery doesn't return the results from your query. The return your looking at indicates how many rows were affected by your statement, in your case zero.
ExecuteNonQuery as the name tells you does not make a query. it is normally used for inserts or updates and returns the number of affected records. for the query you provided you should use ExecuteReader or a DataAdapter and its Fill method to fill a datatable.
Because you are executing a query, and ExecuteNonQuery returns the number of rows effected, which when you select is always 0 since you aren't changing anything (ie. INSERT,UPDATE or DELETE)
ExecuteNonQuery only returns the number of rows affected for UPDATE, DELETE or INSERT operations. For the number of rows in the SELECT statement, try:
OleDbCommand cmd = new OleDbCommand("SELECT * FROM cars", conn);
OleDbDataReader reader = cmd.ExecuteReader();
int numbers = 0;
while (reader.Read())
{
//// other Reader-related operations here...
numbers++;
}