Filling an arraylist from a datareader - c#

I have a problem with how to fill an array list from a data reader
string queryDTL = " SELECT * FROM tbl1 ";
connection.Connect();
cmd = new OracleCommand(queryDTL, connection.getConnection());
dr_DTL = qcmd2.ExecuteReader();
ArrayList RecordsInfo = new ArrayList();
while (dr_DTL.Read())
{
RecordsInfo = dr_DTL["number"].ToString();
}
The problem is the datareader contain alot of info other than the number but I don't know how to put them in their correct position.
I am still a beginner in this sorry if it sounds stupid.

You can't put a String in an ArrayList. You have to add the string to the list.
Ex. :
ArrayList RecordsInfo = new ArrayList();
while (dr_DTL.Read())
{
RecordsInfo.Add(dr_DTL["number"].ToString());
}
If you want a list of String the best way is using List<String>.
Ex. :
List<String> RecordsInfo = new List<String>();
while (dr_DTL.Read())
{
RecordsInfo.Add(dr_DTL["number"].ToString());
}

I think you would be better off with a DataTable and an adapter:
SqlConnection Conn = new SqlConnection(MyConnectionString);
Conn.Open();
SqlDataAdapter Adapter = new SqlDataAdapter("Select * from Employees", Conn);
DataTable Employees = new DataTable();
Adapter.Fill(Employees);
GridView1.DataSource = Employees;
GridView1.DataBind();
Of course in your case, use the Oracle versions of the objects.

Hi you have to do RecordInfo.Add, currently you are reassigning the whole arraylist...
Also if you are retrieving too many columns, just query the columns you need, in your case number, not simply SELECT * ...

Related

Getting specific column data from database in C#

I have created a search function that returns product data in a DataGridView (data is coming from local database), it does work but I need to have control over returned data in my grid view.
Current behavior
It returns all columns of database row in DataGridView
What I want
Returning only 2 or 3 columns of searched item instead of all columns
Create new list of searched items so I can edit those returned data
Logic
Search for product
Get product name and price from database, add custom quantity field make new list and add this item to show in DataGridView
Be able to change quantity field in DataGridView
Code
Here is my search code that returns all columns of product table
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["SampleDatabaseWalkthrough.Properties.Settings.SampleDatabaseConnectionString"].ConnectionString))
{
if (cn.State == ConnectionState.Closed)
cn.Open();
using (DataTable dt = new DataTable("Products"))
{
using (SqlCommand cmd = new SqlCommand("select * from Products where Id=#Id or Name like #Name", cn))
{
cmd.Parameters.AddWithValue("Id", searchBox.Text);
cmd.Parameters.AddWithValue("Name", string.Format("%{0}%", searchBox.Text));
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
adapter.Fill(dt);
// Following line will show all columns of founded product and replace it with next search result
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
selectedItems.DataSource = dt;
}
}
}
PS: Code above finds products based on id or name entered in search field and return all columns of product row.
Idea:
I think I can be able to create my list after finding product but the issue I'm facing is that I'm not sure how to get those specific columns from my dt (table row),
Here is what I've tried and failed (commented)
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["SampleDatabaseWalkthrough.Properties.Settings.SampleDatabaseConnectionString"].ConnectionString))
{
if (cn.State == ConnectionState.Closed)
cn.Open();
using (DataTable dt = new DataTable("Products"))
{
using (SqlCommand cmd = new SqlCommand("select * from Products where Id=#Id or Name like #Name", cn))
{
cmd.Parameters.AddWithValue("Id", searchBox.Text);
cmd.Parameters.AddWithValue("Name", string.Format("%{0}%", searchBox.Text));
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
adapter.Fill(dt);
//selectedItems.DataSource = dt; //<-- changed with lines below
List<string> items = new List<string>();
items.Add(dt); // <-- here is the issue (it expect to get string of my table row let say: Price column, but I don't know how to get Price column value from dt)
selectedItems.DataSource = items;
}
}
}
PS: code above is just idea and obviously I am not sure if it is best way to do it or not that's why I'm asking here :)
Any suggestions?
Update
I've created new class and added my data to that class as following
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public string Price { get; set; }
public string Qty { get; set; }
}
Then in my query I added
List<Item> itemList = new List<Item>();
for (int i = 0; i < dt.Rows.Count; i++)
{
Item item = new Item();
item.Id = Convert.ToInt32(dt.Rows[i]["Id"]);
item.Name = dt.Rows[i]["Name"].ToString();
item.Price = dt.Rows[i]["SellPrice"].ToString();
item.Qty = dt.Rows[i]["Qty"].ToString();
itemList.Add(item);
}
selectedItems.DataSource = itemList;
Now it does return data in my selectedItems but when I search for next product instead of adding it to the list it replace it with first product.
According to your sql query you are selecting all columns of the table.
To get the specific columns please change your sql query as such:
SqlCommand cmd = new SqlCommand("select Products.id, Products.name from Products where Id=#Id or Name like #Name", cn);
Thank you.
As per my understanding based on the comments, you are looking for some Linq code.
You only need to convert your result to a list that you could use.
Here is some code that might help you achieve this.
var result = dt.AsEnumerable().Select(x=> new {
Id = x["Id"],
Name = x["Name"],
Quantity = {Your Logic here}
});
selectedItems.DataSource = result;
You can then assign result to your datasource. You did not specify what your datasource is assigned to (selectedItems) so I do not know what type it is. but this should theoretically work. Just remove Quantity = {Your Logic here} from the code and see if it display's after which you could then just add it back and populate what you want Quantity to be
UPDATE
Because selectedItems is a DataGridView it requires a DataTable object to display the data. In which case you can not use an anonymous list as I created you would need something like this.
DataTable dtResult = new DataTable();
dtResult.Columns.Add("Id");
dtResult.Columns.Add("Name");
dtResult.Columns.Add("Quantity");
var result = dt.AsEnumerable().Select(x=> dtResult.Rows.Add(x["Id"],
x["Name"],
{Your Logic for Quantity here}
));
selectedItems.DataSource = result;
If you want to test this solution you can create a console application in c# and do something like where you can see the datasource is correct.
You could refer to the following code to show specific column data from database in winform datagirdview.
private void button1_Click(object sender, EventArgs e)
{
string str = "str";
SqlConnection connection = new SqlConnection(str);
connection.Open();
string sql = "select * from Product where Id=#Id or Name like #Name";
SqlCommand command = new SqlCommand(sql,connection);
command.Parameters.AddWithValue("#Id", textBox1.Text);
command.Parameters.AddWithValue("#Name", string.Format("%{0}%", textBox1.Text));
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataTable table = new DataTable();
adapter.Fill(table);
var dt = from t in table.AsEnumerable()
select new
{
//Name=t.Field<string>("Name"), //The same way to show other columns data
Price = t.Field<string>("Price")
};
dataGridView1.DataSource = dt.ToList();
}
Result:
Database:

Extract Contents of DataSet into an Object

I have this DataSet which calls my Stored Procedure and returns a list of integers. How can I extract the list of integers which I could store in a variable be it a collection which grows in size such as a List<T> or a primitive data type like an array of integers.
Below is my code:
private DataSet getSubGroupsBelongingToUser()
{
DataTable variable;
DataSet DS;
myConnectionString = ConfigurationManager.ConnectionStrings["FSK_ServiceMonitor_Users_Management.Properties.Settings.FSK_ServiceMonitorConnectionString"].ConnectionString;
using (mySQLConnection = new SqlConnection(myConnectionString))
{
SqlParameter param = new SqlParameter("#UserId", getUserID(cbxSelectUser.Text));
DS = GetData("Test", param);
variable = DS.Tables[0];
}
return DS;
}
When I hover over the DS magnifier (refer to image):
I want to retrieve and store that list of integers somewhere. How can I go about doing this? All the examples I came across online make use of linq and that is not applicable here since I am getting the results from my stored procedure which requires one input parameter. Here is the definition of the stored procedure below:
create proc [dbo].[Test]
#UserId smallint
as
begin
select DepartmentSubGroupId from DepartmentSubGroupUser
where UserId= #UserId
end
GO
So essentially when you pass in a UserId, you should get those values. I am using SQL Server as my DBMS.
The simplest and most efficient approach would be to not use a DataSet/DataTable at all:
private List<int> GetSubGroupsBelongingToUser()
{
List<int> list = new List<int>();
using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["FSK_ServiceMonitor_Users_Management.Properties.Settings.FSK_ServiceMonitorConnectionString"].ConnectionString))
using (var cmd = new SqlCommand("Test", con))
{
cmd.CommandType = CommandType.StoredProcedure;
var param = new SqlParameter("#UserId", SqlDbType.Int).Value = int.Parse(cbxSelectUser.Text);
cmd.Parameters.Add(param);
con.Open();
using (var rd = cmd.ExecuteReader())
{
while (rd.Read()) list.Add(rd.GetInt32(0));
}
} // no need to close the connection with the using
return list;
}
If you insist on the DataTable, at least it's more conscise:
return DS.Tables[0].AsEnumerable().Select(r => r.Field<int>(0)).ToList();
As #David pointed out the simplest option would be to use a SqlDataReader and loop through all the records.
However, if your heart is set on DataTables then all you need to do is to iterate all rows from the result table, grab the value from column DepartmentSubGroupId and add it to a list. You can do that with Linq also like this:
return DS.Tables[0].Rows
.Cast<DataRow>() // Rows is an ICollection and you need to cast each item
.Select(r => (int)r["DepartmentSubGroupId"]) // For each row get the value from column DepartmentSubGroupId
.ToList();
Before I saw #Tim's solution, I had already prepared this (which works just as well as most of the above solutions):
public List<int> getSubGroupsBelongingToUser()
{
List<int> DepartmentSubGroupIds = new List<int>();
myConnectionString = ConfigurationManager.ConnectionStrings["FSK_ServiceMonitor_Users_Management.Properties.Settings.FSK_ServiceMonitorConnectionString"].ConnectionString;
using (mySQLConnection = new SqlConnection(myConnectionString))
{
SqlParameter parameter = new SqlParameter("#UserId", getUserID(cbxSelectUser.Text));
mySQLCommand = new SqlCommand("Test", mySQLConnection);
mySQLCommand.CommandType = CommandType.StoredProcedure;
mySQLCommand.Parameters.Add(parameter);
mySQLConnection.ConnectionString = myConnectionString;
mySQLConnection.Open();
SqlDataReader sqlDataReader = mySQLCommand.ExecuteReader();
while (sqlDataReader.Read())
{
DepartmentSubGroupIds.Add(Convert.ToInt32(sqlDataReader["DepartmentSubGroupId"]));
}
}
return DepartmentSubGroupIds;
}
Thanks everybody, much appreciated.

Iterate Multiple DataTables

I have a SQL Server stored procedure that I run two select statements. I can easily return one select statement and store it in a DataTable but how do I use two?
How can I set my variable countfromfirstselectstatement equal to the count returned from my first select statement and how can I set my variable countfromsecondselectstatement equal to the count returned from the second select.
private void ReturnTwoSelectStatements()
{
DataSet dt112 = new DataSet();
using (var con = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand("Return2SelectStatements", con))
{
using (var da = new SqlDataAdapter(cmd))
{
cmd.CommandType = CommandType.StoredProcedure;
da.Fill(dt112);
}
}
}
DataTable table1 = dt112.Tables[0];
DataTable table2 = dt112.Tables[1];
string countfromFirstSelectStatement = table1.Rows.Count().ToString();
string countfromSecondSelectStatement = table2.Rows.Count().ToString();
//I only want to iterate the data from the 1st select statement
foreach (DataRow row in dt112.Rows)
{
}
}
You could also directly use the DbDataReader (cmd.ExecuteReader()), which gives you NextResult to advance to the next result set. DataTable.Load allows you to load rows from the data reader to the table.
DbDataAdapter is really a bit of an overkill for just reading data into a data table. It's designed to allow the whole CRUD-breadth of operation for controls that are abstracted away from the real source of data, which isn't really your case.
Sample:
using (var reader = cmd.ExecuteReader())
{
dataTable1.Load(reader);
if (!reader.NextResult()) throw SomethingWhenTheresNoSecondResultSet();
dataTable2.Load(reader);
}
Fill a Dataset with both select statements and access it:
....
DataSet dataSet = new DataSet();
da.Fill(dataSet);
....
DataTable table1 = dataSet.Tables[0];
DataTable table2 = dataSet.Tables[1];
string countfromFirstSelectStatement = table1.Rows.Count.ToString();
string countfromSecondSelectStatement = table2.Rows.Count.ToString();

How does one assign column names to tables in dataset?

I have this code
SqlConnection conn = Database.GetConnection();
//not sure why doing this bit (bit between this comment and next
//SqlDataAdapter adapter = new SqlDataAdapter("Select * From CarType", conn);
DataSet DataSetRentals2 = new DataSet("CustomerSQLTable");
DataTable table = new DataTable("CustomerSQLTable"); //you can name it
DataTable table2 = new DataTable("CarRental");
using (SqlDataAdapter adapter = new SqlDataAdapter())
{
adapter.SelectCommand = new SqlCommand("SELECT * FROM Customer", conn);
conn.Open();
///this might brake the code
///
adapter.Fill(DataSetRentals2,"CustomerSQLTable");
adapter.SelectCommand = new SqlCommand("SELECT * FROM CarRental", conn);
adapter.Fill(DataSetRentals2, "CarRental");
adapter.Fill(DataSetRentals2, "CarRental");
}
CustomerGrid.DataSource = DataSetRentals2;
CustomerGrid.DataMember = "CustomerSQLTable";
CarRGrid.DataSource = DataSetRentals2.Tables["CarRental"];
CarRGrid.DataMember = "CarRental";
the teacher gave me this code to link them in a relationship so that when i click on one customer number in one data grid and for it to only return corresponding records in the other.
DataRowView selectedRow =
(DataRowView)CustomerGrid.SelectedRows[0].DataBoundItem;
DataSetRentals2.Tables["CarRental"].DefaultView.RowFilter =
"CustomerNo = " + selectedRow.Row["CustomerNo"].ToString();.
so what i think i need to do is to name the columns in the dataset. But i have no idea how to do this. I'm sure there must be a way an I'm sure you guy's can easily tell me it. Thank you in advanced.
dataTable.Columns[0].ColumnName = "MyColumnName";
Your columns will already have names. They are supplied by the database.
I would guess that your issue is with this line. If this isn't it please describe what you're expecting to happen, vs what is actually happening so that we may assist you better.
CarRGrid.DataSource = DataSetRentals2.Tables["CarRental"];
Which should probably be
CarRGrid.DataSource = DataSetRentals2;

SqlDataReader filling column in datagridview

I have been wondering for quiet long time how can I set my SqlDataReader to fill column "pocet" in my datagridview "dtg_ksluzby". I thought that my code should look something like this:
SqlCommand novyprikaz2 = new SqlCommand("SELECT pocet FROM klisluz WHERE id='"+vyberradek+"'",spojeni); // I also have column "pocet" in table klisluz, vyberradek is string which selectrs id number
spojeni.Open();
SqlDataReader precti2 = novyprikaz2.ExecuteReader();
if (precti2.Read())
{
dtg_ksluzby.Columns["pocet"]; // this part I need to improve to fill
}
Would you please help me to improve my code?
Thanks so much in advance.
Edit for trippino:
In "klisluz" which is in the table that includes columns
(id,akce,subkey,text,pocet). I need to:
select * from klisluz where subkey = '"+vyberradek+"'
Take column pocet and fill it into dtg_ksluzby where i find the text is similar in column "text" in dtg_ksluzby
I hope my description is understandabla, sorry for my weak english.
Do not use string concatenation to build sql commands, (to avoid Sql Injection and parsing problem)
using(SqlConnection spojeni = new SqlConnection(conString))
using(SqlCommand novyprikaz2 = new SqlCommand("SELECT pocet FROM klisluz " +
"WHERE id = #id",spojeni);
{
novyprikaz2.Parameters.AddWithValue("#id", vyberradek);
spojeni.Open();
using(SqlDataAdapter da = new SqlDataAdapter(novyprikaz2))
{
DataTable dt = new DataTable();
da.Fill(dt);
dtg_ksluzby.DataSource = dt;
}
}
Use a DataAdapter to load your data from database and pass this DataAdapter instance to the DataSource of your DataGridView
Use something like this:
for (int i = 0; i < dtg_ksluzby.Rows.Count; i++)
{
var row = dtg_ksluzby.Rows[i];
using(var novyprikaz2 = new SqlCommand("SELECT pocet FROM klisluz WHERE text LIKE #t AND subkey=#s", spojeni))
{
novyprikaz2.Parameters.AddWithValue("#t", row.Cells["text"].Value.ToString());
novyprikaz2.Parameters.AddWithValue("#s", vyberradek);
spojeni.Open();
SqlDataReader precti2 = novyprikaz2.ExecuteReader();
if (precti2.Read())
{
row.Cells["pocet"].Value = precti2["pocet"];
}
}
}

Categories

Resources