Pulling Data from tables to pass into an autocompleter c# - c#

I'm working on an autocompleter in c#, I'm using a SQL stored procedure to pull the data which is tested and working.
The issue I'm having is with my for loop which I am using the populate the auto completer.
AutoCompleteStringCollection col = new AutoCompleteStringCollection();
int i = 0;
foreach (DataRow row in TYPESDS.Tables[0].Rows)
{
col.Add(row[i].ToString().ToUpper());
i++;
}
Above is where I have go to with regards to this, I get no errors however the code just does not work.
I have an auto completer working however this has the SQL embedded in the code and I would rather have it working using the stored procedure.

The issue is the use of foreach() to iterate over rows, then for each row also using an indexer (i).
in the original code sample, the "row" in each iteration is a Data Row. The default indexer on this is indexing into the COLUMNS. So on the first row, it'll access column 0, and on the second row, it'll access column 1 and so on.
the second example works because you're using the indexer (i) on the Rows collection property of the table - so this is accessing a ROW. on this Row you're then using the field name indexer to get the "Type" Column.
If the first example was modified to this:
AutoCompleteStringCollection col = new AutoCompleteStringCollection();
foreach (DataRow row in TYPESDS.Tables[0].Rows)
{
col.Add(row["Type"].ToString().ToUpper());
}
Then it is basically equivalent to the second (working) example.

I gave up on using foreach and got it working the following way.
for (int i = 0; i < TYPESDS.Tables[0].Rows.Count - 1; i++ )
{
col.Add(TYPESDS.Tables[0].Rows[i]["Type"].ToString().ToUpper());
}
I think the main issue came with not having the ["Type"] with Rows[i].

Related

DataRow Column Has Value When Read One Way, But Not When Read a Different Way

I'm trying to read values from a DataSet in C#/ASP.NET returned from a stored procedure. Normally, the DefaultView from that DataSet is passed into a GridView in an ASP.NET page. in that event, a particular column I'm interested in has a value. However, if I try to read a DataRow and get the column value, it comes through as empty.
For example, this will display a value:
DataSet ds = //////
DataView dv = ds.Tables[0].DefaultView;
grdQuotes.DataSource = dv;
grdQuotes.DataBind();
This, however, gives me no value:
DataSet ds = //////
foreach (DataRow row in ds.Tables[0].Rows) {
String value1 = (String)row["DOReviewDate"];
String value2 = ((Object)row["DOReviewDate"]).ToString();
String value3 = row.Field<String >("DOReviewDate");
}
All three variables end up empty.
I'm pretty lost on where to go with this, as it's apparent that there's a value being pulled from the SQL database, otherwise it wouldn't display in the GridView table on the page. Also, I can get the rest of the column values in the row without problem. Interestingly enough, there is one other column exhibiting the same behavior.
-- EDIT --
Attempt to iterate through rows and columns to get data:
StringBuilder sb = new StringBuilder();
foreach (DataRow row in ds.Tables[0].Rows)
{
StringBuilder r = new StringBuilder();
foreach (DataColumn c in ds.Tables[0].Columns)
{
r.Append(String.Format("{0} | ", row[c]));
}
r.Append("END");
sb.AppendLine(r.ToString());
}
I was finally able to locate the stored procedure powering this functionality. It's returning empty values for the columns I need. There's nothing but an empty string designating what to return. So, while I can't seem to find the functionality within the page construction, it looks like there is some sort of join or alternate search pulling the data, and I believe I found the table to pull from. Guess I'll just have to take this initial data returned to me and use it to pull from the other table. Or, I guess, maybe make my own SQL search with a join. Either way, the stored procedure does not itself contain a join to the table I need. This is what was in the stored procedure:
'' as DOReviewDate

Need to Get data value prior to binding to row in listview

I have a ListView object in Asp.Net (C#) where I also have a ListView_ItemDataBound() method that is populated using a sqlDataSource.
In some cases, I would like to be able to insert a row in the ListView prior to the current record being bound. I.e., as the rows are being populated, I need to be able to read the value that is about to be bound and then insert a "header" row mid stream before the current row of data is added to the ListView.
In the case of the ItemDataBound event, the data seems to be already bound to the control so the rows being added are actually one ListView row too late for me to do anything.
ListView_ItemDataBound()
{
System.Data.DataRowView rowView = e.Item.DataItem as System.Data.DataRowView;
//Pseudo code of what I'd like
//if rowView["some_field"]==123 then
// insert row prior to this row being bound
}
I'm relatively new to Asp.Net and come from a classic asp background so maybe I'm thinking and going about this all wrong. Any suggestions would be appreciated.
Instead of doing that after you've already assigned the datasource and called listView.DataBind() you should do that in the datasource. Presuming it's a DataTable:
List<int> rowIndices = new List<int>();
for(int i = 0; i < dataTable.Rows.Count - 1; i++)
{
int some_field = dataTable.Rows[i].Field<int>("some_field");
if (some_field == 123)
rowIndices.Add(i + rowIndices.Count); // indices will increases by count
}
foreach(int index in rowIndices)
{
DataRow newRow = ....
dataTable.Rows.InsertAt(newRow, index);
}
Now assign this modified table as datasource and call DataBind.

duplicate datatable column names

I have a datable with column names I0,I1,I2 etc. However these aren't actual column names. I store the column names in another table.
I then have a loop to map the actual column names as follows:
for (int i = 0; i < dt_key.Rows.Count; i++)
{
dt_data.Columns[i].ColumnName = dt_key.Rows[i][0].ToString();
}
I get the following errors:
A column named 'Pressure' already belongs to this DataTable.
and
A column named 'Size' already belongs to this DataTable.
Ultimately I am trying to write this to a xml file:
dt_data.WriteXml(filename);
This works but I end up the column names I0..I22
There are similar questions to this, but they are trying to make datatables with duplicate columns names. I am just trying to print out a table with duplicate column names. What is a good method to do this?
Edit:
I can do the following:
for (int i = 0; i < dt_key.Rows.Count; i++)
{
dt_data.Columns[i].ColumnName = dt_key.Rows[i][0].ToString() + " " + dt_data.Columns[i].ColumnName;
}
I think the short answer to your question is that there is no way to have duplicate column names using a DataTable. What exactly are you using this XML for? There are lots of alternate ways to generate XML that give you a lot more fine grained control.
You could manually create your file using an XmlWriter object. This method creates an XmlWriter that writes to a file.
for (int i = 0; i < dt_key.Rows.Count; i++)
{
if(dt_data.Columns.Contains(dt_key.Rows[i][0].ToString()))
dt_data.Columns[i].ColumnName = dt_key.Rows[i][0].ToString() + " " ;
else
dt_data.Columns[i].ColumnName = dt_key.Rows[i][0].ToString();
}
However adding a same column name is a bad practise,still you could achieve that by adding a space at the end of column name to make it unique.
Maybe you can make use of the DataColumn.Caption property to store the column display name:
https://msdn.microsoft.com/en-us/library/system.data.datacolumn.caption(v=vs.110).aspx
You can not duplicate Column names by using Data Table.Consider this and find another solution .
If you try to duplicate Column name then it will show an error like that you mentioned.
A column named 'Pressure' already belongs to this Data Table .
In here you try to duplicate Column name 'Pressure' that's why that error comes.

how to convert the entire content of a DataTable column to a delimited string in C#?

I am retrieving data from an MSSQL server using the SqlDataAdapter and DataSet. From that DataSet I am creating a DataTable. My goal is to convert each column of the table into a string where the elements are comma delimited. I figured that I would try the string conversion first before making the delimiter work.
The code runs in the code-behind of an ASP.Net page. The ultimate goal is to pass the string to a jscript variable, it's a "functional requirement" that I create a delimited string from the columns and that it has to end up as a jscript variable.
Here's what I have thus far:
DataSet myDataSet = new DataSet();
mySqlDataAdapter.Fill(myDataSet);
DataTable temperature = myDataSet.Tables["Table"];
// LOOP1
foreach (DataRow row in temperature.Rows)
// this loop works fine and outputs all elements
// of the table to the web page, this is just to
// test things out
{
foreach (DataColumn col in temperature.Columns)
{
Response.Write(row[col] + " ### ");
}
Response.Write("<br>");
}
// LOOP2
foreach (DataColumn column in temperature.Columns)
// this loop was meant to take all elements for each
// column and create a string, then output that string
{
Response.Write(column.ToString() + "<br>");
}
In LOOP1 things work fine. My data has 4 columns, all are appropriately rendered with one record per row on the web page.
I saw the code for LOOP2 at http://msdn.microsoft.com/en-us/library/system.data.datacolumn.tostring.aspx which seems to do exactly what I need except it does not actually do what I want.
The only thing LOOP2 does is write 4 lines to the web page. Each line has the header of the respective table column but none of the additional data. Clearly there's either a logic flaw on my part or I misunderstand how DataColumn and .toString for it works. Please help me out on this one. Thanks in advance.
EDIT:
Here's an SQL query result example, this is what the Table looks like:
Table quesry result # ImageShack
What I want to end up are four strings, here's an example for the string that would be created from the second column: "-6.7, -7, -7.2, -7.3, -7.3".
This code will concatenate values from cells under each column with ", ":
foreach (var column in temperature.Columns)
{
DataColumn dc = column as DataColumn;
string s = string.Join(", ", temperature.Rows.OfType<DataRow>()
.Select(r => r[dc]));
// do whatever you need with s now
}
For example, for DataTable defined as:
DataTable table = new DataTable();
table.Columns.Add(new DataColumn("Column #1"));
table.Columns.Add(new DataColumn("Column #2"));
table.Rows.Add(1, 2);
table.Rows.Add(11, 22);
table.Rows.Add(111, 222);
... it will produce "1, 11, 111" and "2, 22, 222" strings.
Edit: I saw you chose to declare column as var as opposed to DataColumn, is that a matter of personal preference/style or is there an issue with coding?
Consider following scenario (on the same data table example as above):
// we decide we'll use results later, storing them temporarily here
List<IEnumerable<string>> columnsValues = new List<IEnumerable<string>>();
foreach (DataColumn column in temperature.Columns)
{
var values = temperature.Rows.OfType<DataRow>()
.Select(r => r[column].ToString())
columnsValues.Add(values);
}
We assume we now got list of list of column values. So, when we print them, like this:
foreach (var lisOfValues in columnsValues)
{
foreach (var value in listOfValues)
{
Debug.Write(value + " ");
}
Debug.WriteLine("");
}
We expect to see 1 11 111 followed by 2 22 222. Right?
Wrong.
This code will output 2 22 222 twice. Why? Our .Select(r => r[column].ToString()) captures column variable - not its value, but variable itself - and since we don't use it immediately, once we're out of loop all we know is last value of column.
To learn more about this concept search for closures and captured variables - for example, in posts like this.
Summary:
In this very case you can go with DataColumn in foreach statement. It doesn't matter here because we're enumerating through our .Select(r => r[dc]) either way inside the loop (precisely, string.Join does that for us), producing results before we get to next iteration - whatever we capture, is used immediately.
The link you have posted clearly states
The Expression value, if the property
is set; otherwise, the ColumnName
property.
and that is what is happening. You get column names.
This could help: How to convert a DataTable to a string in C#?

Remove row from generic datatable in C#

I ran into a problem trying to remove a row from a datatable in C#. The problem is that the datatable is built from SQL, so it can have any number of columns and may or may not have a primary key. So, I can't remove a row based on a value in a certain column or on a primary key.
Here's the basic outline of what I'm doing:
//Set up a new datatable that is an exact copy of the datatable from the SQL table.
newData = data.Copy();
//...(do other things)
foreach (DataRow dr in data.Rows)
{
//...(do other things)
// Check if the row is already in a data copy log. If so, we don't want it in the new datatable.
if (_DataCopyLogMaintenance.ContainedInDataCopyLog(dr))
{
newData.Rows.Remove(dr);
}
}
But, that gives me an error message, "The given DataRow is not in the current DataRowCollection". Which doesn't make any sense, given that newData is a direct copy of data. Does anyone else have any suggestions? The MSDN site wasn't much help.
Thanks!
Your foreach needs to be on the copy, not the original set. You cannot remove an object contained in collection1 from collection2.
foreach (DataRow dr in newData.Rows)
Otherwise you could use a counter to remove at an index. Something like this:
for(int i = 0; i < data.Rows.Count; i++)
{
if (_DataCopyLogMaintenance.ContainedInDataCopyLog(data.Rows[i]))
{
newData.Rows.RemoveAt(i);
}
}

Categories