I have a requirement for B2B integration, I will reading flat table from dataset and parse to a normalize form of datatable.
I will have reapting colums in the datatable
Sample Data
Invoice num Amount LineNum Line Amout Ledger
INV1 100 1 50 11101
INV1 100 2 50 25631
rows will repeat with different invoices
How can distinctly select into new datatable ? using ADO.NET
I want to parse the data into following format
Header Table
Invoice num Amount
INV1 100
Line Table
Invoice num LineNum Line Amout Ledger
INV1 1 50 11101
INV1 2 50 25631
QUESTION : I dont know what would be the best way to bring the above format ? I see examples usign linq , DataTable, Views ? I looking for a code snippet.
OK, to start the problem, I am working with a DataTable and data defined as follows. Change names and types to suit your needs.
// I am building this table in code just for the purposes of this answer.
// If you already have your data table, ignore!
DataTable salesTable = new DataTable();
salesTable.Columns.Add("InvoiceNum", typeof(string));
salesTable.Columns.Add("Amount", typeof(decimal));
salesTable.Columns.Add("LineNum", typeof(int));
salesTable.Columns.Add("LineAmount", typeof(decimal));
salesTable.Columns.Add("Ledger", typeof(string));
// This is also just to populate data for the sample.
// Omit as you already have your data.
salesTable.Rows.Add("INV1", 100M, 1, 50M, "11101");
salesTable.Rows.Add("INV1", 100M, 1, 50M, "25631");
Notice that I'm using the overload of .Rows.Add that accepts a params object[] array. The values I'm passing in are in the order and type of the columns they should populate. The code below uses the same approach.
First thing I want to do is define the tables for your new normalized format. First, the header table.
DataTable headerTable = new DataTable();
headerTable.Columns.Add("InvoiceNum", typeof(string));
headerTable.Columns.Add("Amount", typeof(decimal));
And then the line item table.
DataTable lineTable = new DataTable();
lineTable.Columns.Add("InvoiceNum", typeof(string));
lineTable.Columns.Add("LineNum", typeof(int));
lineTable.Columns.Add("LineAmount", typeof(decimal));
lineTable.Columns.Add("Ledger", typeof(string));
After this, I'm going to utilize LINQ to group the original sales table based on the invoice number.
var groupedData = from row in salesTable.AsEnumerable()
group row by row.Field<string>("InvoiceNum") into grp
select grp;
After this, it's just a matter of iterating over the groups and adding the data to the new tables.
foreach (var invoiceGroup in groupedData)
{
string invoiceNumber = invoiceGroup.Key;
decimal amount = invoiceGroup.First().Field<decimal>("Amount");
headerTable.Rows.Add(invoiceNumber, amount);
foreach (DataRow row in invoiceGroup)
{
lineTable.Rows.Add(
invoiceNumber,
row.Field<int>("LineNum"),
row.Field<decimal>("LineAmount"),
row.Field<string>("Ledger")
);
}
}
And now you have your data in the normalized format you prefer. Again, change relevant column names and data types to suit your needs.
Related
I am reading CSV file into datatable.
In my datatable I have 4 columns date, time, value1 and value2.
Date Time VALUE1 VALUE2
05/16/2019 15:08:02 2.01 1.01
05/16/2019 15:08:03 4.02 1.02
05/16/2019 15:08:04 5.03 1.03
I want to merge date and time columns in the datatable into a single column called datetime and need to merge date and time values with comma.
I want like below.
DateTime VALUE1 VALUE2
05/16/2019,15:08:02 2.01 1.01
05/16/2019,15:08:03 4.02 1.02
05/16/2019,15:08:04 5.03 1.03
How to achieve it?
Please help me.
You need to declare one more temporary table to hold columns in table and then by using .Select predicate in linq you can flatten your existing datable rows to newly created table with .CopyToDataTable() extension.
DataTable _dt = new DataTable();
_dt.Columns.Add("DateTime", typeof(string));
_dt.Columns.Add("VALUE1", typeof(double));
_dt.Columns.Add("VALUE2", typeof(double));
DataTable result = dt.AsEnumerable()
.Select(x =>
{
var r = _dt.NewRow();
r["DateTime"] = Convert.ToString(x["Date"]) + ", " + Convert.ToString(x["Time"]);
r["VALUE1"] = Convert.ToDouble(x["VALUE1"]);
r["VALUE2"] = Convert.ToDouble(x["VALUE2"]);
return r;
})
.CopyToDataTable();
In the above code snippet result is a data table that contains flattened output from above LINQ query.
Output:
Try this one.
dt.Columns.Add("DateTime_Merge", typeof(string), "Date+','+Time");
For removing columns
dt.Columns.Remove("Date");
dt.Columns.Remove("Time");
Joining Values Of Two Columns From DataTable
Two columns make it in one columns from datatable
my datatable is
TagNumber, LogNumber Combined
124 1 2
125 1 3
126 2 4
o/p:
TagNumber
124 ~1~2
125 ~1~3
126 ~2~4
combined column is merge from column0 and column1
i dont understand hw can i do please write sample of code
I dont have experience on linq .
I add column bt hw can i merge two columns in that one columns
I got answer:
For i As Integer = 0 To dstemp.Tables(0).Rows.Count - 1
dstemp.Tables(0).Rows(i)(0) = dstemp.Tables(0).Rows(i)("TagNumber") & "~" & dstemp.Tables(0).Rows(i)("LogNumber") & "~" & dstemp.Tables(0).Rows(i)("Combined")
next
Try doing it like this.
dtTwoItems.Columns.Add("Combined", typeof(string), "TagNumber+'/'+LogNumber");
Ok if you really want to do this then you have create a extra DataTable with Three Columns:
TagNumber, LogNumber Combined:
as below:
private DataTable CreateDataTableColumns()
{
DataTable dtThreeItems = new DataTable();
dtThreeItems.Columns.Add("TagNumber", typeof(String));
dtThreeItems.Columns.Add("LogNumber", typeof(String));
dtThreeItems.Columns.Add("Combined", typeof(String));
return dtThreeItems;
}
Now iterate the old datatable as below to get combined value:
foreach (DataRow dr in dtTwoItems.Rows)
{
row = dtThreeItems.NewRow();
row["TagNumber"] = dr["TagNumber"].ToString();
row["LogNumber"] = dr["LogNumber"].ToString();
row["Combined"] = dr["TagNumber"].ToString()+"/"+dr["LogNumber"].ToString() ;
dtThreeItems.Rows.Add(row);
}
Thats All
DataTable is like a container.
It is not proper to join tables.
I recommend you'd use linq.
Did you try to Add new Column to DataTable and then iterate through Each Row to put value by combining them?
EDIT: I Am not sure if Linq or Datatable query have some inbuilt feature to do this, but simple solution is what I tell. Or if you are filling your datatable from any SQL Query based database, then write a SQL that has third column with merged value using concat of columns.
Edit2:
foreach (Datarow r in myTable.Rows) {
r["Newcolumn"] = Convert.ToString(r["c1"]) + "/" + Convert.ToString(r["c2"]);
}
I have five rows in my data table (with column AccountId, Name, Email, Address) and I want to get a specific row on basis of AccountId as all the five rows have different AccountID. I want to filter it on the basis of AccountID. I mean I only need one row from the Data table to process on the basis of AccountId.
How do I get a specfic row from the data table containing the AccountId that I have passed?
Three options:
Use DataTable.Select, providing a filter expression
Iterate over the rows yourself
Use LINQ, with the data table extensions
Personally I'd suggest using the last option (LINQ):
var row = table.AsEnumerable()
.FirstOrDefault(r => r.Field<string>("AccountID") == accountID);
if (row != null)
{
// Use the row
}
Have you looked into the DataTable.Select() method?
http://msdn.microsoft.com/en-us/library/system.data.datatable.select(v=vs.100).aspx
public class DataTableExample
{
public static void Main()
{
//adding up a new datatable
DataTable dtEmployee = new DataTable("Employee");
//adding up 3 columns to datatable
dtEmployee.Columns.Add("ID", typeof(int));
dtEmployee.Columns.Add("Name", typeof(string));
dtEmployee.Columns.Add("Salary", typeof(double));
//adding up rows to the datatable
dtEmployee.Rows.Add(52, "Human1", 21000);
dtEmployee.Rows.Add(63, "Human2", 22000);
dtEmployee.Rows.Add(72, "Human3", 23000);
dtEmployee.Rows.Add(110,"Human4", 24000);
// sorting the datatable basedon salary in descending order
DataRow[] rows= dtEmployee.Select(string.Empty,"Salary desc");
//foreach datatable
foreach (DataRow row in rows)
{
Console.WriteLine(row["ID"].ToString() + ":" + row["Name"].ToString() + ":" + row["Salary"].ToString());
}
Console.ReadLine();
}
}
Example with an array:
http://msdn.microsoft.com/en-us/library/f6dh4x2h(VS.80).aspx
Example with a single Object:
http://msdn.microsoft.com/en-us/library/ydd48eyk
Just use something like this:
DataTable dt = new DataTable();
DataRow dr = dt.Rows.Find(accntID);
Hope this helped you out.
First Datatable is dt
var dt = new DataTable();
dt.Columns.Add("ID");
dt.Columns.Add("First Name");
dt.Rows.Add(1,"name1");
dt.Rows.Add(6,"name6");
dt.Rows.Add(4,"name4");
The second table is dt2
var dt2 = new DataTable();
dt2.Columns.Add("ID");
dt2.Columns.Add("First Name");
dt2.Columns.Add("Last Name");
dt2.Columns.Add("Birthday");
dt2.Rows.Add(1,"name1", "lastName1", 01.01.1991);
dt2.Rows.Add(2,"name2", "lastName2", 02.02.1992);
dt2.Rows.Add(3,"name3", "lastName3", 03.03.1993);
dt2.Rows.Add(4,"name4", "lastName4", 04.04.1994);
dt2.Rows.Add(5,"name5", "lastName5", 05.05.1995);
dt2.Rows.Add(6,"name6", "lastName6", 06.06.1996);
in the third DataTable dt3, I want to get those values where ID is the same
result:
ID Name Birthdate
1 name1 01.01.1991
4 name4 04.04.1994
6 name6 06.06.1996
how to go through the DataTable's in c# ?
Unfortunately, there's no easy way, AFAIK, to join the 2 tables and get the third table automagically unless you are willing to write some code....
You can join them using Linq first:
var common = from c in dt.AsEnumerable()
join x in dt2.AsEnumerable() on c.Field<string>("ID") equals x.Field<string>("ID")
select new object[] { c["ID"],c["First Name"], x["Birthday"] };
And now you can create the destination table with the schema you want:
DataTable dt3 = new DataTable();
dt3.Columns.Add("ID");
dt3.Columns.Add("Name");
dt3.Columns.Add("Birthdate");
foreach (var item in common)
dt3.LoadDataRow(item.ToArray(),true);
Write an SQL Query or a Stored Procedure such that it joins the Two tables like you have depicted. Now use that Query for your DataTable with in .Net. You will get what you need.
Are you adding them to an actual database with a defined schema or just trying to do this in memory? If memory, I would add these to a DataSet which you can then use to filter the criteria becuase in the dataset, you can define their relationship.
You might be looking for adding Relationship between your tables. Check this link.
I guess you will need the DataTables to be in the same DataSet (you can add the DataTables into DataSet).
I have two datatables D1 and D2.
I merged the datatable D2 with D1 as follows:
D1.Merge(D2);
But now, I want to remove the DataTable D2 from the D1. How to achieve this?
This may not be the most beautiful solution, but you can consider adding a distinctive column to your tables. I set those values by hand, but for example if your datatables are filled from a SQL query, you can easily add that distinctive column in those queries and use them accordingly.
D1.Columns.Add("ORIGINAL_DATATABLE_NAME", typeof(int));
D2.Columns.Add("ORIGINAL_DATATABLE_NAME", typeof(int));
foreach(DataRow row in D1.Rows)
row["ORIGINAL_DATATABLE_NAME"] = 1;
foreach(DataRow row in D2.Rows)
row["ORIGINAL_DATATABLE_NAME"] = 2;
D1.Merge(D2);
DataRow[] rows = D1.Select("ORIGINAL_DATATABLE_NAME=1", "");
DataSet ds = new DataSet();
ds.Merge(rows, false, MissingSchemaAction.Add);
ds.Tables[0].Columns.Remove("ORIGINAL_DATATABLE_NAME");