Let's say I have a table with 3 columns like this:
ID | NAME | Subject
---+------+----------
1 | Mark | English
1 | Mark | Math
2 | Matt | Math
2 | Matt | English
1 | Mark | History
How to get each subject of "Mark" like English, Math, History (order by) that will match to their id in every row in column subject? Because I only get the first subject which is "English" or the first row.
string sql = "select * from tbl_Student where ID like '"+ID.Text+"'";
cm = new SqlCommand(sql, cn);
dr = cm.ExecuteReader();
while (dr.Read())
{
Subject1.Text = dr["Subject"].ToString();
Subject2.Text = dr["Subject"].ToString();
Subject3.Text = dr["Subject"].ToString();
}
dr.Close();
You replace the value of Subject.Text in each loop. That means it contains only the last value.
You should concatenate the string
Subject.Text += dr["Subject"].ToString();
I would definitely change the like operator to an equal(=) operator.
And you are having always one value in the loop, concatenate the strings.
Use StringBuilder:
StringBuilder sb = new StringBuilder();
while (dr.Read())
{
sb.Append(dr["Subject"].ToString());
sb.Append(",");
}
result = sb.ToString().TrimEnd(',');
UPDATE
use switch/case then, to determine your id and assign its value to proper TextBox:
while (dr.Read())
{
string subject = dr["Subject"].ToString();
switch (dr["ID"].ToString())
{
case "1":
Subject1.Text += subject + " ";//$"{subject} "; //or use string builder as I've showed above
break;
case "2":
Subject2.Text += subject + " ";//$"{subject} ";
break;
case "3":
Subject3.Text += subject + " ";//$"{subject} ";
break;
default:
break;
}
}
Also, please use Parameterized Queries.
Related
I have this table called WeeklySales with 2 columns, DateandTime and Sales. Now, I have 3 textbox on my form. I wanted to get the latest value that was added on the table so I have this string.
string sql = "SELECT Sales FROM database.weeklysales ORDER BY DateandTime DESC LIMIT 3";
Now, I have this database(lets say that month is the date),
DateandTime | Sales
March | $300
February | $500
January | $400
and get this result with that string:
Sales
$300
$500
$400
Now, I wanted to put the first row into first textbox, then second row to second textbox and so on... Now, I do not know what to out in inside the Datareader...
try
{
con.Open();
using (reader = cmd.ExecuteReader())
{
first.Text = ?
second.Text = ?
third.Text = ?
}
}
finally
{
con.Close();
}
I have searched but they only get the first row unfortunately.
Since you only have 3 text boxes to fill - no loop just advance the reader manually.
MySqlDataReader dr = cmd.ExecuteReader();
dr.Read();
first.Text = dr.GetValue(0).ToString();
dr.Read();
second.Text = dr.GetValue(0).ToString();
dr.Read();
third.Text = dr.GetValue(0).ToString();
The SqlDataReader class has a Read() method, which returns a bool as long as there are more rows to read. You can use it to read multiple rows using a while loop for example.
using (SqlDataReader reader = cmd.ExecuteReader()
{
while (reader.Read())
{
//Do your stuff here
}
}
See https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.read%28v=vs.110%29.aspx for further information
Following code will be helpful to you,
using (reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
int i = 1;
while (reader.Read())
{
switch (i)
{
case 1:
first.Text = reader["Sales"].ToString();
break;
case 2:
second.Text = reader["Sales"].ToString();
break;
default:
third.Text = reader["Sales"].ToString();
break;
}
i += 1;
}
}
}
Avoiding repetitions or in case of multiple objects
public void Example(MySqlDataReader dr)
{
TextBox a = new TextBox();
TextBox b = new TextBox();
TextBox c = new TextBox();
foreach(TextBox current in new List<TextBox> { a, b, c })
{
dr.Read();
current.Text = dr.GetValue(0).ToString();
}
}
I have an Access table which looks like this:
ID | col_1 | col_2 | col_n
1 | 12345 | ... | ...
1 | null | ... | ...
1 | null | ... | ...
2 | 67891 | ... | ...
What I want to accomplish is to get all col_1 with the ID 1 if there is at least one value in col_1 with that ID. So my result would be:
ID | col_1
1 | 12345
1 | null
1 | null
The following code gets me the all the values of ID and col_1 and stores them in a DataTable results0.
public void ConnectDB(string path, string query0, string query1)
{
string connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Persist Security Info=False";
try
{
using (OleDbConnection conn = new OleDbConnection(connString))
{
DataTable results0 = new DataTable();
OleDbCommand cmd = new OleDbCommand(query0, conn);
conn.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
adapter.Fill(results0);
}
}
catch (System.InvalidOperationException inv)
{
MessageBox.Show(inv.Message);
throw;
}
}
I wanted to use LINQ for this issue, since I don't want to loop through the rows and tried a few things without success. At first I thought something like this would give me the relevant values (which it does)
int id = 1;
for (int i = 0; i < 9; i++) // iterate through IDs and increment
{
IEnumerable<String> Ids =
results0
.AsEnumerable()
.Where(row => row.Field<Int32>("ID") == id)
.Select(row => row.Field<String>("FERI"));
id+=1;
}
but I'm not sure how to rephrase it in an if-statement. Something like "If ID = 1 and at least one value in col_1 get range of rows with ID = 1"
I hope this isn't too confusing.
Any help and suggestions are appreciated!
Update: I'm still having trouble getting the relevant rows. I tried using DataRow[], selecting all the rows with ID = 1 and iterating with foreach-loops but this doesn't seem really efficient. Can anyone help?
To get the list of records with ID==1 from the Database assuming database with name "DBName", we will have:
public DBName _dbContext = new DBName ();
and then using following LINQ query we will get result:
_dbContext.TableName.Where(u => u.ID == 1).Select(u => u.col_1 ).ToList();
Real easy.
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("col_1", typeof(int));
dt.Columns["col_1"].AllowDBNull = true;
dt.Rows.Add(new object[] { 1, 12345});
dt.Rows.Add(new object[] { 1, null});
dt.Rows.Add(new object[] { 1, null});
dt.Rows.Add(new object[] { 2, 67891});
int id = 1;
DataTable dt2 = dt.AsEnumerable().Where(x => x.Field<int>("ID") == id).CopyToDataTable();
So, I know that you can populate information to a data grid from a SQL server. But is there a reverse process but to a different table to do so?
For instance having a master list and using other tables.
Example:
Master Table: (Displayed on datagrid1)
| OtherTableName| TestSubj | TestCriteria |
----------------------------------------------
| TableName | ValueSubj | ValueCriteria |
----------------------------------------------
| TableName | ValueSubj | ValueCriteria |
----------------------------------------------
Other Table
| TestSubj | TestCriteria |
-----------------------------
| ValueSubj | ValueCriteria |
-----------------------------
| ValueSubj | ValueCriteria |
-----------------------------
I want to pull the matching columns from a single row from Master Table(DataGridView1) to Other Table(SQL Database).
So essentially, you would click a row in DataGridView1 then click a button "Add Row to Other Table". Which would add your insert command to the SQL database, in this case it would Exclude the "OtherTableName" column and only insert the "TestSubj" and "TestCriteria" into "OtherTable" Table..
Is this at all possible? I've tried searching for some documentation on this, but I can't seem to find anything.
I'm sure there's a much simpler method in doing this.However, You can just use the strings from the selected rows cell Value. The user must select entire row You can change these settings in Visual Studio under datagridview properties.
private void button1_Click_1(object sender, EventArgs e)
{
string iOne = dgMasterGridView.SelectedRows[0].Cells[1].Value + string.Empty;
string iTwo = dgMasterGridView.SelectedRows[0].Cells[2].Value + string.Empty;
string iThree = dgMasterGridView.SelectedRows[0].Cells[3].Value + string.Empty;
string iFour = dgMasterGridView.SelectedRows[0].Cells[4].Value + string.Empty;
string iFive = dgMasterGridView.SelectedRows[0].Cells[5].Value + string.Empty;
string iSix = dgMasterGridView.SelectedRows[0].Cells[6].Value + string.Empty;
string iSeven = dgMasterGridView.SelectedRows[0].Cells[7].Value + string.Empty;
string iEight = dgMasterGridView.SelectedRows[0].Cells[8].Value + string.Empty;
string iNine = dgMasterGridView.SelectedRows[0].Cells[9].Value + string.Empty;
string iTen = dgMasterGridView.SelectedRows[0].Cells[10].Value + string.Empty;
string iEleven = dgMasterGridView.SelectedRows[0].Cells[11].Value + string.Empty;
string iTwelve = dgMasterGridView.SelectedRows[0].Cells[12].Value + string.Empty;
try
{
// Connection to DB
SqlConnection con = new SqlConnection();
con.ConnectionString = (#"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Database;Integrated Security=True");
//Insert Query
string insertquery = "INSERT INTO dbo.[myTable] ([Item1], [Item2], [Item3], [Item4], [Item5], [Item6], [Item7], [Item8], [Item9], [Item10], [Item11], [Item12]) VALUES(#Item1,#Item2,#Item3,#Item4,#Item5,#Item6,#Item7,#Item8,#Item9,#Item10,#Item11,#Item12)";
SqlCommand cmd = new SqlCommand(insertquery, con);
//open connection
con.Open();
//Parameters
cmd.Parameters.AddWithValue("#Item1", iOne);
cmd.Parameters.AddWithValue("#Item2", iTwo);
cmd.Parameters.AddWithValue("#Item3", iThree);
cmd.Parameters.AddWithValue("#Item4", iFour);
cmd.Parameters.AddWithValue("#Item5", iFive);
cmd.Parameters.AddWithValue("#Item6", iSix);
cmd.Parameters.AddWithValue("#Item7", iSeven);
cmd.Parameters.AddWithValue("#Item8", iEight);
cmd.Parameters.AddWithValue("#Item9", iNine);
cmd.Parameters.AddWithValue("#Item10", iTen);
cmd.Parameters.AddWithValue("#Item11", iEleven);
cmd.Parameters.AddWithValue("#Item12", iTwelve);
//execute
cmd.ExecuteNonQuery();
//close connection
con.Close();
MessageBox.Show("Information has been submitted");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
This also skips the 1st column. However, If you wanted to pull the information from the 1st column, just add:
string iZero = dgMasterGridView.SelectedRows[0].Cells[0].Value + string.Empty;
&&
cmd.Parameters.AddWithValue("#Item0", iZero);
Don't forget to add it to your SQLQuery string also.
You can also Store the information in a Var for later use inside or outside of your scope.
I have rowfilter from textbox input and here is how it looks like
var dt = (DataTable)dataGridView1.DataSource;
try
{
dt.DefaultView.RowFilter = string.Format("KATBR like '%{0}%'", filterKatbr.Text.Trim().Replace("'", "''")) + "AND " + string.Format("NAZIV like '%{0}%'", filterNaziv.Text.Trim().Replace("'", "''"));
dataGridView1.Refresh();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
It supports 2 textbox and filter from 2 textbox in same time but for now lets focus on one textbox. What i want to achieve is if i type in textbox something like this Computer%Land, it needs to filter me everything that must have Computer then any characterS between and then must have Land after it.
It doesn't matter what character is used for that anything between. I used % but it can be anything.
So if i had table like this:
|Computer432Land |
|Computer321 Land |
|Land 213 Computer |
|Computer asd13 Land|
Result would be first, second and fourth column.
Don't think of your filter as a single statement, but instead as two statements to be joined. That is, you need everything that:
Starts with "Computer"; and
Ends with "Land"
Like so:
dt.DefaultView.RowFilter = "ColumnName like 'Computer%' AND ColumnName like '%Land'";
As shown below, using your example data++ we see the expected results.
DataTable dt = new DataTable();
dt.Columns.Add("ColumnName", typeof(string));
dt.Rows.Add("Computer432Land");
dt.Rows.Add("Computer31 Land");
dt.Rows.Add("Land 213 Computer");
dt.Rows.Add("Computer asd13 Land");
dt.Rows.Add("Computer asd13");
dt.Rows.Add("asd13 Land");
dataGridView1.DataSource = dt;
Oh it was catchy because of splitting string but here is how i made it (it is working only with one '%')
string filterNazivStr = filterNaziv.Text;
if(filterNazivStr.ToLower().Contains('%'))
{
int i= 0;
string first = "";
string second = "";
Char separator = '%';
String[] substrings = filterNazivStr.Split(separator);
foreach (var substring in substrings)
{
switch (i)
{
case 0:
first = substring;
break;
case 1:
second = substring;
break;
default:
break;
}
i++;
}
dt.DefaultView.RowFilter = string.Format("NAZIV like '%{0}%'", first) + " AND " + string.Format("NAZIV like '%{0}%'", second);
}
I am running a stored procedure and the result is this format
+------+--------+-----+-------+
| ID | Resign | Sum | Count |
+------+--------+-----+-------+
| 1234 | 0 | 400 | 3 |
| 1234 | 1 | 800 | 4 |
+------+--------+-----+-------+
I tried this code to reference the values returned by the query but, it seem not working the way I want it
if (conn.State != ConnectionState.Open)
conn.Open();
SqlCommand sc = new SqlCommand();
sc.CommandText = "usp_GetResignPool";
sc.CommandType = CommandType.StoredProcedure;
sc.Connection = conn;
sc.Parameters.Add(AddParam(EndDate, "#EndDate"));
sc.Parameters.Add(AddParam(am_id, "#id"));
SqlDataReader reader;
reader = sc.ExecuteReader();
while (reader.Read())
{
if reader. // lost here
}
How can I do something like this. ↓
int resigned = 0, resign_count = 0, not_resigned = 0, notresign_count =0;
if (read["Resigned"] == 1)
{
resigned = read["sum"];
resign_count = read["count"];
}
else
{
not_resigned = read["sum"];
notresign_count = read["count"];
}
It is not important that I used SQLDataReader.
Edit: Real column names
ID Resigned sum count
--------- ----------- ---------------------- -----------
It didn't work because you don't have a column in your table named "Resigned", like you have when you are working with your SqlDataReader.
EDIT: I think the root of the problem is the way you are adding parameters. AddParam() is not the method you want to be using. Therefore, your result set is probably empty.
....
SqlCommand sc = new SqlCommand();
sc.CommandText = "usp_GetResignPool";
sc.CommandType = CommandType.StoredProcedure;
sc.Connection = conn;
sc.Parameters.AddWithValue("#EndDate", EndDate);
sc.Parameters.AddWithValue("id", am_id);
SqlDataReader reader;
reader = sc.ExecuteReader();
using (reader = sc.ExecuteReader())
{
while (reader.Read())
{
if (Convert.ToInt32(read["Resign"]) == 1)
{
resigned = Convert.ToInt32(read["Sum"]);
resign_count = Convert.ToInt32(read["Count"]);
}
else
{
not_resigned = Convert.ToInt32(read["Sum"]);
notresign_count = Convert.ToInt32(read["Count"]);
}
}
}
Notice how I changed your element indicator to "Resign". This needs to match the column that is returned in your dataset. Or, you could use a column number to get this, like so:
if (Convert.ToInt32(read[1]) == 1)
{
resigned = Convert.ToInt32(read[2]);
resign_count = read[3];
}
else
{
not_resigned = Convert.ToInt32(read[2]);
notresign_count = Convert.ToInt32(read[3]);
}
Also, keep in my that in every iteration or your while loop, you'll be overwriting the variables resigned, resign_count or not_resigned and notresign_count.
Would this work?
int resign = 0;
int not_resign = 0;
int resign_count = 0;
int not_resign_count = 0;
while (reader.Read())
{
if (Convert.ToInt32(reader["Resigned"]) == 1)
{
resign = Convert.ToInt32(reader["Sum"]);
resign_count = Convert.ToInt32(reader["Count"]);
}
else
{
not_resign = Convert.ToInt32(reader["Sum"]);
not_resign_count = Convert.ToInt32(reader["Count"]);
}
}
Can you post your query from the procedure?
Are the column names really "Sum" and "Count"?
There are reserved words, maybe you should try using "AS" and give other names to these to columns in the projection.