c# - DataTable expression column using linq - c#

I need to add columns from one datatable to another only if the columns in second datable not exists and also the second datatable has expression column that needs to set value from first datatable column using linq.
I have achieved this using foreach but how to do without foreach in linq ?
DataTable first = new DataTable();
first.Clear();
first.Columns.Add("Name");
first.Columns.Add("Exp");
DataRow _ra = dt1.NewRow();
_ra["Name"] = "Column_1";
_ra["Exp"] = "ExpTarget * Column_3";
first.Rows.Add(_ra);
DataRow _r = dt1.NewRow();
_r["Name"] = "Column_2";
_r["Exp"] = "ExpTarget * Column_3";
first.Rows.Add(_r);
DataRow _r2 = dt1.NewRow();
_r2["Name"] = "Column_3";
_r2["Exp"] = "ExpTarget";
first.Rows.Add(_r2);
DataTable second = new DataTable();
second.Clear();
second.Columns.Add("Column_3",typeof(System.Int16));
second.Columns.Add("ExpTarget",typeof(System.Int16));
DataRow _r21 = table.NewRow();
_r21["Column_3"] = 100;
_r21["ExpTarget"] = 2;
second.Rows.Add(_r21);
Code to add columns & expression is below, i need to avoid foreach linq below for expression column, how to do it without foreach ?
// get all columns from first datatable
string[] col = string.Join(",", first.AsEnumerable().Select(x => x["Name"].ToString()).ToArray()).Split(',').ToArray();
// get all columns and expression from first datatable
List<string> exp = string.Join(",", first.AsEnumerable().Select(x => x["Name"].ToString() + "~" + x["Exp"].ToString()).ToArray()).Split(',').ToList();
List<string[]> list = new List<string[]>();
list.Add(col);
second.Columns.AddRange(list.First().Select(r => second.Columns.Contains(r) ? second.Columns["Dummy"] : new DataColumn(r, typeof(System.Decimal))).ToArray());
exp.ForEach(r =>
{
second.Columns[r.ToString().Split('~')[0].ToString()].Expression = r.ToString().Split('~')[1].ToString();
});

Related

Need help Creating a Datatable from a list with possible null values

I need some assistance in the best way to edit my DataTable to handle possible null values.
In this instance their is potential for any of the items from the list being added to the DataTable to be null. I'm looking for the best way to account for those null values when creating the DataTable so when I insert this into MSSQL I don't run into errors.
Here is the code I'm using to generate the DataTable:
public DataTable ConvertListToCustomDataTable(List<RootObject> listOfItems)
{
DataTable table = new DataTable();
table.Columns.Add("DateCreated");
table.Columns.Add("DepthCode");
table.Columns.Add("DepthDateCreated");
table.Columns.Add("DepthLevel");
table.Columns.Add("DepthID");
table.Columns.Add("DepthCategoryName");
table.Columns.Add("DepthName");
table.Columns.Add("DepthCategoryDateUpdated");
table.Columns.Add("DepthDateUpdated");
table.Columns.Add("Name");
table.Columns.Add("ID");
table.Columns.Add("CategoryCode");
table.Columns.Add("CategoryDateCreated");
table.Columns.Add("CategoryDateUpdated");
table.Columns.Add("CategoryID");
table.Columns.Add("CategoryName");
table.Columns.Add("Code");
foreach (var item in listOfItems)
{
var row = table.NewRow();
row["DateCreated"] = item.DateCreated;
row["DepthCode"] = item.Depth.Code;
row["DepthDateCreated"] = item.Depth.DateCreated;
row["DepthLevel"] = item.Depth.Level;
row["DepthID"] = item.Depth.ID;
row["DepthCategoryName"] = item.Depth.Category.Name;
row["DepthName"] = item.Depth.Name;
row["DepthCategoryDateUpdated"] = item.Depth.Category.DateUpdated;
row["DepthDateUpdated"] = item.Depth.DateUpdated;
row["Name"] = item.Name;
row["ID"] = item.ID;
row["CategoryCode"] = item.Category.Code;
row["CategoryDateCreated"] = item.Category.DateCreated;
row["CategoryDateUpdated"] = item.Category.DateUpdated;
row["CategoryID"] = item.Category.ID;
row["CategoryName"] = item.Category.Name;
row["Code"] = item.Code;
table.Rows.Add(row);
}
return table;
}
You need to set the table columns to accept nulls.
DataColumn datecolumn = new DataColumn("DateCreated");
datecolumn.AllowDBNull = true;
I would put the Column names in an array and loop through them, ie something similar to this.
DataTable table = new DataTable();
string[] column = { "DateCreated", "DepthCode", "DepthDateCreated" };
foreach (var item in column)
{
DataColumn datecolumn = new DataColumn(item);
datecolumn.AllowDBNull = true;
table.Columns.Add(item);
}

Get N number of columns from datatable c#

I have a datatable where I need to take n number of columns. For ex: From the below datatable I need to take first 10 columns alone with data and put it in another datatable.
Code:
DataTable dtRecord = DAL.GetRecords();
I tried this and this doesn't take the required column.
var selectColumns = dtRecord .Columns.Cast<System.Data.DataColumn>().Take(10);
You can also use this
private DataTable GetNColumnsFromDataTable(DataTable tblSource, int outputCols)
{
DataTable columnOutput = tblSource.Copy();
if (outputCols > 0 && outputCols < tblSource.Columns.Count)
{
while (outputCols < columnOutput.Columns.Count)
{
columnOutput.Columns.RemoveAt(columnOutput.Columns.Count - 1);
}
}
return columnOutput;
}
You can do it like this:
var selectColumns = dtRecord.Columns.Cast<DataColumn>().Take(10);
var dtResult = new DataTable();
foreach (var column in selectColumns)
dtResult.Columns.Add(column.ColumnName);
foreach (DataRow row in dtRecord.Rows)
dtResult.Rows.Add(row.ItemArray.Take(10).ToArray());
Perhaps you should create a column of the same type and with the same expression:
dtResult.Columns.Add(column.ColumnName, column.DataType, column.Expression);
To copy from one DataTable to another, you can extract the columns of interest
var moveCols = dtRecord.Columns.Cast<DataColumn>().Take(10).Select(c => c.ColumnName).ToArray();
Then you must create new DataColumns in a new table, then create new DataRows in the new table:
var newTable = new DataTable();
foreach (var c in moveCols)
newTable.Columns.Add(c);
foreach (var r in dtRecord.AsEnumerable())
newTable.Rows.Add(moveCols.Select(c => r[c]).ToArray());
Which you can make an extension method on DataTable:
public static DataTable Slice(this DataTable dt, params string[] colnames) {
var newTable = new DataTable();
foreach (var c in colnames)
newTable.Columns.Add(c, dt.Columns[c].DataType);
foreach (var r in dt.AsEnumerable())
newTable.Rows.Add(colnames.Select(c => r[c]).ToArray());
return newTable;
}
Now you can call
var newTable = dtRecord.Slice(moveCols);
With a nice extension method, you can convert from Dictionarys to a DataTable dynamically:
var newTable = dtRecord.AsEnumerable().Select(r => moveCols.ToDictionary(c => c, c => r[c])).AsDataTable();
I have some for converting ExpandoObject and anonymous objects as well, as well as an extension to convert those to anonymous objects dynamically. Here is the code for Dictionarys to DataTable:
public static DataTable AsDataTable(this IEnumerable<IDictionary<string, object>> rows) {
var dt = new DataTable();
if (rows.Count() > 0) {
foreach (var kv in rows.First())
dt.Columns.Add(kv.Key, kv.Value.GetType());
foreach (var r in rows)
dt.Rows.Add(r.Values.ToArray());
}
return dt;
}
public static DataTable AsDataTable(this IEnumerable<Dictionary<string, object>> rows) => ((IEnumerable<IDictionary<string, object>>)rows).AsDataTable();
Get 10 columns:
var tbl = new System.Data.DataTable();
var cols = tbl.Columns.Cast<System.Data.DataColumn>().Take(10);
// if you wish to get first 10 columns...
If you want to get the data, then you have to loop through the columns to get the data.
var data = cols.SelectMany(x => tbl.Rows.Cast().Take(10).Select(y => y[x]));
of course, this will dump all the data into an ienumerable, if you want to use strong typed object or a list of one dimensional array, believe it's fairly simple, for example:
var data2 = cols.Select(x => tbl.Rows.Cast().Take(10).Select(y => y[x]).ToArray());

How to create a DataTable with a single row and single key-value pair in that row.

For a test I'm trying to write, all I need is a DataTable with 1 row with ["foo"] = 2314 so that I reach the body of the loop
foreach(DataRow row in mockDataTable.Rows)
{
// ...
int val = (int)row["foo"];
// ...
}
inside a method that my test is testing.
However I can't figure out how to do this through the documentation on https://msdn.microsoft.com/en-us/library/system.data.datatable(v=vs.110).aspx
var dt = new DataTable();
dt.Columns.Add("foo", typeof (int));
var row = dt.NewRow();
row["foo"] = 1234;
dt.Rows.Add(row);

Linq in datatable or data set

I have a list<string> and a DataSet. I need to write a Linq query to get the values from dataset or datatable to check if the values are present in List<string>. Please help me in writing the query to get datas from dataset or datatable
i will use foreach after getting the values to check whether the data is present in list<string>
EDIT:
DataSet dsDuplicate = (DataSet) Session["EventDescription"];
DataTable dt = dsDuplicate.Tables[0];
string cellValue = string.Empty;
for (int rowCount = 0; rowCount < gvEventMechanic.Rows.Count; rowCount++)
{
TextBox textBoxId = (TextBox)gvEventMechanic.Rows[rowCount].Cells[2].FindControl("txtId");
lstStringId.Add(textBoxId.Text);
}
List<string> list = ...
DataTable table = ...
var items = new HashSet<string>(list);
var results = from row in table.AsEnumerable()
where items.Contains(row.Field<string>("YourColumnName"))
select row;
foreach (var matchingRow in results)
{
// do whatever
}
Note: If you need the results to be in the form of another DataTable or DataView (such as for databinding), there are methods for that.
var output = results.CopyToDataTable(); // or
var output = results.AsDataView();

How to check if a record is already present in the DataView? C#

I have a DataView which has two columns: ContactID, and Name
How can I check if a particular ContactID is already existing in the DataView?
Have you had a look at DataView.FindRows Method or maybe DataView.Find Method
The DataView has a method called FindRows, this can be used to search for a specific contactID, for example...
var table = new DataTable();
var column = new DataColumn("Id", typeof (int));
table.Columns.Add(column);
table.PrimaryKey = new[] {column}; // Unique Constraint
var row = table.NewRow();
row["Id"] = 100;
table.Rows.Add(row);
row = table.NewRow();
row["Id"] = 200;
table.Rows.Add(row);
var view = new DataView(table) { ApplyDefaultSort = true };
var rows = view.FindRows(200);
foreach(var r in rows)
{
Console.WriteLine(r["Id"]);
}
Use the Following code to Find the row in the Dataview
//Your original Table Which consist of Data
DataTable dtProducts = new DataTable();
//Add the DataTable to DataView
DataView ProductDataView = new DataView(dtProducts);
ProductDataView.RowFilter = "";
ProductDataView.Sort = "ProdId";
int recordIndex = -1;
//In the Find Row Method pass the Column
//value which you want to find
recordIndex = ProductDataView.Find(1);
if (recordIndex > -1)
{
Console.WriteLine("Row Found");
}

Categories