Find value from the dataview using column name - c#

I am trying to find value from dataview using column name. My dataset shows value but my if condition returns false. I am working in asp.net using c#.
I have tried with different code. I am trying to get value like this
dv[0].DataView.Table.Columns[0].ToString().Contains("52")
//RETURN FALSE
OR
dv[0].Equals("52")
// //RETURN FALSE
OR
dv[0].Find("52")
// //RETURN FALSE
Following is my dataset

If "GBA_Nbr_GBAccount" column is a string type, it may contains spaces.
You should trim text before comparing. Try this
dv[0]["GBA_Nbr_GBAccount"].ToString().Trim().Equals("52");

You could use Linq to query the datatable or the dataview. For example, assuming your column is of type string:
var condition = yourDataTable.AsEnumerable()
.Any(r => r.Field<string>("GBA_Nbr_GBAccount") == "52");
var condition = yourDataView.Cast<DataRowView>()
.Any(rv => rv.Row.Field<string>("GBA_Nbr_GBAccount") == "52");
If the column was an integer, just change the Field<string> to Field<int> and compare against an integer, not a string
var condition = yourDataTable.AsEnumerable()
.Any(r => r.Field<int>("GBA_Nbr_GBAccount") == 52);
var condition = yourDataView.Cast<DataRowView>()
.Any(rv => rv.Row.Field<int>("GBA_Nbr_GBAccount") == 52);
Example application using string column:
static void Main(string[] args)
{
DataSet dataset = new DataSet();
dataset.Tables.Add(new DataTable("table1"));
dataset.Tables[0].Columns.Add(new DataColumn("Value", typeof(string)));
dataset.Tables[0].Rows.Add("10");
dataset.Tables[0].Rows.Add("52");
DataTable table = dataset.Tables[0];
DataView view = table.DefaultView;
var condition1 = table.AsEnumerable().Any(r => r.Field<string>("Value") == "52");
var condition2 = view.Cast<DataRowView>().Any(rv => rv.Row.Field<string>("Value") == "52");
Console.WriteLine(String.Format("Result querying datatable: '{0}'. Result using dataview:'{1}'", condition1, condition2));
Console.ReadLine();
}
If you are really using a string for the column, check for white spaces and apply a trim if needed.

One way to check for the existence of a specific column in a dataview would be like the following:
if (dv.Table.Columns["Name"] != null)
{
//Name column exists. Add Logic here
}

Use the DataViewManager object instead
it has a DataSet property associated with it and the dataset has all the normal dataset features. So, you can traverse the dataset.tables[index] object...
Hope it helps
Example: dv.DataViewManager.DataSet.Tables[0].Rows[0][1]
Thanks,
Sam

int rowIndex = dv.Find("52");
if (rowIndex == -1) {
Console.WriteLine("No match found.");
}
else {
Console.WriteLine("{0}, {1}",
dv(rowIndex)("GBA_Nbr_GBAccount").ToString(),
dv(rowIndex)("GBA_Nam_GBAccount").ToString());
}
I think that may be the solution to your problem, or at the very least point you in the right direction.

Related

How to get Column Names using Linq from DataTable

I'm trying to use LINQ on DataTable that's getting it's data from sql. So I have a data table with it's usual columns and rows and it appears exactly like a sql select statement. Now I need to get certain rows and columns (including column names) from this data.
I converted the datatable to something LINQ can use using AsEnumerable but I'm not sure what exactly it does. Does it convert the data into an array of objects where each row becomes an object?
I'm used to working with Javascript and it's newer arrow functions so i'd like to use Linq with lambda to keep it consistent.
I'm trying to get rows and column names where first column has a value equal to 2018
DataTable myTable = getData(); // populates the datatable and I've verified the data
var linqTable = myTable.AsEnumerable().Select( x => x[0] = 2018);
I need to get the rows and column names. e.g like an object or array of objects.However, the code above doesn't return the data or column names but just two rows with 2018 in it.
My goal is to eventually serialize this data as json and send it to web page.
To Get the column names:
myTable.Columns.Cast<DataColumn>().Select(dc =>dc.ColumnName).ToList();
The problem is Select() is projecting the objects into a new form. You are seeing 2018 because of '=' instead of '=='. You need to use Where()
var linqTable = myTable.AsEnumerable().Where( x => x.Field<int>(0) == 2018);
You will still end up with a list of DataRows though. The DataTable object isn't really what you should be using because it already provides a nice way to filter its rows:
myTable.Rows.Find(2018);
If you are trying to convert it to a list of objects you should use the Select() method something like:
var linqTable = myTable.AsEnumerable().Where(x => x.Field<int>(0) == 2018)
.Select(x => new
{
year = x[0],
p1 = x[1],
p2 = x[2] // etc...
});
You can create the following function:
public static DataTable CreateDataTableFromAnyCollection<T>(IEnumerable<T> list)
{
Type type = typeof(T);
var properties = type.GetProperties();
DataTable dataTable = new DataTable();
foreach (PropertyInfo info in properties)
{
dataTable.Columns.Add(new DataColumn(info.Name, Nullable.GetUnderlyingType(info.PropertyType) ?? info.PropertyType));
}
foreach (T entity in list)
{
object[] values = new object[properties.Length];
for (int i = 0; i < properties.Length; i++)
{
values[i] = properties[i].GetValue(entity,null);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
and pass any type of object your LINQ query returning.
DataTable dt = CreateDataTableFromAnyCollection(query);
I hope this will help you.
Creating a DataTable From a Query (LINQ to DataSet)

c# wildcards not matching datatable column values

I am having an issue trying to match data table column names with a string containing a wildcard.
I have a data table with various column names which includes a set named like follows: "PsA", "PsB", "PsC", ect. I want to iterate through all the columns containing Ps in the title and use those titles to extract the data.
I currently have the following code which fails to return any matches. I have substituted a straight value in the if statement ("PsA") as a test, which works fine; however, when I use the wildcard, I get no matches. I have also tried Regex with no luck.
private void dfaSection_SelectedIndexChanged(object sender, EventArgs e)
{
string psText = null;
string colID = "Ps*";
offBox.Text = ""; //Clear textbox if a reselection occurs
psBox.Text = ""; //Clear textbox if a reselection occurs
info.offTitle = dfaSection.Text; //Set textbox from variable
dt = opr.findOffByTitle(info); //Get datatable from SQL database
if(dt.Rows.Count > 0)
{
offBox.Text = dt.Rows[0][5].ToString(); //Set textbox from datatable
foreach(DataColumn dc in dt.Columns) //Loop through datatable columns
{
if (dc.ColumnName.ToString() == colID) //Check that column title matches test string - Later addition--> && dt.Rows[0][dc].ToString() != null)
{
psText = dt.Rows[0][dc].ToString() + "\n\n"; //Add data from matched column to string variable
}
}
psBox.Text = psText; //Set textbox from variable
}
}
Edit: Issue fixed using .Contains(colID) Column names now being matched, string are now not being loaded to the psText variable, but I'll spend some time with that and get it working. Thanks Skaros Ilias.
I am not so failiar with C, but == for sure is not the right method.
you need to use the contains method. As I said, I am not familiar with it, but the docs have a good example of it.
String s = "This is a string.";
String sub1 = "this";
Console.WriteLine("Does '{0}' contain '{1}'?", s, sub1);
StringComparison comp = StringComparison.Ordinal;
Console.WriteLine(" {0:G}: {1}", comp, s.Contains(sub1, comp));
take a breakpoint a check what is column name and colID at failure moment.How are you going to solve problems, when don't even know values?
Use dc.ColumnName.ToString().StartsWith(). Contains() is good only untill string endswith.
As per this answer before : Regular expression wildcard
And here is sample of code :
private static bool Match(string pattern, string stringToCheck) {
var finalPattern = pattern.Replace("*", ".*?");
Regex regex = new Regex(finalPattern);
return regex.IsMatch(stringToCheck);
}

How can I filter a DataTable without brute-forcing it?

I populate a DataTable with a Stored Procedure. In one particular instance, though, I need to filter those results down to a subset of what they normally are, based on the vaue of a member value in the result set that is not one of the parameters provided the Stored Procedure.
ISTM that it should be doable to filter the DataTable, assigning a subset of itself to itself for this singular scenrio.
I don't know what exact code I need for this, but the pseudocode would, I think, be something like this ("dtUsage" is a DataTable):
dtUsage = dtUsage.Rows Where MemberNo in ["0451", "050", "067"];
I could use another DataTable temporarily, and loop through the first one, conditionally adding rows to the second one, but I'm sure there is a more elegant way to do this with LINQ or so.
UPDATE
Based on what I see here, something like this might work:
DataRow[] result = dtUsage.Select("MemberNo IN [\"103\",\"016\",\"04501\"]");
...but how to then assign result to the data table?
Neither this:
dtUsage = result;
...nor this:
dtUsage.Rows = result;
...compiles. Nor does this:
DataTable dt = new DataTable();
foreach (DataRow drp in result)
{
dt.Add(drp);
}
You could use something like this I guess.
dtUsage = dtUsage.Where(data => data.MemberNo == '0451' || data.MemberNo == '050' || data.MemberNo == '067')
Edit: Or maybe this?
var results = from row in dtUsage.AsEnumerable()
where (row.Field<string>("MemberNo") == "0451" ||
row.Field<string>("MemberNo") == "050" ||
row.Field<string>("MemberNo") == "067")
select row;
You would probably want something like:
var result = from x in dtUsage.AsEnumerable()
where new string[]{"0451", "050", "067"}.Contains(x.Field<string>("MemberNo"))
select x;

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

Categories