How to query a datatable - c#

I am using a XML file and the data from the XML is set into a dataset and user selected table is stored as a datatable.A query is been generated with filter criteria, grouping, aggregate function, expressions etc.Is it possible to query the datatable?
I did come accross table.Select(filter criteria, sort) method.but kindly let me know how grouping, aggregate function and expression (eg: Column1 + Column2 as SumColumn) can be got.

You could query the data using LINQ - assuming you are using a .Net Framework version that supports it. Check out LINQ To Dataset

Unfortunately, table.Select(filterCriteria, sort) is your only option without LINQ (I'm not a LINQ guru, so don't ask me what it can do).
Anytime I need something specific, I create/add that column to the DataTable.
DataTable table = new DataTable();
// code that populates the table
DataColumn c = table.Columns.Add("Column1 + Column2", typeof(int));
int Sum = 0;
for (int i = 0; i < table.Rows.Count; i++) {
r = table.Rows[i];
int col1 = (int)r["Column1"];
int col2 = (int)r["Column2"];
int both = col1 + col2;
Sum += both;
r[c] = string.Format("{0}", both);
}
DataRow summaryRow = table.NewRow();
summaryRow[c] = (int)((float)Sum / table.Rows.Count + 0.5); // add 0.5 to round
table.Rows.Add(summaryRow);
HTH.

Related

Insert NON-DUPLICATE Data into SQL Database from Excel file using ASP.NET Core 3.1

I'm trying to use two C# DataTables like below to meet my requirement.
dtExcelData: This DataTable holds the data which is uploaded from Excel file. This data should be inserted into SQL Server Database based on certain conditions which were mentioned below.
dtDbData: This DataTable holds data from Database. Preparing this DataTable just by reading two columns which represent Primary Key.
I'm using dtExcelData datatable to save records into SQL Server Database after uploading Excel file.
The requirement is that I should validate dtExcelData before I insert into database. There exists 39 columns in dtExcelData datatable with the column headings column1, column2, ... column39. And, the number of rows can range upto 400 (or even little more).
I've to do validation like below:
column6, and column22 from Excel file combinedly is considered as primary key. If this same data is already available in database, I should NOT consider that record to insert into database. I can simply ignore that record. All other records should be inserted into database.
I've tried number of approaches to meet this requirement, but unable to arrive to proper solution.
I am looking for some approach like below:
dtExcelData.Except(dtDbData, SomeDataComparerForTheseTwoColumns)
Looking for some help.
Below is a work demo, you can refer to it.
DataTable dtExcelData = new DataTable();
dtExcelData.Columns.Add("Id", typeof(int));
dtExcelData.Columns.Add("Name", typeof(string));
DataRow row = dtExcelData.NewRow();
row["Id"] = 1;
row["Name"] = "John";
dtExcelData.Rows.Add(row);
DataRow row2 = dtExcelData.NewRow();
row2["Id"] = 2;
row2["Name"] = "Max";
dtExcelData.Rows.Add(row2);
DataRow row3= dtExcelData.NewRow();
row3["Id"] = 2;
row3["Name"] = "John";
dtExcelData.Rows.Add(row3);
DataRow row4 = dtExcelData.NewRow();
row4["Id"] = 1;
row4["Name"] = "Max";
dtExcelData.Rows.Add(row4);
DataRow row5 = dtExcelData.NewRow();
row5["Id"] = 3;
row5["Name"] = "Tom";
dtExcelData.Rows.Add(row5);
DataTable dtDbData = new DataTable();
dtDbData.Columns.Add("Id", typeof(int));
dtDbData.Columns.Add("Name", typeof(string));
DataRow rrow = dtDbData.NewRow();
rrow["Id"] = 1;
rrow["Name"] = "John";
dtDbData.Rows.Add(rrow);
DataRow rrow2 = dtDbData.NewRow();
rrow2["Id"] = 2;
rrow2["Name"] = "Max";
dtDbData.Rows.Add(rrow2);
//match up the column and then find the missing.
var matched = from r1 in dtExcelData.AsEnumerable()
join r2 in dtDbData.AsEnumerable()
on r1.Field<int>(0) equals r2.Field<int>(0)
where r1.Field<string>(1) == r2.Field<string>(1)
select r1;
//This should give you the rows which do not have a match
var missing = from table1 in dtExcelData.AsEnumerable()
where !matched.Contains(table1)
select table1;
if (missing.Any())
{
//use for/foreach loop through each row and then insert into database.
// do something with these rows
}
result:

Merging DataTables with Condition

I would like to merge DataTables in a list using sum or average depending on conditions. For example:
private DataTable getData(List<DataTable> datas, string[] KeyColumnNames, string valueCol)
{
List<DataTable> dataTables = datas;
//if datas has 3 dataTables in it : dt1, dt2, dt3
// then I want to create another dataTable dtAll which will have the sum of
// valueCol of all three datatables for the row which will be conditioned using
// KeyColumnNames (can be multiple Primary keys)
return dataTable;
}
Consider all datatables to be exactly same but different values as they are tables from similar schemas but different data centers.
Thanks.
I would do
List<DataTable> dataTableList = dtList;
DataTable unionDataTable = new DataTable();
for(int i = 0; i < dtList.Count; i++)
unionDataTable = Union(unionDataTable, dtList[i], "UnionDataTable");
where the Union method is defined by something like the following
public static DataTable Union(DataTable First, DataTable Second, string strReturnedTableName)
{
// Result table.
DataTable table = new DataTable(strReturnedTableName);
// Build new columns.
DataColumn[] newcolumns = new DataColumn[First.Columns.Count];
for (int i = 0; i < First.Columns.Count; i++)
newcolumns[i] = new DataColumn(First.Columns[i].ColumnName, First.Columns[i].DataType);
// Add new columns to result table.
table.Columns.AddRange(newcolumns);
table.BeginLoadData();
// Load data from first table.
foreach (DataRow row in First.Rows)
table.LoadDataRow(row.ItemArray, true);
// Load data from second table.
foreach (DataRow row in Second.Rows)
table.LoadDataRow(row.ItemArray, true);
table.EndLoadData();
return table;
}
I hope this helps.
Edit. You can pass an Action in to the method and use this in the foreach blocks to do what you want.
Your question is way too vague to provide any actual code but you want to do a LINQ Join. It works about the same as a SQL join. This question shows joins in both query and method syntax How to do a join in linq to sql with method syntax? also you can look at the msdn docs here; http://msdn.microsoft.com/en-us/library/bb311040.aspx

Duplicacy check between DATABASE and DATATABLE

i have one column in my database by name PNUMSET (Primary Key) contains unique data.(approx 1L rows)
and in application i have one datatable with one column name NEWPNUM which contains data.
i want to check that no value is matching between existing database and current datatable values..
Note:- no of rows may or may not be same in database and datatable.
so far i tried.....
String query = "Select PNUMSET FROM DUMMYTABLE";
MySqlDataAdapter msda = new MySqlDataAdapter(query, connection);
msda.Fill(dt);
for (int k = 0; k < Class1.global_dataset.Tables[0].Rows.Count; k++)
{
if (dt.Rows.Contains(Class1.global_dataset.Tables[0].Rows[k][4].ToString()))
{
MessageBox.Show("Baj Gaya Ghanta!!!!");
}
}
You can use Linq-To-DataTable to join both tables on this column, for example:
var commonRows = from r1 in dt.AsEnumerable()
join r2 in Class1.global_dataset.Tables[0].AsEnumerable()
on r1.Field<int>(4) equals r2.Field<int>(4)
select r1;
if(commonRows.Any())
{
// do something with these rows
}
(assuming the 5th column and it's type int)
Note that although Enumerable.Join is quite efficient it might be better to compare this in the database instead of loading all into memory.

Copy rows from one Datatable to another DataTable?

How can I copy specific rows from DataTable to another Datable in c#? There will be more than one row.
foreach (DataRow dr in dataTable1.Rows) {
if (/* some condition */)
dataTable2.Rows.Add(dr.ItemArray);
}
The above example assumes that dataTable1 and dataTable2 have the same number, type and order of columns.
Copy Specified Rows from Table to another
// here dttablenew is a new Table and dttableOld is table Which having the data
dttableNew = dttableOld.Clone();
foreach (DataRow drtableOld in dttableOld.Rows)
{
if (/*put some Condition */)
{
dtTableNew.ImportRow(drtableOld);
}
}
Try This
String matchString="ID0001"//assuming we have to find rows having key=ID0001
DataTable dtTarget = new DataTable();
dtTarget = dtSource.Clone();
DataRow[] rowsToCopy;
rowsToCopy = dtSource.Select("key='" + matchString + "'");
foreach (DataRow temp in rowsToCopy)
{
dtTarget.ImportRow(temp);
}
Check this out, you may like it (previously, please, clone table1 to table2):
table1.AsEnumerable().Take(recodCount).CopyToDataTable(table2,LoadOption.OverwriteChanges);
Or:
table1.AsEnumerable().Where ( yourcondition ) .CopyToDataTable(table2,LoadOption.OverwriteChanges);
Supported in: 4, 3.5 SP1, you can now just call a method on the object.
DataTable dataTable2 = dataTable1.Copy()
As a result of the other posts, this is the shortest I could get:
DataTable destTable = sourceTable.Clone();
sourceTable.AsEnumerable().Where(row => /* condition */ ).ToList().ForEach(row => destTable.ImportRow(row));
I've created an easy way to do this issue
DataTable newTable = oldtable.Clone();
for (int i = 0; i < oldtable.Rows.Count; i++)
{
DataRow drNew = newTable.NewRow();
drNew.ItemArray = oldtable.Rows[i].ItemArray;
newTable.Rows.Add(drNew);
}
I needed to copy rows from multiple tables with the same structure into a new table to be used as a datasource for datagridview:
// Generate DataTable[] alltables from multiple datatables
DataTable newTable = alltables[0].Clone();
foreach (DataTable dt in alltables)
{
for (int i = 0; i < dt.Rows.Count; i++)
newTable.Rows.Add(dt.Rows[i].ItemArray);
}
below sample would be the fastest way to copy one row.
each cell is being copied based on the column name.
in case you dont need a specific cell to copy then have a try catch or add if.
if your going to copy more than 1 row then loop the code below.
DataRow dr = dataset1.Tables[0].NewRow();
for (int i = 0; i < dataset1.Tables[1].Columns.Count; i++)
{
dr[dataset1.Tables[1].Columns[i].ColumnName] = dataset1.Tables[1].Rows[0][i];
}
datasetReport.Tables[0].Rows.Add(dr);
dataset1.Tables[1].Rows[0][i]; change the index 0 to your specified row index or you can use a variable if your going to loop or if its going to be logical
private void CopyDataTable(DataTable table){
// Create an object variable for the copy.
DataTable copyDataTable;
copyDataTable = table.Copy();
// Insert code to work with the copy.
}
To copy whole datatable just do this:
DataGridView sourceGrid = this.dataGridView1;
DataGridView targetGrid = this.dataGridView2;
targetGrid.DataSource = sourceGrid.DataSource;
For those who want single command SQL query for that:
INSERT INTO TABLE002
(COL001_MEM_ID, COL002_MEM_NAME, COL002_MEM_ADD, COL002_CREATE_USER_C, COL002_CREATE_S)
SELECT COL001_MEM_ID, COL001_MEM_NAME, COL001_MEM_ADD, COL001_CREATE_USER_C, COL001_CREATE_S
FROM TABLE001;
This query will copy data from TABLE001 to TABLE002 and we assume that both columns had different column names.
Column names are mapped one-to-one like:
COL001_MEM_ID -> COL001_MEM_ID
COL001_MEM_NAME -> COL002_MEM_NAME
COL001_MEM_ADD -> COL002_MEM_ADD
COL001_CREATE_USER_C -> COL002_CREATE_USER_C
COL002_CREATE_S -> COL002_CREATE_S
You can also specify where clause, if you need some condition.
There is better way to do this.
DataTable targetDataTable = new DataTable();
targetDataTable = changedColumnMetadata.AsEnumerable().Where(dataRow => entityName.Equals(dataRow["EntityName"])).CopyToDataTable();
Please try this and let me know in case of any issues.
You can do it calling the DataTable.Copy() method, for example:
DataSet ds = new DataSet();
System.Data.DataTable dt = new System.Data.DataTable();
dt = _BOSearchView.DS.Tables[BusLib.TPV.TableName.SearchView].Copy();
ds.Tables.Add(dt);
UltGrdSaleExcel.SetDataBinding(ds, dt.TableName, true);
use Merge, this will append all rows of newDataTable with oldDateTale
oldDateTale.Merge(newDataTable);

how to display few records from a database in dataviewgrid control in c#?

suppose i am having a database table with 20 records and of that i want to display only 10 records in the dataviewgrid control, how can i achieve this?
You can write a query like this:
SELECT * FROM (
SELECT TOP 10 * FROM (
SELECT TOP 20 * FROM MyTable ORDER BY MyID ASC
) AS NewTbl ORDER BY MyID DESC
) AS NewTbl2 ORDER BY MyID ASC
This selects records 11-20. If you want to select records 6-15 just change 20 to 15.
20 is the "last record to select" and 10 is the number of records before and up to 20.
Edit (After your comment about having all rows in a DataSet):
var newDS = new DataSet();
newDS.Tables.Add(oldDSWithAllRows.Tables["YourTableName"].Clone());
foreach (DataRow myDataRow in oldDSWithAllRows.Tables["YourTableName"].Rows)
{
if (/* Your criteria */)
{
newDS.Tables["YourTableName"].ImportRow(myDataRow);
}
}
myDataGridView.DataSource = newDS;
Select only the 10 records you want.
In SQL use the TOP clause:
SELECT TOP 10 * FROM myTable
use DataTable.Select
usage:
dataSet1.Tables[0].Select("Id>5");
or, better, DataView with a RowFilter, example here
you can set tha DataGridView.DataSource to this DataView
If you're using the latest version of C# you could filter your source with LINQ:
// change Skip to 10 to page through
var filtered = mydatasource.Skip(0).Take(10);
This assumes you've returned your SQL data as an IEnumerable<T>
Suppose we have the following table
DataTable dt = new DataTable();
int counter = 1;
dt.Columns.Add("ID");
dt.Columns.Add("Name");
for (int i = 1; i <= 20; i++)
{
DataRow dr = dt.NewRow();
dr["ID"] = i;
dr["Name"] = string.Format("Name{0}", i);
dt.Rows.Add(dr);
}
You can bind the grid this way:
this.GridView1.DataSource = dt.AsEnumerable().Take(10);
this.GridView1.DataBind();
but:
this can work if you did the following:
-Add two template fields to the gridview
-Add the following function to the code behind page:
protected object GetColumnValue(object Row,string columnName)
{
DataRow dr = Row as DataRow;
return dr[columnName];
}
Edit the DataBindings of the fields of the gridview to bind this way:
GetColumnValue(Container.DataItem,"ID") //for the first Field
GetColumnValue(Container.DataItem,"Name") //for the second field

Categories

Resources