how convert DataTable to List<String> in C# - c#

I am using C# Linq now I am converting DataTable to List
and I am getting stuck...
give me right direction thanks..
private void treeview1_Expanded(object sender, RoutedEventArgs e)
{
coa = new List<string>();
//coa = (List<string>)Application.Current.Properties["CoAFull"];
HMDAC.Hmclientdb db = new HMDAC.Hmclientdb(HMBL.Helper.GetDBPath());
var data = (from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new { a.Asset, a.Category, a.CoAName, a.Hide, a.Recurring, a.TaxApplicable });
DataTable dtTable = new DataTable();
dtTable.Columns.Add("Asset", typeof(bool));
dtTable.Columns.Add("Category", typeof(string));
dtTable.Columns.Add("CoAName", typeof(string));
dtTable.Columns.Add("Hide", typeof(bool));
dtTable.Columns.Add("Recurring", typeof(bool));
dtTable.Columns.Add("TaxApplicable", typeof(bool));
if (data.Count() > 0)
{
foreach (var item in data)
{
DataRow dr = dtTable.NewRow();
dr["Asset"] = item.Asset;
dr["Category"] = item.Category;
dr["CoAName"] = item.CoAName;
dr["Hide"] = item.Hide;
dr["Recurring"] = item.Recurring;
dr["TaxApplicable"] = item.TaxApplicable;
dtTable.Rows.Add(dr);
}
}
coa = dtTable;
}

It seems that you already have a strongly typed list. Why converting this to a weakly typed DataTable and then back to a list?????
var data =
from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new
{
a.Asset,
a.Category,
a.CoAName,
a.Hide,
a.Recurring,
a.TaxApplicable
};
var list = data.ToList();
If you want to be able to use this list outside the scope of the method, define a type that will hold the different properties and in your select statement use this type instead of the anonymous type like:
var data =
from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new MyType
{
Asset = a.Asset,
Category = a.Category,
CoAName = a.CoAName,
Hide = a.Hide,
Recurring = a.Recurring,
TaxApplicable = a.TaxApplicable
};
List<MyType> list = data.ToList();

You don't need the data table according to the code you have displayed:
var data = (from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new { a.Asset.ToString() + a.Category.ToString()
+ a.CoAName.ToString()... }).ToList();

If you really want to convert your datatable to a 1D list, you can do it like this
foreach (DataRow row in dtTable.Rows)
{
foreach (DataColumn col in dtTable.Columns)
{
coa.Add(row[col]);
}
}

As you are using Select new in you linq query It will find object. What you can do is
var data = (from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new { a.Asset, a.Category, a.CoAName, a.Hide, a.Recurring, a.TaxApplicable });
this is your query and you select multiple columns in your query. So you can't convert your data to a single List of string. What you can do is concatenate all the column in a single string and then add them in a list of string.
To do that modify your query like 'CK' said
var data = (from a in db.CoA
where a.ParentId == 0 && a.Asset == true
select new { a.Asset.ToString() + a.Category.ToString()
+ a.CoAName.ToString()... }).ToList();
And then do
List<string> name = new List<string>(data.ToList());

Related

Date selection comparison with Date_Time data column using Linq query in ASP.NET Gridview

I need my Linq query to compare Date_Time (has only date in data not date_time, datatype - nvarchar) column with date selection of Date1.Value (string) but without showing any error my Gridview doesn't get populated. If I remove the Date_Time where condition, the page runs well. I would be really thankful if someone could help me out with this.
Regards,
Tejas
private void populateData()
{
// here code for populate data
using (TrialEntities13 dc = new TrialEntities13())
{
var v = (from p in dc.Vehicle_Andon
where (p.Line_Name == DropDownList1.SelectedValue
&& p.Loss_Type == 9 && p.Date_Time == Date1.Value)
join s in dc.LOSS_TYPE_MASTER on p.Loss_Description equals s.Loss_Description
select new
{
p,
s.Loss_Description,
});
List<Vehicle_Andon> allP = new List<Vehicle_Andon>();
foreach (var i in v)
{
Vehicle_Andon p = new Vehicle_Andon();
p = i.p;
p.Loss_Description = i.Loss_Description;
allP.Add(p);
}
GridView1.DataSource = allP;
GridView1.DataBind();
}
}

c# linq create dynamic query with

I have 5 Dropdown lists which are filled with the columns of my dataset.
That works well.
var query = ds.Tables["Input"].AsEnumerable().Select
(a => new
{ID = a.Field<string>("ID"),
Element1 = a.Field<string>(comboBoxElement1.SelectedItem.ToString()),
Element2 = a.Field<string>(comboBoxElement2.SelectedItem.ToString()),
Element3 = a.Field<string>(comboBoxElement3.SelectedItem.ToString()),
Element4 = a.Field<string>(comboBoxElement4.SelectedItem.ToString()),
Element5 = a.Field<string>(comboBoxElement5.SelectedItem.ToString())});
But that only works if all ComboBoxes are not empty.
How can I build the query with only 2 selected Boxes dynamically?
I tried it with a StingBuilder and if (comboBoxName.SelectedIndex >= 0) statements, but I'm wondering if there is another method to do that within LINQ.
Why not add a where clause asking for only selectedIndex != 0
like this (in a WinForm):
result = Controls.OfType<ComboBox>().Where(cb => cb.SelectedIndex != -1).Aggregate(result, (current, cb) => current + (cb.SelectedItem + ","));
Have you try this:
var query = ds.Tables["Input"].AsEnumerable().Where(cb => cb.SelectedIndex != -1).Select
(a => new
{ID = a.Field<string>("ID"),
Element1 = a.Field<string>(comboBoxElement1.SelectedItem.ToString()),
Element2 = a.Field<string>(comboBoxElement2.SelectedItem.ToString()),
Element3 = a.Field<string>(comboBoxElement3.SelectedItem.ToString()),
Element4 = a.Field<string>(comboBoxElement4.SelectedItem.ToString()),
Element5 = a.Field<string>(comboBoxElement5.SelectedItem.ToString())});
I found a easy solution.
Create a List from the (not empty) ComboBoxes:
List<string> myCollection = new List<string>();
if (comboBoxElement1.SelectedIndex >= 0)
{
myCollection.Add(comboBoxElement1.SelectedItem.ToString());
}
if (comboBoxElement2.SelectedIndex >= 0)
{
myCollection.Add(comboBoxElement2.SelectedItem.ToString());
}
Create a DataView from the InputTable:
DataView dv = new DataView(dtInput);
Write to the selected DataColumns from comboBoxes to the ouputTable:
dtOutput = dv.ToTable(true, myCollection.ToArray());
You can refactor the above by creating a method such as:
public AddSelected(IList list, params ComboBox[] comboBoxes)
{
foreach (var comboBox in comboBoxes)
{
if (comboBox.SelectedIndex >= 0)
{
list.Add(comboBox.SelectedItem.ToString());
}
}
}
Then calling with code such as:
AddSelected(myCollection, comboBoxElement1, comboBoxElement2 /* , ... */ );

Gridview table data manage in different view add sub heads

I want to manage the data of gridview in different format like add sub heads
code of this data :
var data = (from r in data
join texp in totalexplist on r.SancPropId equals texp.AllSanchAmtId into list2
from l2 in list2.DefaultIfEmpty()
select new
{
Id = r.Id,
FYear = r.FYear,
SancPropId = r.SancPropId,
ExpSubHeadId = r.ExpSubHeadId,
ExpSubHeadName = r.ExpSubHeadName,
ProposedAmount = r.ProposedAmount,
SanctionedAmount = r.SanctionedAmount,
MonthYear = l2 == null ? "" : l2.MnthYear,
Expenditure = l2 == null ? 0 : l2.Exp,
}).ToList();
grd.DataSource = data;
grd.DataBind();
But i want to show this data in below given form
i have try this code but stuck in add to subheads
var monthwise = (from t in data
group t by new { t.MonthYear}
into grp
select new
{
grp.Key.MonthYear,
Data = grp.ToList()
}).ToList();
var allColumns = monthwise.SelectMany(d => d.Data.Select(s => s.ExpSubHeadName)).Distinct().ToList();
var datatable = new DataTable();
datatable.Columns.Add(new DataColumn("Month"));
allColumns.ForEach(c => datatable.Columns.Add(new DataColumn(c)));
Is anyone know how can i manage grid in this form ?

Use linq to find DataTable(Name) in a DataSet using unique list of Column Names

I got roped into some old code, that uses loose (untyped) datasets all over the place.
I'm trying to write a helper method to find the DataTable.Name using the names of some columns.....(because the original code has checks for "sometimes we have 2 datatables in a dataset, sometimes 3, sometimes 4)..and its hard to know the order. Basically, the TSQL Select statements conditionally run. (Gaaaaaaaaaaaaaahhh).
Anyway. I wrote the below, and if I give it 2 column names, its matching on "any" columnname, not "all column names".
Its probably my linq skillz (again), and probably a simple fix.
But I've tried to get the syntax sugar down..below is one of the things I wrote, that compiles.
private static void DataTableFindStuff()
{
DataSet ds = new DataSet();
DataTable dt1 = new DataTable("TableOne");
dt1.Columns.Add("Table1Column11");
dt1.Columns.Add("Name");
dt1.Columns.Add("Age");
dt1.Columns.Add("Height");
DataRow row1a = dt1.NewRow();
row1a["Table1Column11"] = "Table1Column11_ValueA";
row1a["Name"] = "Table1_Name_NameA";
row1a["Age"] = "AgeA";
row1a["Height"] = "HeightA";
dt1.Rows.Add(row1a);
DataRow row1b = dt1.NewRow();
row1b["Table1Column11"] = "Table1Column11_ValueB";
row1b["Name"] = "Table1_Name_NameB";
row1b["Age"] = "AgeB";
row1b["Height"] = "HeightB";
dt1.Rows.Add(row1b);
ds.Tables.Add(dt1);
DataTable dt2 = new DataTable("TableTwo");
dt2.Columns.Add("Table2Column21");
dt2.Columns.Add("Name");
dt2.Columns.Add("BirthCity");
dt2.Columns.Add("BirthState");
DataRow row2a = dt2.NewRow();
row2a["Table2Column21"] = "Table2Column1_ValueG";
row2a["Name"] = "Table2_Name_NameG";
row2a["BirthCity"] = "BirthCityA";
row2a["BirthState"] = "BirthStateA";
dt2.Rows.Add(row2a);
DataRow row2b = dt2.NewRow();
row2b["Table2Column21"] = "Table2Column1_ValueH";
row2b["Name"] = "Table2_Name_NameH";
row2b["BirthCity"] = "BirthCityB";
row2b["BirthState"] = "BirthStateB";
dt2.Rows.Add(row2b);
ds.Tables.Add(dt2);
DataTable dt3 = new DataTable("TableThree");
dt3.Columns.Add("Table3Column31");
dt3.Columns.Add("Name");
dt3.Columns.Add("Price");
dt3.Columns.Add("QuantityOnHand");
DataRow row3a = dt3.NewRow();
row3a["Table3Column31"] = "Table3Column31_ValueM";
row3a["Name"] = "Table3_Name_Name00M";
row3a["Price"] = "PriceA";
row3a["QuantityOnHand"] = "QuantityOnHandA";
dt3.Rows.Add(row3a);
DataRow row3b = dt3.NewRow();
row3b["Table3Column31"] = "Table3Column31_ValueN";
row3b["Name"] = "Table3_Name_Name00N";
row3b["Price"] = "PriceB";
row3b["QuantityOnHand"] = "QuantityOnHandB";
dt3.Rows.Add(row3b);
ds.Tables.Add(dt3);
string foundDataTable1Name = FindDataTableName(ds, new List<string> { "Table1Column11", "Name" });
/* foundDataTable1Name should be 'TableOne' */
string foundDataTable2Name = FindDataTableName(ds, new List<string> { "Table2Column21", "Name" });
/* foundDataTable1Name should be 'TableTwo' */
string foundDataTable3Name = FindDataTableName(ds, new List<string> { "Table3Column31", "Name" });
/* foundDataTable1Name should be 'TableThree' */
string foundDataTableThrowsExceptionName = FindDataTableName(ds, new List<string> { "Name" });
/* show throw exception as 'Name' is in multiple (distinct) tables */
}
public static string FindDataTableName(DataSet ds, List<string> columnNames)
{
string returnValue = string.Empty;
DataTable foundDataTable = FindDataTable(ds, columnNames);
if (null != foundDataTable)
{
returnValue = foundDataTable.TableName;
}
return returnValue;
}
public static DataTable FindDataTable(DataSet ds, List<string> columnNames)
{
DataTable returnItem = null;
if (null == ds || null == columnNames)
{
return null;
}
List<DataTable> tables =
ds.Tables
.Cast<DataTable>()
.SelectMany
(t => t.Columns.Cast<DataColumn>()
.Where(c => columnNames.Contains(c.ColumnName))
)
.Select(c => c.Table).Distinct().ToList();
if (null != tables)
{
if (tables.Count <= 1)
{
returnItem = tables.FirstOrDefault();
}
else
{
throw new IndexOutOfRangeException(string.Format("FindDataTable found more than one matching Table based on the input column names. ({0})", String.Join(", ", columnNames.ToArray())));
}
}
return returnItem;
}
I tried this too (to no avail) (always has 0 matches)
List<DataTable> tables =
ds.Tables
.Cast<DataTable>()
.Where
(t => t.Columns.Cast<DataColumn>()
.All(c => columnNames.Contains(c.ColumnName))
)
.Distinct().ToList();
To me sounds like you're trying to see if columnNames passed to the method are contained within Column's name collection of Table. If that's the case, this should do the work.
List<DataTable> tables =
ds.Tables
.Cast<DataTable>()
.Where(dt => !columnNames.Except(dt.Columns.Select(c => c.Name)).Any())
.ToList();
(Below is an append by the asker of the question)
Well, I had to tweak it to make it compile, but you got me there..
Thanks.
Final Answer:
List<DataTable> tables =
ds.Tables.Cast<DataTable>()
.Where
(dt => !columnNames.Except(dt.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName))
.Any()
)
.ToList();
Final Answer (which is not case sensitive):
List<DataTable> tables =
ds.Tables.Cast<DataTable>()
.Where
(dt => !columnNames.Except(dt.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName), StringComparer.OrdinalIgnoreCase)
.Any()
)
.ToList();

take out foreach using linq

Is there a way to take out the foreach in the following code in linq yet produce the same output?
DropDownList ddl = new DropDownList();
foreach (DataRow row in ds.Tables[0].Rows)
{
if ((byte)row["ListTypeID"] == 0)
{
item = new ListItem(row["ListText"].ToString(), string.Format("{0}:{1}", row["ListTypeID"].ToString(), row["ListID"].ToString()));
ddl.Items.Add(item);
}
else
{
item = new ListItem(row["ListText"].ToString(), string.Format("{0}", row["ListID"].ToString()));
ddl.Items.Add(item);
}
}
Instead of cramming all into a one-line lambda, I prefer readability over saving line space:
ddl.Items.AddRange(ds.Tables[0].Rows.Select( row =>
{
var listText = row["ListText"];
var listTypeId = (byte)row["ListTypeID"];
var listId = row["ListID"];
var format = listTypeId == 0 ? "{0}:{1}" : "{1}";
var itemText = String.Format(format, listTypeID, listId);
return new ListItem(listText, itemText);
}
));
ddl.Items.AddRange(ds.Tables[0].Rows.Select( row =>
(byte)row["ListTypeID"] == 0
? new ListItem(row["ListText"].ToString(), string.Format("{0}:{1}", row["ListTypeID"].ToString(), row["ListID"].ToString()))
: new ListItem(row["ListText"].ToString(), string.Format("{0}", row["ListID"].ToString()))
));
a bit of cleaning
ddl.Items.AddRange(ds.Tables[0].Rows.Select( row =>
(byte)row["ListTypeID"] == 0
? new ListItem(row["ListText"].ToString(), string.Format("{0}:{1}", row["ListTypeID"], row["ListID"]))
: new ListItem(row["ListText"].ToString(), string.Format("{0}", row["ListID"]))
));
leave foreach :)
After a bit of reordering you can achieve the following - adding the items excluded.
var items = ds.Tables[0].Rows.Select(row =>
new ListItem(row["ListText"].ToString(),
String.Format(
(Byte)row["ListTypeID"] == 0 ? "{0}:{1}" : "{1}",
row["ListTypeID"], row["ListID"])));
You can use something like this
var Items= (from DataRow dr in ds.Tables[0].AsEnumerable()
select new {
Text=dr.Field<string>("ListText"),
Value =dr.Field<byte>("ListTypeID") == 0?string.Format("{0}:{1}", dr.Field<string>("ListTypeID"), dr.Field<string>("ListID")):string.Format("{0}", dr.Field<string>("ListID"))
}).ToList();
now you can use Items as data-source for the dropdown.

Categories

Resources