c# SqlDataReader Not Finding Value - c#

My Problem has Been Fixed, My main problem was getting the information from the textbox in the xaml which got erased after that window was closed and another opened. Though the answers did fix my other problems and have made my code much simpler and easier to read. So thank you very much!
So I am Currently working on building a Calendar for a personal project and working on adding events to a Database, this table for Events stores two varchars, and an int (name, description, userid), the userid is a foreign key and is linked to the User Table. When I use the code below to try and pull the userid for the username that the person entered, it tells me that there is no existing value.
using (SqlConnection connection = new SqlConnection())
{
connection.ConnectionString =
"Data Source=calenderserver.database.windows.net;" +
"Initial Catalog=Calender;" +
"User id=*******;" +
"Password=*******;" +
"MultipleActiveResultSets = true";
connection.Open();
SqlCommand com = new SqlCommand("Select UserId from Users Where UserName = #user", connection);
com.Parameters.AddWithValue("#user", UsernameTextBox.Text);
SqlDataReader reader = com.ExecuteReader();
reader.Read();
int userid = reader.GetInt32(1);
messages.Text = "Event Added";
SqlCommand command = new SqlCommand("INSERT INTO [Events] VALUES (#eventname, #eventdesc)", connection);
command.Parameters.AddWithValue("#eventname", name);
command.Parameters.AddWithValue("#eventdesc", description);
command.Parameters.AddWithValue("#userid", userid);
command.ExecuteNonQuery();
reader.Close();
connection.Close();
}
Even though when I run the same command in an actual SQL Query it returns a proper value.
SQL Command
I am completely lost on this and have checked multiple sources and solutions and would really appreciate the help.

You are doing int userid = reader.GetInt32(1); the indexes for the get function are 0 based so you actually need int userid = reader.GetInt32(0); so you get the first column.
That being said, because you are using the first result of the first column you can simplify your code by switching from a data reader to using ExecuteScalar()
SqlCommand com = new SqlCommand("Select UserId from Users Where UserName = #user", connection);
com.Parameters.AddWithValue("#user", UsernameTextBox.Text);
int userid = (int)com.ExecuteScalar();

Try using ExecuteScalar function. Execute scalar returns a single value and I see you only need the user ID.
Take a look at this link .
int userid = (Int32)com.ExecuteScalar();
I Hope it helps!

Indices in GetInt32 are 0-based as per doc, therefore your call should read:
int userid = reader.GetInt32(0);

Change these lines:
SqlDataReader reader = com.ExecuteReader();
reader.Read();
int userid = reader.GetInt32(1);
to:
var userID = com.ExecuteScalar();
Why:
Execute Scalar should be used when your query returns a single value.
Execute Reader returns a collection of data in the form of a DataReader. DataReaders are fast, and you can quickly iterate over them to get the data you need from the database. The connection remains open as long as the datareader is open.
Because you were only getting a single value back from the database, it makes sense to use ExecuteScalar. It's more efficient and too the point.
If you were getting a list of UserID's, then I'd recommend you use a DataReader to iterate through the UserIDs.

Related

Insert a value in a table from another table using a variable in C# , SQL Server

I have to insert some values in a table while fetching them from another table. Here is my code:
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConString"].ConnectionString);
SqlCommand myCommand = new SqlCommand("SELECT Name FROM TableName WHERE Id = '" + Id + "'", con);
SqlDataReader rdr = myCommand.ExecuteReader();
if (dr.HasRows)
{
while (rdr.Read())
{
// User exist - get email
string Name = rdr["Name"].ToString();
}
}
My question is how to insert the name into another table.
I do not want to use a textbox for this the value must be inserted as a variable into other table. I use following script to insert data . but error message is Id not found. Please let me know if I am missing something
SqlCommand cmd = new SqlCommand(#"insert into finalTable (AccountNumber) VALUES (#string)", con);
I use following script to insert data . but error message is Id not found.
SqlCommand cmd = new SqlCommand(#"insert into finalTable (AccountNumber) VALUES
(#string)", con);
You need to specify a value for all columns in the table, unless some columns have default values. Its hard to tell without the exact error message, but it sounds like Id is probably the primary key column and not set to auto increment, so you must supply a value for Id. Since you are inserting, it must be a value not yet used in the table. Depending on your needs, you might want to change finalTable's ID to be auto increment.
On a side note, you are not disposing of things (like your DB connection) that implement IDisposable. The using keyword is your friend here.

ASP.NET C# - using dataset to read one row?

I'm developing a classic WEBForms application in C# and when I have to authenticate the user, I read from SQL database the user data using a query like that:
SELECT userid,username,email,city FROM USERS where username='blablabla' and password='blablabla'
I want to use this sql query in my method that returns a DTO Object that I defined in my UserValue class.
I'm thinking to use a dataset to fill user data executing the query.
Is it the correct approach or is it too expensive and useless to use dataset to read one row from a query?
Can you advice me?
thanks
For getting only one record from database or one by one record from database,"Data Reader" is Good Approach.Check the sites below You can get clear Idea on Data Reader.
http://www.aspdotnet-suresh.com/2012/10/aspnet-difference-between-datareader.html
http://msdn.microsoft.com/en-us/library/haa3afyz.aspx
http://www.akadia.com/services/dotnet_data_reader.html
Here's a code snippet (this is for MS SQL, but other flavors of SQL should be similar) to illustrate what I'm talking about in my comment:
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
SqlCommand cmd = new SqlCommand("SELECT userid,username,email,city FROM USERS where username=#username and password=#password", con);
cmd.Paramters.AddWithValue("#username", username);
cmd.Parameters.AddWithValue("#password", password);
cmd.CommandType = CommandType.Text;
UserInfo info = new UserInfo();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
if (rdr.HasRows)
{
rdr.Read(); // get the first row
info.UserID = rdr.GetInt32(0);
info.UserName = rdr.GetString(1);
info.Email = rdr.GetString(2);
info.City = rdr.GetString(3);
}
}
}
This example also shows how to do parameterized queries, which are essential for preventing SQL Injection attacks.
Also, rather than looping through the reader, I check to see if it has rows and if it does I read the first row only (and since you're dealing with user information there should theoretically be only one row) and populate the DTO.
Hopefully this will illustrate my comment to your question.

Determining if user login already exists in database?

I am building a web application in asp.net using C#. I have the Form where the user should register and then can login. I am having a problem in making the web app know that the name which the user picks is either "already exists" or not. If it already exists it should not insert the same name and display a message saying "user name already exists". I have tried the SqlDataReader but no luck.
protected void Register_Button_Click(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["BJ_Player_String"].ToString());
SqlCommand cmd = new SqlCommand();
SqlCommand cmd2 = new SqlCommand();
SqlDataReader data_reader;
String name = TextBox2.Text;
String date = TextBox3.Text;
try
{
conn.Open();
cmd = new SqlCommand("Insert into BJ_Player (Player_Name, D_O_B) Values (#Player_name, #D_O_B)", conn);
cmd = new SqlCommand("Select Player_Name from BJ_Player WHERE Player_Name = #Player_name", conn);
cmd.Parameters.Add("#Player_name", SqlDbType.NVarChar).Value = name;
cmd.Parameters.Add("#D_O_B", SqlDbType.Date).Value = date;
cmd.Connection = conn;
data_reader = cmd.ExecuteReader();
cmd.ExecuteNonQuery();
if (data_reader.HasRows)
{
lblPlayerNameExists.Visible = true;
}
else
{
// do nothing
}
}
Make Player_Name unique in database then it will give you exception when you try to insert. You have to use unique constraint.
You have to give command type also and check you assigned both queries to same cmd object
in your code you're inserting data in your DB and then you are examining that the name is the same or not.
first you should search the name in your DB and then if there isn't any record with that name ,you should add your record.
I usually do it in one of two ways:
Create stored procedure that will check for name uniqueness and insert new record if everything is ok. It should return status as numeric code that you will check.
Check for name uniqueness before saving it using as a part of validation process.
Using the merge statement may help with this. Merge performs insert, update, or delete operations on a target table based on the results of a join with a source table.
Basically it inserts when needed, and updates when needed. Often times referred to as an upsert. but it gets the job done.
Here is a link to a site explaining how to use merge. Looks like a good article.
http://www.kodyaz.com/articles/sql-server-2008-t-sql-merge-statement-example.aspx
If you would like to write a model function to do that then
Leave it for ajax check which is pretty similar to the second
method
Issue "Select username from DB-table" to retrieve
usernames then check the username input against them before
displaying a view to report a problem if any or showing a message to
tell the user that "this name is valid", for example.

How to get UUID generated by MySQL into a C# variable

Here is the query:
string query = #"INSERT INTO session (PK_Id, user_id, login_time, machine_ip, machine_fingerprint)
VALUES (UUID(), #UId, #LogInTime, #MIp, #MFingerPrint);
";
Now I need this last inserted id back, which is a UUID generated by MySQL. As far as I read there is no select_last_insert_id() function for UUIDs!! And I read for php you could assign UUID() function first to a variable and then return that value. But how to go about that in C#?
Something like this, but not exactly:
string query = #"INSERT INTO session (PK_Id, user_id, login_time, machine_ip, machine_fingerprint)
VALUES (#UUID = SELECT UUID(), #UId, #LogInTime, #MIp, #MFingerPrint);
"; //how to do this here?
Here is more of my code:
string query = #"INSERT INTO session (PK_Id, user_id, login_time, machine_ip, machine_fingerprint)
VALUES (#UUID = SELECT UUID(), #UId, #LogInTime, #MIp, #MFingerPrint);
";
try
{
if (_conn.State != ConnectionState.Open)
_conn.Open();
MySqlCommand cmd = new MySqlCommand(query, _conn);
cmd.Parameters.AddWithValue("#UId", Utility.usr.Id);
cmd.Parameters.AddWithValue("#LogInTime", DateTime.Now);
cmd.Parameters.AddWithValue("#MIp", GetMachineIP());
cmd.Parameters.AddWithValue("#MFingerPrint", GetHardwareFingerPrint());
var s= Convert.ToString(cmd.ExecuteScalar()); //this returns an empty string :(
//I need to get it to any .NET data type, string, or Guid or byte[] or anything.
But I need this datatype of s to be used in another WHERE clause in a query like this:
string query = #"UPDATE session SET logout_time = #LogOutTime
WHERE user_id = #UId AND PK_Id = #SessionId";
try
{
if (_conn.State != ConnectionState.Open)
_conn.Open();
MySqlCommand cmd = new MySqlCommand(query, _conn);
cmd.Parameters.AddWithValue("#UId", Utility.usr.Id);
cmd.Parameters.AddWithValue("#SessionId", s);
cmd.Parameters.AddWithValue("#LogOutTime", DateTime.Now);
cmd.ExecuteScalar();
Here #"SessionId" is the UUID field in the same table. So basically, how can I get the MySQL varbinary field in C# so that I could use that type to update by specifying WHERE in another query?
In MySQL table the UUID field is varbinary (I hope to see some solution that is not another php link or that is not asking me to switch to char datatype in the database :) ).
Edit: The problem here is we have already added plenty of UUIDs generated by MySQL into the table, so I'm a bit apprehensive about changing MySQL UUID to .NET Guid. If that's the only workaround, I'll consider that. Just that this is the first time we needed the inserted UUID value back so that I can update in another query another point of time.
A sub question: Is .NET Guid exactly the same thing as MySQL UUID?
You can use the Guid type which is the MS implementation of UUID. You should be aware that when inserting data into the DB, you may need to convert the Guid to ByteArray if the MySQL driver isn't familiar with handling Guid's. See Store GUID in MySQL from C# for an example of this.
I think you can go ahead with your earlier implementation without having to rely on MS Guid, but I fear I am too late :)
string query = #"INSERT INTO session (PK_Id, user_id, login_time, machine_ip, machine_fingerprint)
VALUES (UUID(), #UId, #LogInTime, #MIp, #MFingerPrint);
SELECT PK_Id FROM session WHERE login_time=#LogInTime AND machine_fingerprint=#MFingerPrint; //or something similar which gives you the exact same id - UUID
";
try
{
if (_conn.State != ConnectionState.Open)
_conn.Open();
MySqlCommand cmd = new MySqlCommand(query, _conn);
cmd.Parameters.AddWithValue("#UId", Utility.usr.Id);
cmd.Parameters.AddWithValue("#LogInTime", DateTime.Now);
cmd.Parameters.AddWithValue("#MIp", GetMachineIP());
cmd.Parameters.AddWithValue("#MFingerPrint", GetHardwareFingerPrint());
MySqlDataReader r = cmd.ExecuteReader();
if (r.Read()) //ensure if it is read only once, else modify your `WHERE` clause accordingly
{
var s = (Guid)r[0];
}
//or even (Guid)cmd.ExecuteScalar() would work
Now you can query in update like this:
string query = #"UPDATE session SET logout_time = #LogOutTime
WHERE user_id = #UId AND PK_Id = #SessionId";
try
{
if (_conn.State != ConnectionState.Open)
_conn.Open();
MySqlCommand cmd = new MySqlCommand(query, _conn);
cmd.Parameters.AddWithValue("#UId", Utility.usr.Id);
cmd.Parameters.AddWithValue("#SessionId", s.ToByteArray());
cmd.Parameters.AddWithValue("#LogOutTime", DateTime.Now);
cmd.ExecuteNonQuery();
Note: Here I have converted the Guid variable s to byte array before querying. This is important, in WHERE clause, be it UPDATE or SELECT statements in query. I would ask you to move to binary field in MySQL table from varbinary.
Edit: If your table would grow dramatically large then inserting and selecting is a bad idea since SELECT query is an additional query being run. In that case #PinnyM's choice is better. I really do not think MySQL or any other database would have a default way to give back "custom" inserted ids which are not something database generated. So in short I advice you to not go for this..
Edit2: See this answer for getting binary value to .NET datatype. Sometimes casting do not work depending on MySQL .NET connector version..

MySql Last Insert ID, Connector .net

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;

Categories