Check if column exists before execute select clause - c#

I use a DataTable in a foreach loop from sql like:
foreach(var i in tasks)
{
// query sql
var timeOfTasks = db.GetTableBySQL($"exec usp_Get_WorkedProyectTime #TaskTypeCategoryId = '{i.TaskTypeCategoryId}', #TaskId= '{i.TaskId}'");
// read columns (different rows have different columns)
var progressToBackCheck = (from DataRow dr in timeOfTasks.Rows select dr["ProgressToBackCheck"]).FirstOrDefault();
var backcheckToCorrection = (from DataRow dr in timeOfTasks.Rows select dr["BackcheckToCorrection"]).FirstOrDefault();
var correctionsToCompleted = (from DataRow dr in timeOfTasks.Rows select dr["CorrectionsToCompleted"]).FirstOrDefault();
var progressToCompleted = (from DataRow dr in timeOfTasks.Rows select dr["ProgressToCompleted"]).FirstOrDefault();
}
Not all task results have the same data rows. And each row doesn't contain all fields. Is there a way to check if a column exists in the result, before I use query for it?

You can try to use DataColumnCollection.Contains to check the column is exists in the data table.
if (timeOfTasks.Columns.Contains("ProgressToBackCheck"))
{
}
You can use this linq to get field, add where linq
where timeOfTasks.Columns.Contains("ProgressToBackCheck")
look like this.
var progressToBackCheck = (
from DataRow dr in timeOfTasks.Rows
where timeOfTasks.Columns.Contains("ProgressToBackCheck")
select dr["ProgressToBackCheck"]
).FirstOrDefault();

Related

How to Get Single Column Value in c# LINQ?

DataTable Master_Table = Execute_Manager.getTableDataSet(connection, select_query, master_table);
string RuleName = (From EachRow in Master_Table
where EachRow.Field<string>("RuleID") == "123456"
Select EachRow.Field<string>("RuleName")).CopyToDataTable().ToString();
I need to get single Column Value using LINQ in Datatable c#
You could do something like the following I have added in the two examples below:
string carManufacturer = "BMW";
DataTable dt = new DataTable();
int id = (from DataRow dr in dt.Rows
where (string)dr["CarManufacturer"] == carManufacturer
select (int)dr["id"]).FirstOrDefault();
string columnValue = dt.Rows[0]["ColumnName"].ToString();
What column value are you trying to fetch from your data table?

Not able to delete multiple rows from datatable

I have following code. Data is datable
DataRow[] rows;
rows = data.Select("meta_key = '_edit_lock'");
rows = data.Select("meta_key = 'resume_path'");
foreach (DataRow r in rows)
r.Delete();
data.AcceptChanges();
I can only delete resume_path row from datatable and can't delete _edit_lock.
The select filter should include both conditions, like in the code below.
DataRow[] rows;
rows = data.Select("meta_key = '_edit_lock' OR meta_key = 'resume_path'");
foreach (DataRow r in rows) {
r.Delete();
}
data.AcceptChanges();
Select filter could also be expressed as
"meta_key IN ('_edit_lock', 'resume_path')"

GROUP BY in datatable select using c#

I have a dataTable which has rows as shown in below image,
I would like to write groupby statement with select on that datatable for getting output as below,
select ApplicationName, count(*) from DataTableName
group by ApplicationName
where DataTableName should be replaced by the actual name of your table in the database, and ApplicationName should be replaced by the name of the column in that table that contains applicatin name
Try this using LINQ in C#
var result = from tab in dt.AsEnumerable()
group tab by tab["ApplicationNmae"]
into groupDt
select new
{
ApplicationNmae = groupDt.Key,
Sum = groupDt.Sum((r) => decimal.Parse(r["Count"].ToString()))
};
DataTable dt1 = new DataTable();
dt1 = dt.Clone();
foreach (var item in result)
{
DataRow newRow = dt1.NewRow();
newRow["ApplicationNmae"] = item.ApplicationNmae;
newRow["Count"] = item.Sum;
dt1.Rows.Add(newRow);
}
Grid.DataSource = dt1;
Ref: Group by in DataTable Column sum
Simply this...
SELECT ApplicationName, COUNT(*) [Count]
FROM THETABLENAME
GROUP BY ApplicationName
or with ordering and filtering (where there is a duplication and order by the count)...
SELECT ApplicationName, COUNT(*) [Count]
FROM THETABLENAME
GROUP BY ApplicationName
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC

compare two datatables with multiple columns with a unique id

I have written a program to compare two datatables with unique ids and create another datatable to insert certain columns which have the same id in common. I have demonstrated my requirement below.
These are the tables that needs to be compared:
And i need the output as below
but i receive an empty table as the result. I cannot understand where have i gone wrong. Could you please help me on this. I have provided my coding below.Please not that quantity and input are two datatables
DataTable result = new DataTable();
result.Columns.AddRange(new DataColumn[2] { new DataColumn("id"), new DataColumn("qty") });
foreach (DataRow row1 in input.Rows)
{
foreach (DataRow row2 in quantity.Rows)
{
if (row1["id"].ToString() == row2["id"].ToString())
{
result.ImportRow(row2);
}
else
{
result.ImportRow(row1);
}
}
}
return result;
You need a Left Join of 2 Data tables.
DataTable dtinput = new DataTable();
DataTable dtquantity = new DataTable();
dtinput.Columns.Add("id",typeof(int));
dtinput.Rows.Add("2");
dtinput.Rows.Add("4");
dtinput.Rows.Add("7");
dtquantity.Columns.Add("id", typeof(int));
dtquantity.Columns.Add("qty", typeof(int));
dtquantity.Rows.Add("1", "12");
dtquantity.Rows.Add("2", "13");
dtquantity.Rows.Add("3", "5");
dtquantity.Rows.Add("4", "6");
dtquantity.Rows.Add("7", null);
var results = from table1 in dtinput.AsEnumerable()
join table2 in dtquantity.AsEnumerable()
on (int)table1["id"] equals (int)table2["id"]
into outer
from row in outer.DefaultIfEmpty<DataRow>()
select row;
DataTable dt = results.CopyToDataTable();
This diagram should help you in future:
Try something like this:
var result = input.Rows.Where(x => quantity.Rows.Amy(y => x == y));
I hope this helps!

How to populate DataTable with anonymous LINQ result

I have the following LINQ query:
var timesheets = from timesheet in entities.Timesheets
join timesheetTask in entities.Timesheet_Task on timesheet.Id equals timesheetTask.Timesheet_Id
join task in entities.Tasks on timesheetTask.Task_Id equals task.Id
join project in entities.Projects on task.Project_Id equals project.Id
join department in entities.Departments on project.Department_Id equals department.Id
where timesheet.Employee_Id == employeeId
select new
{
date = timesheet.Date,
taskName = task.Name,
projectName = project.Name,
projectDesc = project.Description,
departmentName = department.Name,
taskEstimatedHours = task.Estimated_Hours,
timesheetHours = timesheetTask.Hours
};
How can I put these results into a DataTable which I can then bind to a DataGridView control?
This is what I'm currently doing:
table.Columns.Add("date");
table.Columns.Add("taskName");
table.Columns.Add("projectName");
table.Columns.Add("projectDesc");
table.Columns.Add("departmentName");
table.Columns.Add("taskEstimatedHours");
table.Columns.Add("timesheetHours");
foreach (var item in timesheets)
{
table.Rows.Add(item.date, item.taskName, item.projectName,
item.projectDesc, item.departmentName, item.taskEstimatedHours,
item.timesheetHours);
}
}
Update: Here is my updated code:
DataTable table = new DataTable();
using (PTMS_DataEntities entities = new PTMS_DataEntities())
{
var timesheets = from timesheet in entities.Timesheets
join timesheetTask in entities.Timesheet_Task on timesheet.Id equals timesheetTask.Timesheet_Id
join task in entities.Tasks on timesheetTask.Task_Id equals task.Id
join project in entities.Projects on task.Project_Id equals project.Id
join department in entities.Departments on project.Department_Id equals department.Id
where timesheet.Employee_Id == employeeId
select new
{
date = timesheet.Date,
taskName = task.Name,
projectName = project.Name,
projectDesc = project.Description,
departmentName = department.Name,
taskEstimatedHours = task.Estimated_Hours,
timesheetHours = timesheetTask.Hours
};
table.Columns.Add("date", typeof(DateTime));
table.Columns.Add("taskName", typeof(string));
table.Columns.Add("projectName", typeof(string));
table.Columns.Add("projectDesc", typeof(string));
table.Columns.Add("departmentName", typeof(string));
table.Columns.Add("taskEstimatedHours", typeof(int));
table.Columns.Add("timesheetHours", typeof(int));
List<DataRow> list = new List<DataRow>();
foreach (var item in timesheets)
{
//table.Rows.Add(item.date, item.taskName, item.projectName,
// item.projectDesc, item.departmentName, item.taskEstimatedHours,
// item.timesheetHours);
var row = table.NewRow();
row.SetField<DateTime>("date", item.date);
row.SetField<string>("taskName", item.taskName);
row.SetField<string>("projectName", item.projectName);
row.SetField<string>("projectDesc", item.projectDesc);
row.SetField<string>("departmentName", item.departmentName);
row.SetField<int>("taskEstimatedHours", item.taskEstimatedHours);
row.SetField<int>("timesheetHours", item.timesheetHours);
list.Add(row);
}
table = list.CopyToDataTable();
}
Here is the SQL query I tested in SSMS (which should be the equivalent of the LINQ query):
SELECT dbo.Department.Name, dbo.Task.Name AS Expr1, dbo.Task.Estimated_Hours, dbo.Timesheet.Date, dbo.Project.Name AS Expr2, dbo.Project.Description,
dbo.Timesheet_Task.Date AS Expr3
FROM dbo.Department INNER JOIN
dbo.Project ON dbo.Department.Id = dbo.Project.Department_Id INNER JOIN
dbo.Task ON dbo.Project.Id = dbo.Task.Project_Id INNER JOIN
dbo.Timesheet_Task ON dbo.Task.Id = dbo.Timesheet_Task.Task_Id INNER JOIN
dbo.Timesheet ON dbo.Timesheet_Task.Timesheet_Id = dbo.Timesheet.Id
If you really want to populate DataTable:
// your query
var timesheets = ...
// design table first
DataTable table = new DataTable();
table.Columns.Add(new DataColumn
{
ColumnName = "TaskName",
DataType = typeof(String);
});
...
List<DataRow> list = new List<DataRow>();
foreach (var t in timesheets)
{
var row = table.NewRow();
row.SetField<string>("TaskName", t.taskName); // extension method from System.Data.DataSetExtensions.dll
...
list.Add(row);
}
DataTable table = list.CopyToDataTable(); // extension method too
Or more LINQ way:
timesheets
.Select(t =>
{
var row = table.NewRow();
...
return row;
})
.CopyToDataTable();
Or in same query syntax. Implement a method:
static DataRow NewRow(DataRow row, string taskName, ....)
{
...
}
Then query itself:
(from ...
where ...
select NewRow(table.NewRow(), task.Name, ...)
).CopyToDataTable();
Call .ToList().
The resulting List<T> can also be bound to a DataGridView, and is easier to work with than a DataTable.
I'm using FastMember for this purpose. It uses IL instead of reflection (much faster) to iterate over all of the property and field values automatically. Code sample from the site:
IEnumerable<SomeType> data = ...
var table = new DataTable();
using(var reader = ObjectReader.Create(data))
{
table.Load(reader);
}

Categories

Resources