Linq distinct equivalent - c#

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.

Related

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

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 :)

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();

Removing duplicate rows in database with primary key using Distinct()

I have some duplicate values in my database so I am using Linq to Entity to remove them with the code below. The problem is that there is an autonumber primary key in RosterSummaryData_Subject_Local, which invalidates the line var distinctRows = allRows.Distinct();
So, even if all the rows are the same, distinct won't work because the pk is different. Is there anyway to discredit the pk in the distinct? Or anyway to remove it from the query so it becomes a non issue. Just to note I want the query to return an IQueryable of my entity type so I can use the RemoveRange() method on the enttiy to remove the duplicates.
var allRows = (from subjLocal in customerContext.RosterSummaryData_Subject_Local
select subjLocal);
var distinctRows = allRows.Distinct();
if (allRows.Count() == distinctRows.Count())
{
return;
}
else
{
var rowsToDelete = allRows.Where(a => a != distinctRows);
customerContext.RosterSummaryData_Subject_Local.RemoveRange(rowsToDelete);
}
EDIT
I realized that to properly bring back distinct rows, all I have to do is select all the items except primary key:
var distinctRows = allRows
.Select(a => new {a.fkRosterSetID, a.fkTestInstanceID, a.fkTestTypeID,
a.fkSchoolYearID, a.fkRosterTypeID, a.fkDistrictID,
a.fkSchoolID, a.fkGradeID, a.fkDepartmentID,
a.fkCourseID, a.fkPeriodID, a.fkDemoCommonCodeID,
a.fkDemoCommonCategoryID, a.fkTest_SubjectID})
.Distinct();
The problem is that I cannot fetch the duplicate rows with the code below because the ! operator does not work with anonymous types(the variable distinctRows is an anonymous type because I didn't select all the columns):
var rowsToDelete = allRows.Where(a => a != distinctRows);
Any help?
you can try this:
var allRows = (from subjLocal in customerContext.RosterSummaryData_Subject_Local
select subjLocal).ToList();
var distinctRows = allRows.Distinct().ToList();
Since you will be dealing with list objects, then in your original else statement you can do this:
else
{
var rowsToDelete = allRows.Where(a => !distinctRows.Contains(a));
customerContext.RosterSummaryData_Subject_Local.RemoveRange(rowsToDelete);
}
To handle your issue with Distinct() and the autonumberID in the database, there are two solutions I can think of.
One is you can bring in the MoreLinq library, it's a Nuget package. then you can use the MoreLinq method DistinctBy():
allRows.DistinctBy(a => a.SomePropertyToUse);
Or the other route would be to use an IEqualityComparer with the regular .Distinct() Linq Method. You can check out this SO question for more info on using an IEqualityComparer in the .Distinct() method. using distinct with IEqualityComparer
maybe you need to check for each one of the fields in your customerContext.RosterSummaryData_Subject_Local to see which one is different

Entity Framework select distinct name

How can I do this SQL query with Entity Framework?
SELECT DISTINCT NAME FROM TestAddresses
Using lambda expression..
var result = EFContext.TestAddresses.Select(m => m.Name).Distinct();
Another variation using where,
var result = EFContext.TestAddresses
.Where(a => a.age > 10)//if you have any condition
.Select(m => m.name).Distinct();
Another variation using sql like syntax
var result = (from recordset
in EFContext.TestAddresses
.where(a => a.city = 'NY')//if you have any condition
.select new
{
recordset.name
}).Distinct();
Try this:
var results = (from ta in context.TestAddresses
select ta.Name).Distinct();
This will give you an IEnumerable<string> - you can call .ToList() on it to get a List<string>.
The way that #alliswell showed is completely valid, and there's another way! :)
var result = EFContext.TestAddresses
.GroupBy(ta => ta.Name)
.Select(ta => ta.Key);
I hope it'll be useful to someone.
DBContext.TestAddresses.Select(m => m.NAME).Distinct();
if you have multiple column do like this:
DBContext.TestAddresses.Select(m => new {m.NAME, m.ID}).Distinct();
In this example no duplicate CategoryId and no CategoryName i hope this will help you
Entity-Framework Select Distinct Name:
Suppose if you are using Views in which you are using multiple tables and you want to apply distinct in that case first you have to store value in variable & then you can apply Distinct on that variable like this one....
public List<Item_Img_Sal_VIEW> GetItemDescription(int ItemNo)
{
var Result= db.Item_Img_Sal_VIEW.Where(p => p.ItemID == ItemNo).ToList();
return Result.Distinct().ToList();
}
Or you can try this Simple Example
Public Function GetUniqueLocation() As List(Of Integer)
Return db.LoginUsers.Select(Function(p) p.LocID).Distinct().ToList()
End Function
use Select().Distinct()
for example
DBContext db = new DBContext();
var data= db.User_Food_UserIntakeFood .Select( ).Distinct();
In order to avoid ORDER BY items must appear in the select list if SELECT DISTINCT error, the best should be
var results = (
from ta in DBContext.TestAddresses
select ta.Name
)
.Distinct()
.OrderBy( x => 1);
Entity-Framework Select Distinct Name:
Suppose if you are want every first data of particular column of each group ;
var data = objDb.TableName.GroupBy(dt => dt.ColumnName).Select(dt => new { dt.Key }).ToList();
foreach (var item in data)
{
var data2= objDb.TableName.Where(dt=>dt.ColumnName==item.Key).Select(dt=>new {dt.SelectYourColumn}).Distinct().FirstOrDefault();
//Eg.
{
ListBox1.Items.Add(data2.ColumnName);
}
}

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