Saving database values as variables - c#

I can't figure out how to save individual data from an Access database into variables.
I understand that you can save variables like this:
int memberID;
cmd.CommandText = "SELECT * FROM MemberDetails WHERE [MemberID] =#MemberID";
cmd.Parameters.AddWithValue("#MemberID", memberID);
try
{
con.Open();
dr = cmd.ExecuteReader();
while (dr.Read())
{
lblName.Text = (memberID);
}
con.Close();
}
catch (Exception)
{
throw;
}
However I want to save all the data into separate variables, something like this:
cmd.CommandText = "SELECT [MemberID] = #MemberID, [Name] = #Name, [Surname] = #Surname";
cmd.Parameters.AddWithValue("#MemberID", memberID);
cmd.Parameters.AddWithValue("#Name", name);
cmd.Parameters.AddWithValue("#Surname", surname);
This obviously doesn't work (otherwise I wouldn't be here) but is anything like this possible and how would I go about doing this?

Maybe have a look at this great tutorial from Microsoft, it explains on how to query an MS Access database with C# and how to process the results: https://msdn.microsoft.com/en-us/library/ms971485.aspx
What you could do to achieve the desired result is something like this (this is a slightly modified example from the article mentioned above):
OleDbConnection conn = null;
OleDbDataReader reader = null;
try
{
conn = new OleDbConnection(
"Provider=Microsoft.Jet.OLEDB.4.0; " +
"Data Source=" + Server.MapPath("MyDataFolder/MyAccessDb.mdb"));
conn.Open();
OleDbCommand cmd =
new OleDbCommand("Select MemberID, Name, Surname FROM MemberDetails WHERE MemberID = #MemberID", conn);
cmd.Parameters.AddWithValue("#MemberID", memberID);
reader = cmd.ExecuteReader();
while(reader.Read())
{
memberID = reader.GetInt32(reader.GetOrdinal("MemberID"));
name = reader["Name"].ToString();
surname = reader["Surname"].ToString();
}
}
finally
{
if (reader != null) reader.Close();
if (conn != null) conn.Close();
}
Be carefull though, this will only work correctly when there is only one result returned in be the database query. When multiple records are returned only the last will be stored in the variables.
When you need to capture multiple results you will probably want to create a Member class, create an instance for each record and add the instance to a members list. Something like this:
public class Member
{
public int MemberId {get; set;}
public string Name {get; set;}
public string Surname {get; set;}
}
public IList<Member> GetMembers()
{
OleDbConnection conn = null;
OleDbDataReader reader = null;
try
{
conn = new OleDbConnection(
"Provider=Microsoft.Jet.OLEDB.4.0; " +
"Data Source=" + Server.MapPath("MyDataFolder/MyAccessDb.mdb"));
conn.Open();
OleDbCommand cmd =
new OleDbCommand("Select MemberID, Name, Surname FROM MemberDetails", conn);
reader = cmd.ExecuteReader();
var members = new List<Member>();
while(reader.Read())
{
var member = new Member();
member.MemberID = reader.GetInt32(reader.GetOrdinal("MemberID"));
member.Name = reader["Name"].ToString();
member.Surname = reader["Surname"].ToString();
members.Add(member);
}
return members;
}
finally
{
if (reader != null) reader.Close();
if (conn != null) conn.Close();
}
return null;
}

Correct me if I'm wrong, but it looks as though you're attempting to retrieve a row where you have a known MemberID. If that's the case, then you can always do something like this
int memberID = [some number];
DataTable results = new DataTable(); //Your SQL row will be "saved" in here
string command = string.Format("select * from MemberDetails where MemberID = {0}", memberID);
using (SqlDataAdapter sda = new SqlDataAdapter(command, con))
{
sda.Fill(results); //Your DataTable now has your values
}
All you need is something where you can feed the memberID to your condition variable.

Related

How to store multiple SQL data columns into different variables C#

I am trying to store sql data that I have for a voucher id and voucher amount into a variable and display it into a label on a click of a button.
protected void Button1_Click(object sender, EventArgs e)
{
string voucherId = String.Empty;
string voucherAmount = String.Empty;
string queryVoucherId = "select voucherid from ReturnForm where email = '" + Session["username"] + "';";
string queryVoucherAmount = "select voucheramount from ReturnForm where email = '" + Session["username"] + "';";
int index = 0;
using (SqlConnection con = new SqlConnection(str))
{
SqlCommand cmd = new SqlCommand(queryVoucherId, con);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
voucherId = reader[index].ToString();
index++;
}
}
using (SqlConnection con = new SqlConnection(str))
{
SqlCommand cmd = new SqlCommand(queryVoucherAmount, con);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
voucherAmount = reader[index].ToString();
index++;
}
}
if (txtVoucher.Text == voucherId)
{
Label3.Visible = true;
Label3.Text = voucherAmount;
}
}
When I click the button its giving me an error saying that the index is out of bounds.
Building on #JSGarcia's answer - but using parameters as one ALWAYS should - you'd get this code:
string email = Session['username'];
string query = $"SELECT voucherid, voucheramount FROM ReturnFrom WHERE Email = #email";
DataTable dt = new DataTable();
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(query, conn))
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
// set the parameter before opening connection
// this also defines the type and length of parameter - just a guess here, might need to change this
cmd.Parameters.Add("#email", SqlDbType.VarChar, 100).Value = email;
conn.Open();
sda.Fill(dt);
conn.Close();
}
Personally, I'd rather use a data class like
public class VoucherData
{
public int Id { get; set; }
public Decimal Amount { get; set; }
}
and then get back a List<VoucherData> from your SQL query (using e.g. Dapper):
string query = $"SELECT Id, Amount FROM ReturnFrom WHERE Email = #email";
List<VoucherData> vouchers = conn.Query<VoucherData>(query).ToList();
I'd try to avoid the rather clunky and not very easy to use DataTable construct...
I strongly recommend combining your sql queries into a single one, write it into a datatable and continue your logic from there. IMHO it is much cleaner code:
string email = Session['username'];
string query = $"SELECT voucherid, voucheramount FROM ReturnFrom where Email = '{email}'";
DataTable dt = new DataTable();
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = conn.CreateCommand())
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
conn.Open();
sda.Fill(dt);
conn.Close();
}
// Work with DataTable dt from here on
...
Well, one more big tip?
You ONLY as a general rule need a dataadaptor if you going to update the data table.
And you ONLY need a new connection object if you say not using the sql command object.
The sqlcommand object has:
a connection object - no need to create a separate one
a reader - no need to create a separate one.
Note how I did NOT create a seperate connection object, but used the one built into the command object.
And since the parameter is the SAME in both cases? Then why not re-use that too!!
So, we get this:
void TestFun2()
{
String str = "some conneciton???";
DataTable rstVouch = new DataTable();
using (SqlCommand cmdSQL =
new SqlCommand("select voucherid from ReturnForm where email = #email",
new SqlConnection(str)))
{
cmdSQL.Parameters.Add("#email", SqlDbType.NVarChar).Value = Session["username"];
cmdSQL.Connection.Open();
rstVouch.Load(cmdSQL.ExecuteReader());
// now get vouch amount
cmdSQL.CommandText = "select voucheramount from ReturnForm where email = #email";
DataTable rstVouchAmount = new DataTable();
rstVouchAmount.Load(cmdSQL.ExecuteReader());
if (rstVouch.Rows[0]["vourcherid"].ToString() == txtVoucher.Text)
{
Label3.Visible = true;
Label3.Text = rstVouchAmount.Rows[0]["voucheramount"].ToString();
}
}
}

.Rows.Count always returns -1 even if record in database already exists?

Basically I want to check, using c#, if there is a username in the database already existing. If there is not-it must be created.
Below is the code that is doing exactly that(only the checking part matters in my opinion, but I have added the code for the adding part anyways)
Problem is that no matter what-if it exists or not, it always returns -1
public Boolean checkUser()
{
var connection = new MySqlConnection("Server=127.0.0.1;Database=book_library;user=root;password=root2");
var table = new DataTable();
connection.Open();
string checkUsernameQuery = "SELECT * FROM accounts WHERE username = 'usernameInputField.Text'";
var adapter = new MySqlDataAdapter();
MySqlCommand command = new MySqlCommand(checkUsernameQuery, connection);
//command.Parameters.Add("#username", MySqlDbType.VarChar).Value = usernameInputField.Text;
adapter.SelectCommand = command;
adapter.Fill(table);
if (table.Rows.Count > 0)
{
return true;
}
else
{
return false;
}
}
Here is the adding part(just adding it, but it is not too related with the problem)
private void registerIconButton_Click(object sender, EventArgs e)
{
checkUser();
var connection = new MySqlConnection("Server=127.0.0.1;Database=book_library;user=root;password=root2");
connection.Open();
string insertQuery = "INSERT INTO `accounts` (username, password, email) VALUES ('" + usernameInputField.Text + "','" + passwordInputField.Text + "','" + emailInputField.Text + "')";
MySqlCommand command = new MySqlCommand(insertQuery, connection);
command.Parameters.Add("#username", MySqlDbType.VarChar).Value = usernameInputField.Text;
command.Parameters.Add("#password", MySqlDbType.VarChar).Value = passwordInputField.Text;
command.Parameters.Add("#email", MySqlDbType.VarChar).Value = emailInputField.Text;
if (checkUser())
{
MessageBox.Show("This username already exists!");
}
else
{
if (command.ExecuteNonQuery() == 1)
{
}
else
{
MessageBox.Show("ERROR");
}
}
connection.Close();
}
Connections and Commands are disposable so you should put them inside using blocks to deterministically clean up resources.
If you just want to know if something exists, you can use ExecuteScalar instead of using a heavy-weight adapter.
Then just return the result of the expression != null to get your boolean that indicates if the user is there or not.
using(var connection = new MySqlConnection("Server=127.0.0.1;Database=book_library;user=root;password=root2"))
using(var cmd = connection.CreateCommand())
{
connection.Open();
string checkUsernameQuery = "SELECT TOP 1 username FROM accounts WHERE username = #p1";
cmd.Parameters.Add(new MySqlParameter("#p1", MySqlDbType.VarChar).Value = usernameInputField.Text;
var user = cmd.ExecuteScalar();
return user != null;
}

Exception: Invalid attempt to Read when reader is closed

I am trying to update my database while reading data from it, but the reader gets closed and it throws the exception that it can''t read wen reader is closed. Is the update.ExecuteNonQuery() closing the reader method?
If i get rid of linescon.Close(); con.Open(); i get There is already an open DataReader associated with this Connection which must be closed first.
So how can i update my database records while keep the reading opened?
{
public class MySqlReadUpdate
{
public int Id { get; set; }
public string Notes { get; set; }
}
static void Main()
{
List<MySqlReadUpdate> dbData = new List<MySqlReadUpdate>();
var config = "server=localhost;user id=root; database=restaurants; pooling=false;SslMode=none;Pooling=True";
MySqlConnection con = new MySqlConnection(config);
MySqlDataReader reader = null;
string query = "SELECT id, notes FROM customers";
MySqlCommand command = new MySqlCommand(query, con);
con.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
MySqlReadUpdate newMySqlReadUpdate = new MySqlReadUpdate();
newMySqlReadUpdate.Id = (int)reader["id"];
newMySqlReadUpdate.Notes = (string)reader["notes"];
string note = newMySqlReadUpdate.Notes;
var notesplit = note.Split(' ', '\n')[1];
dbData.Add(newMySqlReadUpdate);
Console.WriteLine(newMySqlReadUpdate.Id);
Console.WriteLine(newMySqlReadUpdate.Notes);
Console.WriteLine(note);
Console.WriteLine(notesplit);
con.Close();
con.Open();
string query2 = "UPDATE customers SET notes='" + notesplit + "' WHERE id='" + newMySqlReadUpdate.Id + "';";
MySqlCommand update = new MySqlCommand(query2, con);
update.ExecuteNonQuery();
}
con.Close();
Console.WriteLine("Finished!");
Console.Read();
}
}
}
You cannot close a connection like you are, because the data reader depends on it. Once you call con.Close you break it. That's why you see an exception the next time it gets to reader.Read().
What you want is to add MultipleActiveResultSets=True in the configuration string; however, as we discussed in the comments it's apparently still not supported in MySQL. Therefore, the answer is two connection instances.
List<MySqlReadUpdate> dbData = new List<MySqlReadUpdate>();
var config = "server=localhost;user id=root;database=restaurants;pooling=false;SslMode=none";
MySqlConnection con = new MySqlConnection(config);
MySqlConnection cmdCon = new MySqlConnection(config);
MySqlDataReader reader = null;
string query = "SELECT id, notes FROM customers";
MySqlCommand command = new MySqlCommand(query, con);
con.Open();
cmdCon.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
MySqlReadUpdate newMySqlReadUpdate = new MySqlReadUpdate();
newMySqlReadUpdate.Id = (int)reader["id"];
newMySqlReadUpdate.Notes = (string)reader["notes"];
string note = newMySqlReadUpdate.Notes;
var notesplit = note.Split(' ', '\n')[1];
dbData.Add(newMySqlReadUpdate);
Console.WriteLine(newMySqlReadUpdate.Id);
Console.WriteLine(newMySqlReadUpdate.Notes);
Console.WriteLine(note);
Console.WriteLine(notesplit);
string query2 = "UPDATE customers SET notes='" + notesplit + "' WHERE id='" + newMySqlReadUpdate.Id + "';";
MySqlCommand update = new MySqlCommand(query2, cmdCon);
update.ExecuteNonQuery();
}
con.Close();
cmdCon.Close();
Console.WriteLine("Finished!");
Console.Read();
I would recommend that you also modify your code to use using statements or wrap things in try-finally blocks.

WebService only returning first row using a sql queryC#

I have the following code
public class dthvendas: System.Web.Services.WebService {
public class typVenda
{
//public string campanha;
public string id;
public string contact_moment;
public string nome;
// few more properties
}
[WebMethod][SoapDocumentMethod]
public typVenda getListaVendas(string dt_min, string dt_max)
{
//venda vendas = new List<venda>();
typVenda objVenda = new typVenda();
SqlConnection con = new SqlConnection(#"Data Source=server;Initial Catalog=database;User ID=user;password=password");
//SqlCommand cmd = new SqlCommand("SELECT * FROM dbo where contact_moment >='" + dt_min + "' AND contact_moment <DATEADD(dd, 1, '" + dt_max + "')", con);
SqlCommand cmd = new SqlCommand("SELECT * FROM dbo.vcnosadesoes_getlistavendas", con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
//var objVenda = new typVenda();
//objVenda.campanha = dr["id"].ToString();
objVenda.id = dr["id"].ToString();
objVenda.contact_moment = dr["contact_moment"].ToString();
objVenda.nome = dr["nome"].ToString();
objVenda.pacote = dr["pacote"].ToString();
objVenda.telefone = dr["telefone"].ToString();
objVenda.codigo_wc = dr["codigo_wc"].ToString();
//vendas.Add(objVenda);
}
dr.Close();
}
con.Close();
return objVenda;
//return vendas.ToArray();
}
The problem is that is only returning the first row instead of all rows from the table. What could be the problem any ideas?
Also when i return it says "This XML file does not appear to have any style information associated with it. The document tree is shown below." It should have a header like this:
<?xml version="1.0" encoding="UTF‐8" ?>
If you have n fetched rows available in the reader, probably you will get the last row, since the created object's properties ware over writted in each iteration of the while (dr.Read()) and finally return the latest value to the calling method. You should re-define your method to return List<typVenda>, and hence populate the list with objects constructed in each iteration. and finally return the list at the end of iteration.
Few more suggestions For you to improve the Code:
Make use of using while dealing with SqlConnection and SqlCommand; since you need not to bother about the close connection and disposing commands etc. using will take care of these things
Need not to check the reader has rows or not (if (dr.HasRows)) use while (dr.Read()) will not execute the enclosed statements if there are no rows.
Now consider the following code:
public List<typVenda> getListaVendas(string dt_min, string dt_max)
{
List<typVenda> objVendaList = new List<typVenda>();
using (SqlConnection con = new SqlConnection("connection String here"))
{
using (SqlCommand cmd = new SqlCommand("SELECT * FROM dbo.vcnosadesoes_getlistavendas", con))
{
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
var objVenda = new typVenda();
// Assign the values to the properties here
objVendaList.Add(objVenda);
}
dr.Close();
}
}
return objVendaList;
}
public List<typVenda> getListaVendas(string dt_min, string dt_max)
{
venda vendas = new List<typVenda>();
typVenda objVenda = new typVenda();
SqlConnection con = new SqlConnection(#"Data Source=server;Initial Catalog=database;User ID=user;password=password");
//SqlCommand cmd = new SqlCommand("SELECT * FROM dbo where contact_moment >='" + dt_min + "' AND contact_moment <DATEADD(dd, 1, '" + dt_max + "')", con);
SqlCommand cmd = new SqlCommand("SELECT * FROM dbo.vcnosadesoes_getlistavendas", con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
var objVenda = new typVenda();
//objVenda.campanha = dr["id"].ToString();
objVenda.id = dr["id"].ToString();
objVenda.contact_moment = dr["contact_moment"].ToString();
objVenda.nome = dr["nome"].ToString();
objVenda.pacote = dr["pacote"].ToString();
objVenda.telefone = dr["telefone"].ToString();
objVenda.codigo_wc = dr["codigo_wc"].ToString();
vendas.Add(objVenda);
}
dr.Close();
}
con.Close();
return vendas;
}

asp.net web api with Mysql database

I have a background in PHP and bump into a problem while trying out ASP.NET webAPI.
I have a MySQL database and a table that contains some files information.
Now i want to make a "SELECT * FROM Files" and see the result in XML.
How can i render the result of the query that is returned?
This is my code at the moment,
The Model:
namespace ProductsApp.Models
{
public class File
{
public int Id {get; set;}
public string Text {get; set;}
}
}
The Controller:
public IEnumerable<File> Get()
{
try
{
command = conn.CreateCommand();
command.CommandText = "SELECT * FROM Files";
conn.Open();
MySqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
//How to output the rows ????
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return null; // return the list
}
Making some assumptions about your File Table, this is how you get the data
public IEnumerable<File> Get()
{
List<File> list = new List<File>();
try
{
command = conn.CreateCommand();
command.CommandText = "SELECT * FROM Files";
conn.Open();
using(MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
//How to output the rows ????
int id = (int) reader["Id"];//Assuming column name is 'Id' and value if typeof(int)
string text = (string) reader["Text"];//Assuming column name is `Text` and typeof(string)
var file = new File {Id = id, Text = text};
list.Add(file);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return list; // return the list
}
As for the xml that is a formatting setting that needs to be allowed on the request.
Given the default setup of WebApi once the client making the call requests text/xml as the content type then the result should be parsed to xml and returned to the client.
If it is you want to force the response to always be xml then you need to make some changes to the response. One way is to set the Content-Type header before returning your result.
Response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("text/xml;charset=utf-8");
There are other ways you can do this and there are many answers on SO that will be able to show you.
Webconfig:
public static MySqlConnection conn()
{
string conn_string = "server=localhost;port=3306;database=testmvc;username=root;password=root;";
MySqlConnection conn = new MySqlConnection(conn_string);
return conn;
}
Controller :
public MySqlConnection con = WebApiConfig.conn();
public IHttpActionResult GetAllProduct()
{
IList<product> pro = null;
try
{
con.Open();
MySqlCommand cmd = new MySqlCommand("select * from product", con);
cmd.CommandType = CommandType.Text;
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
pro = ds.Tables[0].AsEnumerable().Select(dataRow => new product { Pname = dataRow.Field<string>("pname"), Pid = dataRow.Field<int>("pid"), Pprice = dataRow.Field<decimal>("pprice") }).ToList();
}
finally
{
con.Close();
}
if (pro.Count == 0)
{
return NotFound();
}
return Ok(pro);
}
public IHttpActionResult PostNewProduct(product pro)
{
try
{
con.Open();
MySqlCommand cmd = new MySqlCommand();
cmd.Connection = con;
cmd.CommandText = "SELECT MAX(pid) from product";
cmd.CommandType = CommandType.Text;
int maxid = Convert.ToInt16(cmd.ExecuteScalar().ToString())+1;
cmd.CommandText = "insert into product values(" + maxid + ",'" + pro.Pname + "'," + pro.Pprice + ")";
cmd.ExecuteNonQuery();
}
finally
{
con.Close();
}
return Ok();
}
public IHttpActionResult PutOldProduct(product pro)
{
string sql = "update product set pname='" + pro.Pname + "',pprice=" + pro.Pprice + " where pid=" + pro.Pid + "";
try
{
con.Open();
MySqlCommand cmd = new MySqlCommand(sql, con);
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
}
finally
{
con.Close();
}
return Ok();
}
public IHttpActionResult Delete(int id)
{
string sql = "delete from product where pid=" + id + "";
try
{
con.Open();
MySqlCommand cmd = new MySqlCommand(sql, con);
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
}
finally
{
con.Close();
}
return Ok();
}

Categories

Resources