How to create a LINQ group by query with dynamic columns? - c#

I want to group by a datatable by the columns which are present in a List. Moreover I want to sum a column using group by result.
How to create a dynamic linq query for this?

In case you want to use a dynamic linq query for this, you can use System.Linq.Dynamic.Core.
The code could look like:
var result = context.Posts.GroupBy("BlogId").Select("new(Key, Sum(NumberOfReads) AS TotalReads)");
See also
https://dynamic-linq.net/basic-query-operators#groupby-by-a-single-key-and-do-a-sum

Just group by the identifier you need and then sum the column as below.
var lstYourClass = lstYourClass .GroupBy(x => x.Id).Select(z => new YourClassType
{
Amount= z.Sum(a => a.Amount),
}).ToList();
Hope it helps :)

Related

Linq Distinct not bringing back the correct results

I'm trying to select a distinct values from a DataTable using Linq. The DataTable gets populated from an excel sheet which has dynamic column apart from each excel sheet has a column name SERIAL NUMBER which is mandatory.
I have a DataTable for demo purpose which consist of 4 serial number as:
12345
12345
98765
98765
When I do
var distinctList = dt.AsEnumerable().Select(a => a).Distinct().ToList();
If I do
var distinctList = dt.AsEnumerable().Select(a => a.Field<string>("SERIAL NUMBER").Distinct().ToList();
Then I get the correct results, however but it only contains the one column from dt and not all the other columns
I get all four records instead of 2. Can someone tell me where I'm going wrong please.
The problem is that Distinct method by default uses the default equality comparer, which for DataRow is comparing by reference. To get the desired result, you can use the Distinct overload that allows you to pass IEqualityComparer<T>, and pass DataRowComparer.Default:
The DataRowComparer<TRow> class is used to compare the values of the DataRow objects and does not compare the object references.
var distinctList = dt.AsEnumerable().Distinct(DataRowComparer.Default).ToList();
For more info, see Comparing DataRows (LINQ to DataSet).
So, you want to group them by Serial Number and retrieve the full DataRow? Assuming that after grouping them we want to retrieve the first item:
var distinctList = dt.AsEnumerable().GroupBy(a => a.Field<string>("SERIAL NUMBER"))
.Select(a => a.FirstOrDefault()).Distinct().ToList();
EDIT: As requested
var distinctValues = dt.AsEnumerable().Select(a => a.Field<string>("SERIAL NUMBER")).Distinct().ToList();
var duplicateValues = dt.AsEnumerable().GroupBy(a => a.Field<string>("SERIAL NUMBER")).SelectMany(a => a.Skip(1)).Distinct().ToList();
var duplicatesRemoved = dt.AsEnumerable().Except(duplicateValues);
In ToTable method the first parameter specifies if you want Distinct records, the second specify by which column name we will make distinct.
DataTable returnVals = dt.DefaultView.ToTable(true, "ColumnNameOnWhichYouWantDistinctRecords");
Here there is no need to use linq for this task !
Using Linq a GroupBy would be better suited, by the sounds of it.
var groups = dt.AsEnumerable().GroupBy(a => a.SerialNumber).Select(_ => new {Key = _.Key, Items = _});
This will then contain groupings based on the Serial Number. With each group of items having the same serial number, but other property values different.
Try this:
List<string> distinctValues = (from row in dt.AsEnumerable() select row.Field<string>("SERIAL NUMBER")).Distinct().ToList();
However to me this also works:
List<string> distinctValues = dt.AsEnumerable().Select(row => row.Field<string>("SERIAL NUMBER")).Distinct().ToList();

How do I convert this query into LINQ

How do I convert this query into LINQ?
Here employeeList is a list of employees(model) and idList has a list of ids(int).
Update employeeList
Set employeeList.CaseNumber = '100'
where employeeList.id in idList
It is not possible to create a LINQ-Query that will result in the given UPDATE query.
The only solution is to iterate through the collection of items and set the CaseNumber to 100.
foreach(var item in context.employeeList.Where(i => idList.Contains(i.id))
{
item.CaseNumber = "100";
}
context.SaveChanges();
But this will result in n queries send to the database.
A better solution is to execute the query directly to the database.
context.Database.SqlQuery("UPDATE ... SET ... WHERE");
Another possibility would be to use StoredProcedures which are then mapped to the ORM.
If I understood properly, you only need a LINQ alternative to what you wrote.
If that is the case please try the provided code
employeeList.Where(x => idList.Contains(x.id)).ToList().ForEach(i => i.CaseNumber = 100);

Linq distinct equivalent

How do you use LINQ (C#) to select the value in a particular column for a particular row in a datatable. The equivalent SQL would be:
select Distinct page_no from pagetable;
Thanks in advance.
var result = YourContext.pagetable.Select(x => x.page_no).Distinct()
var items = source.Select(x => x.Property).Distinct();
or for DataTable:
var items = dt.AsEnumerable().Select(x => x.Field<string>("columnName")).Distinct();
You can use a combination of Select and Distinct:
var distinctThings = things.Select(i => i.Property).Distinct();
There is also the MoreLINQ project, which adds some of the methods that should have been a part of LINQ to Objects in the first place.

Get an array of IDs(values) from a datatable

I have a datable with 50 rows and has an ID Column. I am trying to get an array that holds only the IDs like:
string [] IDs = (from row in DataTable.Rows
select row["ID"].toString()).ToArray();
Is there a way to do this. I always get the error "Could not find he implementation of the query...."
Use the DataTableExtensions.AsEnumerable method by adding a reference to System.Data.DataSetExtensions and a using System.Data; Then you should be able to use the following query:
var query = from row in datatable.AsEnumerable()
select row["ID"].ToString();
string[] ids = query.ToArray();
If you really need an array you can use the last line above or enclose the query in parentheses and call ToArray() as you did originally. I'm generally not a fan of the latter approach.
In fluent syntax it would be:
string[] ids = datatable.AsEnumerable()
.Select(row => row["ID"].ToString())
.ToArray();
is there is anyway you can select a list data table into a customer object array. Assuming all the columns are going to be same.

Mixing LINQ to SQL with properties of objects in a generic list

I am trying to accomplish something like this query:
var query = from a in DatabaseTable
where listOfObjects.Any(x => x.Id == a.Id)
select a;
Basically, I want to filter the results where a.Id equals a property of one of the objects in the generic list "listOfObjects". I'm getting the error "Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator."
Any ideas on how to filter this in an easily readable way using "contains" or another method?
Thanks in advance.
Just project your local list into a list of the specific items you need to filter on:
var listOfIds = listOfObjects.Select(o => o.Id);
var query =
from a in DatabaseTable
where listOfIds.Contains(a.Id)
select a;
var listOfIds = listOfObjects.Select(x => x.Id).ToList();
var query = from a in DatabaseTable
where listOfIds.Contains(a.Id)
select a;

Categories

Resources