Joined Linq query to DataTable and result to DataView - c#

I have two DataTables , Items and its Groups. I have a linq query to get item Name and its Group Name by joining the 2 tables.
EnumerableRowCollection<DataRow> dvquery = (from item in Items.AsEnumerable()
join grp in groups.AsEnumerable()
on item.Field<byte>("Group_ID") equals grp.Field<byte>("ID")
into item_grp_join
from itemgrp in item_grp_join
select new
{
ItemName = (string)led.Field<string>("Name"),
GName = (string)itemgrp.Field<string>("Name"),
});
DataView dv = dvquery.AsDataView();
However I am getting compile time error as
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'System.Data.EnumerableRowCollection'. An explicity conversion exists (are you missing a cast?)
How to solve this error? I can easily convert the query result into a list but I need to have a dataview only , so as I can give it as datasource to grid.
Any help appreciated.
Thanks

The problem is that your query returns an IEnumerable<T> of an anonymous type and you can't simply cast that to a EnumerableRowCollection<DataRow>
I'm now sure which type of Grid you are using (e.g. from winforms? WPF? ASP? ASP MVC? etc), however I would expect that you should actually be able to pass it the IEnumerable output of the linq query if you wanted to - e.g.:
var query = (from item in Items.AsEnumerable()
join grp in groups.AsEnumerable()
on item.Field<byte>("Group_ID") equals grp.Field<byte>("ID")
into item_grp_join
from itemgrp in item_grp_join
select new
{
ItemName = (string)led.Field<string>("Name"),
GName = (string)itemgrp.Field<string>("Name"),
});
grid.DataSource = query; // or possible query.ToList() as you suggest in the question!
If you really need to use a DataView type object, then there are blog posts about how to create these, try:
http://www.c-sharpcorner.com/UploadFile/VIMAL.LAKHERA/LINQResultsetToDatatable06242008042629AM/LINQResultsetToDatatable.aspx
http://www.chinhdo.com/20090402/convert-list-to-datatable/
http://wpfguy.blogspot.com/2009/07/how-to-convert-ienumerable-to.html
Note that if you are expecting to use the grid for two-way binding (e.g. for writing changes back to the database), then this is unlikely to "just work" - as your IEnumerable projection isn't tied back to the datasource.

You are returning an list of anonymous objects. It is better to create a DataTable from your query result.
var query = (from item in Items.AsEnumerable() .......
DataTable view = new DataTable();
view.Columns.Add("GroupName");
view.Columns.Add("ItemName");
foreach (var t in dvquery)
{
view.Rows.Add(t.GName, t.ItemName);
}
DataView dv = view.DefaultView;

Related

Why is linq reversing order in group by

I have a linq query which seems to be reversing one column of several in some rows of an earlier query:
var dataSet = from fb in ds.Feedback_Answers
where fb.Feedback_Questions.Feedback_Questionnaires.QuestionnaireID == criteriaType
&& fb.UpdatedDate >= dateFeedbackFrom && fb.UpdatedDate <= dateFeedbackTo
select new
{
fb.Feedback_Questions.Feedback_Questionnaires.QuestionnaireID,
fb.QuestionID,
fb.Feedback_Questions.Text,
fb.Answer,
fb.UpdatedBy
};
Gets the first dataset and is confirmed working.
This is then grouped like this:
var groupedSet = from row in dataSet
group row by row.UpdatedBy
into grp
select new
{
Survey = grp.Key,
QuestionID = grp.Select(i => i.QuestionID),
Question = grp.Select(q => q.Text),
Answer = grp.Select(a => a.Answer)
};
While grouping, the resulting returnset (of type: string, list int, list string, list int) sometimes, but not always, turns the question order back to front, without inverting answer or questionID, which throws it off.
i.e. if the set is questionID 1,2,3 and question A,B,C it sometimes returns 1,2,3 and C,B,A
Can anyone advise why it may be doing this? Why only on the one column? Thanks!
edit: Got it thanks all! In case it helps anyone in future, here is the solution used:
var groupedSet = from row in dataSet
group row by row.UpdatedBy
into grp
select new
{
Survey = grp.Key,
QuestionID = grp.OrderBy(x=>x.QuestionID).Select(i => i.QuestionID),
Question = grp.OrderBy(x=>x.QuestionID).Select(q => q.Text),
Answer = grp.OrderBy(x=>x.QuestionID).Select(a => a.Answer)
};
Reversal of a grouped order is a coincidence: IQueryable<T>'s GroupBy returns groups in no particular order. Unlike in-memory GroupBy, which specifies the order of its groups, queries performed in RDBMS depend on implementation:
The query behavior that occurs as a result of executing an expression tree that represents calling GroupBy<TSource,TKey,TElement>(IQueryable<TSource>, Expression<Func<TSource,TKey>>, Expression<Func<TSource,TElement>>) depends on the implementation of the type of the source parameter.`
If you would like to have your rows in a specific order, you need to add OrderBy to your query to force it.
How I do it and maintain the relative list order, rather than apply an order to the resulting set?
One approach is to apply grouping to your data after bringing it into memory. Apply ToList() to dataSet at the end to bring data into memory. After that, the order of subsequent GrouBy query will be consistent with dataSet. A drawback is that the grouping is no longer done in RDBMS.

Linq query how to select all columns

I have a linq query which is giving me desired output :
var data = (from c in dtskip.AsEnumerable()
select new[] {
c.Field<string>("Suburb"), c.Field<string>("Postcode"), c.Field<string>("State"),c.Field<string>("ID"), c.Field<string>("SEARCHKEY"), c.Field<string>("RATING"), c.Field<string>("DELIVERY")
});
How can i select all the column instead of giving name like c.field<string>("postcode") .My output is the data only from datatable dtskip :
output:
["DARWIN","0800","NT","2","DARWINNT","A","Delivery Area"]
,["ALAWA","0810","NT","5","ALAWANT","A","Delivery Area"],
["BRINKIN","0810","NT","6","BRINKINNT","A","Delivery Area"],
is there any other way i can get the output in dis way from datatable using linq query .
DataRow contains an ItemArray member which returns all the data in that row as an array, the downside is they are all returned as objects but if all your columns are the same type you can cast the ItemArray in line to the desired type (in this case string)
dtskip.Rows.Cast<DataRow>().Select(r => r.ItemArray.Cast<string>());
This will give you an IEnumerable<IEnumerable<string>> to work with.
have you tried
var data = (From c in dtskip
select c).AsEnumerable(); //Not sure about the AsEnumerable :s
Are you looking for something like this?
var data = dtskip.AsEnumerable().
Select(x => new
{
Suburb = x.Field<string>("Suburb"),
Postcode= x.Field<string>("Postcode"),
State= x.Field<string>("State"),
Id= x.Field<string>("ID"),
Searchkey = x.Field<string>("SEARCHKEY"),
Rating = x.Field<string>("RATING"),
Delivery = x.Field<string>("DELIVERY")
});

How to convert to int and then compare in linq query c#

IEnumerable<classB> list = getItems();
//dt is datatable
list = list.Where(x => Convert.ToInt32( !dt.Columns["Id"]) == (x.Id));
I want to only keep the items in the list which match in datatable id column. The rest are removed. I m not doing it right.
The datatable can have: ID - 1,3,4,5,7
The list can have: ID - 1,2,3,4,5,6,7,8,9,10
I want the output list to have: ID - 1,3,4,5,7
Your code won't work because you're comparing a definition of a column to an integer value. That's not a sensible comparison to make.
What you can do is put all of the values from the data table into a collection that can be effectively searched and then get all of the items in the list that are also in that collection:
var ids = new HashSet<int>(dt.AsEnumerable()
.Select(row => row.Field<int>("Id"));
list = list.Where(x => ids.Contains(x.Id));
Try this one
var idList = dt.AsEnumerable().Select(d => (int) d["Id"]).ToList();
list = list.Where(x => idList.Contains(x.Id));
You can't do it like that. Your dt.Columns["Id"] returns the DataColumn and not the value inside that column in a specific datarow. You need to make a join between two linq query, the first one you already have, the other you need to get from the DataTable.
var queryDt = (from dtRow in dt
where !dtRow.IsNull("Id")
select int.Parse(dtRow["Id"])).ToList();
Now the join
var qry = from nonNull in queryDt
join existing in list on nonNull equals list.id

How to convert linq query into a datatable

I know there are quite a few post on this subject but none of them seem to work for me.
I am trying to convert a linq query into an object that is acceptable for my telerik gridview.
What I have:
var allProjectItems = from x in db.DateItems.AsEnumerable()
where
x.Date.ProjectId == projectId
select new
{
ItemDate = (DateTime?)x.Date.ItemDate,
LastName =
((from Users in db.Users
where
Users.UserId == x.Date.AddedByUserId
select new
{
Users.Lastname
}).FirstOrDefault().Lastname),
DateItemId = x.DateItemId,
DateItem1 = x.DateItem1,
DateValue = x.DateValue,
DateId = x.DateId,
DateType = x.DateType
};
I've tried adding .AsEnumerable() onto each table in query but I still am not able to use the query for the gridview or to convert into a datatable with CopyToDataTable method.
Ive also tried to specify requested attributes like x.Field("ProjectId") but Field is not an option.
Can anyone help?
Thanks
Selecting off an anonymous type is going to frustrate you down the road when you actually want to know what object is selected in your gridview.
Just select your DataItem and bind it to your gridview, and set up your Binding on the gridview to show columns for the properties you want to display in the gridview.
//Obviously this is simplified and doesn't include your users stuff, but I think you get the idea.
var allProjectItems = (from x in db.DateItems
where
x.Date.ProjectId == projectId
select x).ToList();
You will have to set up your bindings on your gridview to show the data you want. As for the user business, I'd set up a partial class on the DataItem that will use navigational properties to get the user and return the values you want.

How to select specific column in LINQ?

I have to select specific column from my DataTable using linq
I am using this code
ds.Table[0].AsEnumerable().Where<DataRow>(r=>r.Field<int>("productID")==23).CopyToDataTable();
~
But it is giving me all columns and I need only PRODUCTNAME , DESCRIPTION , PRICE
How I can write this query?
To expand a bit on #lazyberezovsky, you can use an anonymous type projection to get all of the fields you want:
ds.Table[0].AsEnumerable()
.Where<DataRow>(r => r.Field<int>("productID") == 23)
.Select(r => new { ProductName = r.Field<string>("productName"),
Description = r.Field<string>("description"),
Price = r.Field<decimal>("price") });
I don't know what name and type your product name, description, and price fields are, so you will have to substitute those.
Use Select method:
ds.Table[0].AsEnumerable()
.Where<DataRow>(r=>r.Field<int>("productID")==23)
.Select(r => r.Field<int>("productID"));
UPDATE: In case you need to select several columns, you can return anonymous type:
var query = from row in dt.ds.Table[0].AsEnumerable()
where row.Field<int>("productID")==23
select new {
ProductID = x.Field<string>("productID"),
Foo = x.Field<string>("foo")
};
If you need to copy that data to new table, you'll face problem (CopyToDataTable requires collection of DataRow objects). See How to: Implement CopyToDataTable Where the Generic Type T Is Not a DataRow to solve this problem.

Categories

Resources