I have two tables in my database, (Users and Cities) and I want to select all the data in this tables where the column UserID=1 in Users table.
But the Dataset does not find my tables (Users and Cities)
This is my SQL Query:
SELECT * FROM Users INNER JOIN Cities ON Cities.CityID=Users.CityID WHERE Users.UserID=1
And this is the Mathod:
public static DataSet GetData(string SqlQuery)
{
OleDbConnection con = new OleDbConnection(conString);
OleDbCommand cmd = new OleDbCommand(SqlQuery, con);
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
Code:
DataSet ds = GetData(myQuery);
string fname = ds.Tables["Users"].Rows[0]["UserFisrtName"].ToString();
string lname = ds.Tables["Users"].Rows[0]["UserLastName"].ToString();
string city = ds.Tables["Cities"].Rows[0]["CityName"].ToString();
string output = "Name: " + fname + " " + lname + " City: " + city;
If you want 2 datatables in the data set, change the sql query to this.
SELECT * FROM Users WHERE Users.UserID=1; select * from City where CityID in (Select cityid from users where userID = 1);
The user table will then be on ds.Tables[0] and the city table on ds.Tables[1].
Please remember to use the using clause to ensure connections, etc are properly disposed.
public static DataSet GetData(string SqlQuery)
{
using(var con = new OleDbConnection(conString))
using(var cmd = new OleDbCommand(SqlQuery, con))
using(var da = new OleDbDataAdapter(cmd))
{
var ds = new DataSet();
da.Fill(ds);
return ds;
}
}
Code:
var ds = GetData(myQuery);
var fname = ds.Tables[0].Rows[0]["UserFisrtName"].ToString();
var lname = ds.Tables[0].Rows[0]["UserLastName"].ToString();
var city = ds.Tables[1].Rows[0]["CityName"].ToString();
var output = "Name: " + fname + " " + lname + " City: " + city;
I found the answer, in the sql query
SELECT * FROM Users, Cities WHERE Users.CityID=Cities.CityID AND Users.UserID=1
You are filling the dataset only with one table, this because the Sql statement only return a one set of data. For access the tables you use indexes, only the columns name will be mapped in the rows of the table so this values can be access by index or by name.
SELECT * FROM Users INNER JOIN Cities ON Cities.CityID=Users.CityID WHERE Users.UserID=1
Also avoid use SELECT * this because you force the database engine to search for the columns of all the tables instead to only use the you already provided, and if you will not use all or someone change te order of it in the table, can be a future problem.
In a Dataset your tables will not automatically have the names of the tables from which they are selected. Use the ordinals instead:
DataSet ds = GetData(myQuery);
string fname = ds.Tables[0].Rows[0]["UserFisrtName"].ToString();
string lname = ds.Tables[0].Rows[0]["UserLastName"].ToString();
string city = ds.Tables[0].Rows[0]["CityName"].ToString();
string output = "Name: " + fname + " " + lname + " City: " + city;
Related
I am using C# to create a windows form.
I am trying to set a condition statement for a particular value that is retrieved from my database by the onclick of a button. The datatype of the column is 'integer'.
Below is my code:
string checkquantity = "SELECT `inventory_item`.`Item_Quantity_Available`FROM `inventory_item` , `patient`, `out_treatment`WHERE `inventory_item`.`Item_ID` = `out_treatment`.`Inventory_ID`AND `patient`.`Patient_ID` = `out_treatment`.`Patient_ID`AND `out_treatment`.`Patient_ID`= '" + pid + "' ";
MySqlCommand selectout = new MySqlCommand(checkquantity, connect);
MySqlDataAdapter selectdata = new MySqlDataAdapter(checkquantity, connect);
DataTable selecttable = new DataTable();
selectdata.Fill(selecttable);
DataSet ds = new DataSet();
selectdata.Fill(selecttable);
selectdata.Fill(ds);
int i = ds.Tables[0].Rows.Count;
if ( i <= 0)
{
MessageBox.Show("Out of Stock");
}
I'm new with c#.
I don't think the int i = ds.Tables[0].Rows.Count; is the right way.
Any help is much appreciated.
First of all, like #Flydog57 said, you should not concatenate your sql query. The best way is to use parameters, for example:
string checkquantity = "SELECT i.Item_Quantity_Available " +
" FROM inventory_item i JOIN out_treatment t ON i.Item_Id = t.Inventory_ID " +
" JOIN patient p ON t.Patient_ID = p.PatiendID " +
" WHERE t.Patient_ID = #Patiend_ID";
MySqlCommand selectout = new MySqlCommand(checkquantity, connect);
// set the parameter value
selectout.Parameters.AddWithValue("#Patiend_ID", patient_id_value);
MySqlDataReader rdr = cmd.ExecuteReader();
if (rdr.Read())
{
if ((int)rdr["Item_Quantity_Available"] == 0)
MessageBox.Show("Out of Stock");
}
In second place, you could use a MySqlDataReader to verify that Item_Quantity_Available is equal to 0, like in the previous example. Otherwise, If you just wants to verify if there is data, the condition could be something like that:
if (!rdr.Read())
{
MessageBox.Show("Out of Stock");
}
The third improvemente is to join tables with the join clause.
My table structure is as follows:
Session
--------------
SessionID (PK)
RoomID
SessionDate
SessionTimeStart
SessionTimeEnd
I have a following query which will always return one row and display in DGV. I use DataAdapter for connection:
DataTable queryResult = new DataTable();
string ConnStr = "Data Source=DUZY;Initial Catalog=AutoRegSQL;Integrated Security=True";
SqlConnection MyConn = new SqlConnection(ConnStr);
MyConn.Open();
//SQL query that returns todays sessions for the given roomID
string query = #"SELECT SessionID, RoomID, SessionDate, SessionTimeStart, SessionTimeEnd" +
" FROM [Session] " +
" WHERE RoomID = #RoomID " +
" AND SessionDate = cast(getdate() as date) ";
SqlCommand command = new SqlCommand(query, MyConn);
command.Parameters.Add("RoomID", SqlDbType.Char).Value = RoomID;
SqlDataAdapter adapter = new SqlDataAdapter(command);
adapter.Fill(queryResult);
I would like to save the query result into multiple strings representing table columns, i.e.
SessionIDstring = query result for SessionID column
RoomIDstring = query result for RoomID column
and so on...
Is it possible to achieve it using one query, or do I have to create 5 queries for each column?
Something similar to this, perhaps, using ADO.NET?
//SQL query that returns todays sessions for the given roomID
string query = #"SELECT SessionID, RoomID, SessionDate, SessionTimeStart, SessionTimeEnd" +
" FROM [Session] " +
" WHERE RoomID = #RoomID " +
" AND SessionDate = cast(getdate() as date) ";
using (var connection = new SqlConnection(ConnStr))
using (var command = new SqlCommand(query, connection))
{
command.Parameters.Add("RoomID", SqlDbType.Char).Value = RoomID;
try
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
// Note that reader[x] has the equivalent type to the type
// of the returned column, converted using
// http://msdn.microsoft.com/en-us/library/cc716729.aspx
// .ToString() if the item isn't null is always ok
string SessionIDstring = reader[0].ToString(); // it should be an int
// reading it twice is ok
int RoomID = (int)reader[1]; // it should be an int
string RoomIDstring = reader[1].ToString(); // it should be an int
if (reader.Read())
{
throw new Exception("Too many rows");
}
}
else
{
throw new Exception("No rows");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
This code was adapted from MSDN ADO.NET Code Examples. I added some usings and made it single row. I don't even want to know why MSDN examples don't go the full length with using.
Note that SqlDataAdapter are built to recover multiple rows/big data and put them in a DataSet. You can use them for single row data, but it's much easier to simply use a SqlDataReader if you only want to fill some variables.
declare #col1 int
declare #col2 varchar(42)
select #col1 = col1
, #col2 = col2
, ....
You could create a class like so...
public class SessionDto
{
public string SessionID {get; set;}
public string RoomID {get; set;}
public string SessionDate {get; set;}
public string SessionTimeStart {get; set;}
public string SessionTimeEnd {get; set;}
}
And then have a method that takes a Room ID and builds your session object
public SessionDto GetSessionData(int roomId)
{
using (var cnn = new SqlConnection(ConnStr))
{
SessionDto sessionDto;
string query = #"SELECT SessionID, RoomID, SessionDate, SessionTimeStart, SessionTimeEnd" +
" FROM [Session] " +
" WHERE RoomID = #RoomID " +
" AND SessionDate = cast(getdate() as date) ";
cnn.Open();
using (var cmd = new SqlCommand(query,cnn))
{
cmd.Parameters.Add("#RoomID", SqlDbType.Char).Value = roomId;
using (var rdr = cmd.ExecuteReader())
{
if (rdr.HasRows)
{
while (rdr.Read())
{
sessionDto = new sessionDto{
SessionID = rdr.GetString(0),
RoomID = rdr.GetString(1),
SessionDate = rdr.GetString(2),
SessionTimeStart = rdr.GetString(3),
SessionTimeEnd = rdr.GetString(4)
};
}
}
}
}
}
return sessionDto;
}
A lot of this is hand typed as I havent got access to VS right now,
but you should get it to work.
Also, I have used rdr.GetString(), there are other methods for GetType().
I'm trying to translate some perl code into C# and I'm having some trouble with the following.
After establishing a sql server connection and executing the select statement, how do I reference the different elements in the table columns. For example, in Perl it looks like:
my $dbh = DBI -> connect( NAME, USR, PWD )
or die "Failed to connect to database: " . DBI->message;
my $dbname = DB_NAME;
my $dbschema = DB_SCHEMA;
my $sql = qq{select a,b,c,d,e,f,g,h,i,...
from $dbname.$dbschema.package p
join $dbname.$dbschema.package_download pd on p.package_id = pd.package_id
join $dbname.$dbschema.download d on pd.download_id = d.download_id
where p.package_name = '$package'
--and ds.server_address like 'tcp/ip'
order by a,b,c,d,..};
my $sth = $dbh -> prepare( $sql )
or die "Failed to prepare statement: " . $dbh->message;
$sth -> execute()
or die "Failed to execute statement: " . $sth->message;
#now to go through each row in result table
while ( #data = $sth->fetchrow_array() )
{
print "$data[0]";
# If source server FTP is not already open, make new FTP
if ( $data[0] != $src_id )
{
if ( $src_ftp )
{ $src_ftp -> quit; }
$src_ftp = make_ftp( $data[1], $data[2], $data[3], $data[18], $data[19], $data[20] );
$src_id = $data[0];
}
}
so far I've got it down to
string db = NAME;
string myConnectionString = "Data Source=ServerName;" + "Initial Catalog=" + db + "User id=" + ODBC_USR + "Password=" + PWD
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myInsertQuery = "select a,b,c,d,e,f,g,h,i,...
from $dbname.$dbschema.package p
join $dbname.$dbschema.package_download pd on p.package_id = pd.package_id
join $dbname.$dbschema.download d on pd.download_id = d.download_id
where p.package_name = '$package'
--and ds.server_address like 'tcp/ip'
order by a,b,c,d,..";
SqlCommand myCommand = new SqlCommand(myInsertQuery);
myCommand.Connection = myConnection;
myConnection.Open();
myCommand.ExecuteNonQuery();
myCommand.Connection.Close();
but how do I reference the columns like data[0] and data[1] in C#. Sorry I'm new to both languages so my background is severely lacking. Thanks!
You could reference your column directly by its column name or by numeric order (it starts with 0 as the first column) either through a DataTable, DataSet, DataReader or a specific DataRow.
For the sake of example i'll use a DataTable here and I will name it as dt and let's say we want to reference the first row then you could reference it with the following Syntax/Format:
dt[RowNumber]["ColumnName or Column Number"].ToString();
For example:
dt[0]["a"].ToString();
Or by number the first column with be 0 like:
dt[0][0].ToString();
And use Parameters by the way because without which it would be susceptible to SQL Injection. Here's a more complete code below:
string db = NAME;
string myConnectionString = "Data Source=ServerName;" + "Initial Catalog=" + db + "User id=" + ODBC_USR + "Password=" + PWD
using (SqlConnection connection = new SqlConnection(myConnectionString))
{
string mySelectQuery = #"SELECT a,b,c,d,e,f,g,h,i,...
FROM package p
JOIN package_download pd on p.package_id = pd.package_id
join download d on pd.download_id = d.download_id
WHERE p.package_name = #PackageName
AND ds.server_address LIKE 'tcp/ip%'
ORDER by a,b,c,d";
try
{
connection.Open();
using (SqlDataAdapter da = new SqlDataAdapter(mySelectQuery, connection))
{
using (SqlCommand cmd = new SqlCommand())
{
da.SelectCommand.Parameters.AddWithValue("#PackageName", txtPackage.Text);
DataTable dt = new DataTable();
da.Fill(dt);
if (dt.Rows.Count>0) // Make sure there is something in your DataTable
{
String aVal = dt[0]["a"].ToString();
String bVal = dt[0]["b"].ToString();
// You'll be the one to fill up
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I change your LIKE 'tcp/ip' to LIKE 'tcp/ip%' by the way which is the more appropriate one of using LIKE.
you can use ado.net entity data table to reference the tables in your sql server. I don't know if you're asking exactly this but it may help. because direct referencing to sql server is not possible as far as i know.
I want to get max size of any column of a table using datatable in C#. Example is that if i have a table in database named dept and its attributes are NAME and ADDRESS and i have set size of NAME as varchar(50) and Address as varchar(30).
Now i want to get 50 and 30.....
i have written this code
DataSet ds1 = new DataSet();
DataSet ds = new DataSet();
string query = Form1.query1Pass;
SqlCommand cmd = new SqlCommand(query.ToString(), con);
this.tablename1 = query.Substring(query.LastIndexOf("from")+4); ;
cmd.ExecuteNonQuery();
SqlDataAdapter adp = new SqlDataAdapter(cmd);
adp.Fill(this.ds);
string query2 = Form1.query2Pass;
cmd = new SqlCommand(query2, con);
adp = new SqlDataAdapter(cmd);
adp.Fill(this.ds1);
StringBuilder datatype2 = new StringBuilder();
this.datatype2.Append("Data Type Conflict: ");
this.datetimeCon.Append("DateTime Format Conflict: ");
DataTable table1 = this.ds.Tables[0];
DataTable table2 = this.ds1.Tables[0]; ;
DataColumnCollection col1 = table1.Columns;
DataColumnCollection col2 = table2.Columns;
foreach (DataColumn ds in col1) {
foreach (DataColumn ds2 in col2) {
if (ds.ColumnName.Equals(ds2.ColumnName)) {
if (!ds.DataType.Equals(ds2.DataType)) {
this.datatype2.Append(ds.ColumnName + "<" + ds.DataType + ">, " + ds2.ColumnName + "<" + ds2.DataType + ">,");
}
else
if (ds.MaxLength!=ds2.MaxLength) {
maxLength.Append(ds.ColumnName+"<"+ds.MaxLength+">, "+ds2.ColumnName+"<"+ds2.MaxLength+">,");
}
}
}
}
I assume that the columns are not Text columns. The MaxLength property is only set on columns with DataType=String. MSDN:
The MaxLength property is ignored for non-text columns. A
ArgumentException exception is raised if you assign MaxLength to a
non-string column.
By the way, you might want to use a LINQ approach, but that's a matter of taste:
var t1Cols = table1.Columns.Cast<DataColumn>();
var t2Cols = table2.Columns.Cast<DataColumn>();
var diffTypes =
from t1Col in t1Cols
join t2Col in t2Cols on t1Col.ColumnName equals t2Col.ColumnName
where t1Col.DataType != t2Col.DataType
select string.Format("{0}<{1}>,{2}<{3}>",
t1Col.ColumnName, t1Col.DataType, t2Col.ColumnName, t2Col.DataType);
var diffMaxLength =
from t1Col in t1Cols
join t2Col in t2Cols on t1Col.ColumnName equals t2Col.ColumnName
where t1Col.MaxLength != t2Col.MaxLength
select string.Format("{0}<{1}>,{2}<{3}>",
t1Col.ColumnName, t1Col.MaxLength, t2Col.ColumnName, t2Col.MaxLength);
Console.WriteLine("diff. Types: " + string.Join(", ", diffTypes));
Console.WriteLine("diff. max Length: " + string.Join(", ", diffMaxLength));
I have a C# webservice on a Windows Server that I am interfacing with on a linux server with PHP. The PHP grabs information from the database and then the page offers a "more information" button which then calls the webservice and passes in the name field of the record as a parameter. So i am using a WHERE statement in my query so I only pull the extra fields for that record. I am getting the error:
System.Data.SqlClient.SqlException:Invalid column name '42'
Where 42 is the value from the name field from the database.
my query is
string selectStr = "SELECT name, castNotes, triviaNotes FROM tableName WHERE name =\"" + show + "\"";
I do not know if it is a problem with my query or something is wrong with the database, but here is the rest of my code for reference.
NOTE: this all works perfectly when I grab all of the records, but I only want to grab the record that I ask my webservice for.
public class ktvService : System.Web.Services.WebService {
[WebMethod]
public string moreInfo(string show) {
string connectionStr = "MyConnectionString";
string selectStr = "SELECT name, castNotes, triviaNotes FROM tableName WHERE name =\"" + show + "\"";
SqlConnection conn = new SqlConnection(connectionStr);
SqlDataAdapter da = new SqlDataAdapter(selectStr, conn);
DataSet ds = new DataSet();
da.Fill(ds, "tableName");
DataTable dt = ds.Tables["tableName"];
DataRow theShow = dt.Rows[0];
string response = "Name: " + theShow["name"].ToString() + "Cast: " + theShow["castNotes"].ToString() + " Trivia: " + theShow["triviaNotes"].ToString();
return response;
}
}
Quick solution:
I believe you need single quotes in your selectStr:
string selectStr =
"SELECT name, castNotes, triviaNotes FROM tableName WHERE name = '" + show + "'";
More information:
In .NET, you'll want to be sure you close out any connections explicitly when you no longer need them. The easiest way to do this is to wrap using statements around any types that implement IDisposable, such as SqlConnection in this case:
using(SqlConnection conn = new SqlConnection(connectionStr))
{
SqlDataAdapter da = new SqlDataAdapter(selectStr, conn);
DataSet ds = new DataSet();
da.Fill(ds, "tableName");
DataTable dt = ds.Tables["tableName"];
DataRow theShow = dt.Rows[0];
string response = "Name: " + theShow["name"].ToString() + "Cast: " + theShow["castNotes"].ToString() + " Trivia: " + theShow["triviaNotes"].ToString();
return response;
}
Additionally, it looks like your code could be easily subject to SQL injection. What if someone submits a form with the value: fake name' OR 1=1;DROP DATABASE someDbName;--?
You'll want to take advantage of SQL parameters, something like:
SqlCommand cmd = new SqlCommand(
"SELECT name, castNotes, triviaNotes FROM tableName WHERE name = #show", conn);
cmd.Parameters.AddWithValue("#show", show);
Shouldn't the WHERE clause be WHERE name = '" + show + "'"; Strings should be enclosed in single quotes and not double quotes for SQL statements.
Also the System.Data.SqlClient namespace is for SQL Server and not MySQL. See MySQL official docs for connecting to MySQL via C#.