comparing datarow value with a string in if - c#

I have an application which stores a user selected value to the value in my dataset filled datatable. I need to set another column in the table based on this comparison. But the comparison is not working. It always returns false, not entering in the if condition.
foreach (DataRow dr in dsQuestions.Tables[0].Rows)
{
if (dr["Data"] == indicater[0])
{
dr["IsSelected"] = true;
}
}
indiactor[0] is a string array and dr["data"] is also of type string but it shows a warning that it needs to a string type.

The DataRow indexer returns the field at that index as object not as string.
I would recommend to use the strongly typed Field-extension method which also supports nullables:
if (dr.Field<String>("Data") == indicater[0]){}
... and the SetField method that also support nullable types:
dr.SetField("IsSelected", true);
Update if indicater[0] is really a string[] (not a single string), how do you want to compare a string with a string[]? If you for example want to check if the array contains this data:
if (indicater[0].Contains(dr.Field<String>("Data"))){}
That would also explain why it never enters the if: because == only compares strings by equality, other types which don't have overridden the ==-operator will compare only the reference. A string is never the same reference as a string[]. But you don't get a compile time error because you can compare an object with everything else.

First of all string can't compare using == you should use equals method:
foreach (DataRow dr in dsQuestions.Tables[0].Rows)
{
if (dr["Data"].tostring().Equals(indicater[0]))
{
dr["IsSelected"] = true;
}

May be useful for you
DataRow[] result = table.Select("Id = 1");
foreach (DataRow row in result)
{
if (row[0].Equals(indicater[0]))
{
//IsSelected
row[1]=true;
Console.WriteLine("{0}", row[0]);
}
}

Try this:
foreach (DataRow dr in dsQuestions.Tables[0].Rows)
{
if (dr["Data"].ToString() == indicater[0].ToString())
{
Convert.ToBoolean(dr["IsSelected"].ToString()) = true;
}
}

Related

Looping through data table to get value

I have a DataTable with multiple rows. I'm using a foreach loop to loop through each item and return the name. This is returning the same (1st) value for each row. What have I done wrong?
DataTable table = new DataTable();
table.Columns.Add("tag", typeof(string));
string name = hfSelected.Value;
string[] names = name.Split(',');
for (int i = 0; i < names.Length; i++)
table.Rows.Add(new object[] { names[i] });
DataRow row = table.Rows[0];
foreach (var item in table.Rows)
{
Value = row["tag"].ToString() // this is returning the same value for both items in the table.
}
In a comment you mentioned that you get the error:
cannot apply indexing with [] to an expression of type object
when trying to access item["tag"] in the foreach loop.
You need to explicitly declare the DataRow in the foreach.
// declare DataRow here, not var
foreach (DataRow item in table.Rows)
{
// use item here
Value = item["tag"].ToString(); // use += to concatenate string
}
The reason is that the DataRowCollection implements a non-generic IEnumerable so you index an object instead of DataRow. The solution above casts to a DataRow.
I would recommend looking at the Field<T>() and AsEnumerable() methods from System.Data.DataSetExtensions. AsEnumerable() returns an IEnumerable<DataRow>. Field() provides strongly typed access to the values (ie it casts/converts the types for you).
Then you can do:
foreach (var item in table.AsEnumerable())
{
// item is a DataRow here
var myString = item.Field<string>("tag"); // gets string
// you can also do
var myInt = item.Field<int>("Id"); // gets int
var myDate = item.Field<DateTime?>("Date"); // gets nullable DateTime?
var myValue = item.Field<decimal>("Price"); // gets decimal
}
Carl is correct, this is producing the same output, because inside the iteration, you use the same row, all the time. You should use 'item', instead of 'row' there (you don't need 'row' at all).
The exception you receive is because you declared 'item' with a dynamic type, it's
foreach (var item in table.Rows)
You can try
foreach (DataRow item in table.Rows)
this way, you'll be able to get the column info.
your iteration seems to be using the same 'row' variable instead of the 'item' variable you defined in the foreach statement.

iterate through particular column in a datatable

I am Working in asp.net and c#.
I have a datatable in my application with one column.I want to iterate through that column values and check those values with someother value.please tell me how to do that.I tried it with foreach but its not working.
Code:
foreach (DataRow dr in dt.Rows)
{
int code = Convert.ToInt32(dt.Rows[0]["Code"]);
if (code == pcode)
{
//do something
}
else
{ }
}
Note:
dt is my datatable with column code.I want to compare all values in column code with pcode.
int code = Convert.ToInt32(dr["Code"]);
Although you might want to check for NULL also :)
Inside your loop, access dr, instead of dt.Rows[0].
You are always accessing the first row:
dt.Rows[0]["Code"] // use dr instead of dt.Rows[0]
dt is my datatable with column code.I want to compare all values in
column code with pcode.
So am i right when i assume that you want to compare all values with one variable, if all fields equal this value, a bool variable should be true, otherwise false?
You can use Linq:
var allEqual = dt.AsEnumerable()
.All(r => r.Field<int>("Code") == pcode);
Enumerable.All determines whether all elements of a sequence satisfy a condition.
foreach (DataRow dr in dt.Rows)
{
object o = dr["Code"];
if (o != DBNull.Value) // Check for null
{
int code = Convert.ToInt32(o);
if (code == pcode)
{
//do something
}
else
{ }
}
}

DataRow: Select cell value by a given column name

I have a problem with a DataRow that I'm really struggling with.
The datarow is read in from an Excel spreadsheet using an OleDbConnection.
If I try to select data from the DataRow using the column name, it returns DBNull even though there is data there.
But it's not quite that simple.
datarow.Table.Columns[5].ColumnName returns "my column".
datarow["my column"] returns DBNull.
datarow[5] returns 500.
datarow[datarow.Table.Columns[5].ColumnName] returns DBNull. (just to make sure its not a typo!)
I could just select things from the datarow using the column number, but I dislike doing that since if the column ordering changes, the software will break.
Which version of .NET are you using? Since .NET 3.5, there's an assembly System.Data.DataSetExtensions, which contains various useful extensions for dataTables, dataRows and the like.
You can try using
row.Field<type>("fieldName");
if that doesn't work, you can do this:
DataTable table = new DataTable();
var myColumn = table.Columns.Cast<DataColumn>().SingleOrDefault(col => col.ColumnName == "myColumnName");
if (myColumn != null)
{
// just some roww
var tableRow = table.AsEnumerable().First();
var myData = tableRow.Field<string>(myColumn);
// or if above does not work
myData = tableRow.Field<string>(table.Columns.IndexOf(myColumn));
}
This must be a new feature or something, otherwise I'm not sure why it hasn't been mentioned.
You can access the value in a column in a DataRow object using row["ColumnName"]:
DataRow row = table.Rows[0];
string rowValue = row["ColumnName"].ToString();
I find it easier to access it by doing the following:
for (int i = 0; i < Table.Rows.Count-1; i++) //Looping through rows
{
var myValue = Table.Rows[i]["MyFieldName"]; //Getting my field value
}
Hint
DataTable table = new DataTable();
table.Columns.Add("Column#1", typeof(int));
table.Columns.Add("Column#2", typeof(string));
table.Rows.Add(5, "Cell1-1");
table.Rows.Add(130, "Cell2-2");
EDIT: Added more
string cellValue = table.Rows[0].GetCellValueByName<string>("Column#2");
public static class DataRowExtensions
{
public static T GetCellValueByName<T>(this DataRow row, string columnName)
{
int index = row.Table.Columns.IndexOf(columnName);
return (index < 0 || index > row.ItemArray.Count())
? default(T)
: (T) row[index];
}
}
On top of what Jimmy said, you can also make the select generic by using Convert.ChangeType along with the necessary null checks:
public T GetColumnValue<T>(DataRow row, string columnName)
{
T value = default(T);
if (row.Table.Columns.Contains(columnName) && row[columnName] != null && !String.IsNullOrWhiteSpace(row[columnName].ToString()))
{
value = (T)Convert.ChangeType(row[columnName].ToString(), typeof(T));
}
return value;
}
You can get the column value in VB.net
Dim row As DataRow = fooTable.Rows(0)
Dim temp = Convert.ToString(row("ColumnName"))
And in C# you can use Jimmy's Answer, just be careful while converting it to ToString(). It can throw null exception if the data is null
instead Use Convert.ToString(your_expression) to avoid null exception reference
for (int i=0;i < Table.Rows.Count;i++)
{
Var YourValue = Table.Rows[i]["ColumnName"];
}
Be careful on datatype. If not match it will throw an error.
var fieldName = dataRow.Field<DataType>("fieldName");
Simple solution:
Assume sqlDt contains the DataTable, then this will give you the content of the
column named "aaa" in row is:
Dim fldContent = sqlDte.Rows(iz).ItemArray(sqlDte.Columns.Item("aaa").Ordinal)
Console.WriteLine("aaa = " & fldContent)
Edited code formatting

DataTable C# Empty column type

I am trying build a DataTable one row at a time using the following code.
foreach (var e in Project.ProjectElements[hi.FakeName].Root.Elements()) {
index = 0;
object[] obj=new object[count];
foreach (var holdingColumn in names) {
string d = e.Attribute(holdingColumn.Key).Value;
obj[index++] = d;
}
dt.Rows.Add(obj);
}
The problem is the DataTable has types tied to the columns. Sometimes im passing null (or an empty string) in that object index and it is telling me that it cant be converted properly to a DateTime (in this case). My question is what should I default this value to, or is there some way to have the DataTable ignore empty values.
Set the AllowDBNull property of the DataColumn to true, then write
if (String.IsNullOrEmpty(d))
obj[index++] = DBNull.Value;
else
obj[index++] = d;

Checking to see if a column exists in a data reader [duplicate]

This question already has answers here:
Check for column name in a SqlDataReader object
(27 answers)
Closed 8 years ago.
Is there a way to see if a field exists in an IDataReader-based object w/o just checking for an IndexOutOfRangeException?
In essence, I have a method that takes an IDataReader-based object and creates a strongly-typed list of the records. In 1 instance, one data reader has a field that others do not. I don't really want to rewrite all of the queries that feed this method to include some form of this field if I don't have to. The only way I have been able to figure out how to do it so far is to throw the 1 unique field into a try/catch block as shown below.
try
{
tmp.OptionalField = reader["optionalfield"].ToString();
}
catch (IndexOutOfRangeException ex)
{
//do nothing
}
Is there a cleaner way short of adding the "optional field" to the other queries or copying the loading method so 1 version uses the optional field and the other doesn't?
I'm in the 2.0 framework also.
I ended up finding a solution using the reader.GetName(int) method. I created the below method to encompass the logic.
public bool ColumnExists(IDataReader reader, string columnName)
{
for (int i = 0; i < reader.FieldCount; i++)
{
if (reader.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase))
{
return true;
}
}
return false;
}
The following will give you a list of the column name strings given a data reader.
(Remember the results are based on the last read so it may not be the same depending on what the reader read).
var cols = reader.GetSchemaTable()
.Rows
.OfType<DataRow>()
.Select(row => row["ColumnName"]);
Or to check if a column exists:
public bool ColumnExists(IDataReader reader, string columnName)
{
return reader.GetSchemaTable()
.Rows
.OfType<DataRow>()
.Any(row => row["ColumnName"].ToString() == columnName);
}
Enumerable.Range(0, reader.FieldCount).Any(i => reader.GetName(i) == "ColumnName")
This should work, try this:
private static bool ColumnExists(SqlDataReader reader, string columnName)
{
using (var schemaTable = reader.GetSchemaTable())
{
if (schemaTable != null)
schemaTable.DefaultView.RowFilter = String.Format("ColumnName= '{0}'", columnName);
return schemaTable != null && (schemaTable.DefaultView.Count > 0);
}
}
Appears I stand corrected. I know your actual column names are in there, but I was going down the wrong path. This reference helped clear things up a bit, but I'm still not sure if there's an elegant way of doing it. Adapted from the above link, you could get a list of all of your columns with the following:
List<string> myCols = new List<string>();
DataTable schema = reader.GetSchemaTable();
foreach (DataRow row in schema.Rows)
{
myCols.Add(row[schema.Columns["ColumnName"]]);
}
Unfortunately it appears you can only access schema.Rows by index, so I'm not sure you can get around looping through the rows first before checking by name. In that case, your original solution seems far more elegant!
Note: my original answer suggested checking for presence of a column simply by: reader.GetSchemaTable().Columns["optionalfield"].
Load it into a DataTable and then you can check for column:
DataTable dataTable = new DataTable();
dataTable.Load(reader);
foreach (var item in dataTable.Rows)
{
bool columnExists = item.Table.Columns.Contains("ColumnName");
}
Don't need so much complication, just this:
bool bFieldExists = datareader.GetSchemaTable().Columns.Contains(strFieldName);

Categories