Alex
Alex

Reputation: 233

How to use Distinct to compare my model class?

This code is working properly with one issue. Issue is below code's Distinct is not working & data duplicates.

Code

public IList<DistrictSupervisorViewModel> GetAssignedDistricts()
{
    IList<DistrictSupervisorViewModel> lsp = idistrictsupervisorrepository
            .GetList(x => x.IsActive == true && x.IsDelete == false)
            .Select(x => new DistrictSupervisorViewModel { DistrictId = x.District.DistrictId, DistrictName = x.District.DistrictName }).Distinct().ToList();
    return lsp;
}

Upvotes: 0

Views: 246

Answers (4)

Chaitanya Gadkari
Chaitanya Gadkari

Reputation: 2787

Take districts by their district Ids

public IList<DistrictSupervisorViewModel> GetAssignedDistricts()
{
    IList<DistrictSupervisorViewModel> lsp = idistrictsupervisorrepository
            .GetList(x => x.IsActive == true && x.IsDelete == false)
            .Select(x => new DistrictSupervisorViewModel { DistrictId = x.District.DistrictId, DistrictName = x.District.DistrictName }).DistinctBy(p => p.DistrictId).ToList();
    return lsp;
}  

Upvotes: 0

Radin Gospodinov
Radin Gospodinov

Reputation: 2323

DistrictSupervisorViewModel must override Equals and GetHashCode, also you should implement IEquatable. See the guideline here: https://msdn.microsoft.com/en-gb/library/ms173147(v=vs.80).aspx. The second option is to create IEqualityComparer and pass it as parameter of Distinct method. There is generic implementation here: http://www.codeproject.com/Articles/94272/A-Generic-IEqualityComparer-for-Linq-Distinct

Upvotes: 1

Brondahl
Brondahl

Reputation: 8557

As @Stephen and @andrepena has said, the issue is that Distinct is taking object reference equality and thus concluding that all the entries are distinct.

One solution is to define a different Equality model by implementing IEquality, as above, but that makes the assumption that it is sensible to define Equality between these ViewModels as being identically equivalent to their ID's equality. Not just in this query but everywhere! If that is the case, then defining IEquality is exactly what you should do - it will solve this problem every time you use the class for this sort of thing.

But if that's not the case, or you don't want to use IEquatable, then another option is to make the Distinct-ness filter look at the Id directly. This can't be done with vanilla Linq, but the ever-invaluable MoreLinq package has Distinctby built into it:

var myEnumerableOfObjectsWithIds;
var output = myEnumerableOfObjectsWithIds.DistinctBy(obj => obj.Id)

output will hold the set of objects that are distinct when considering the appropriate Equality on the IDs. If they are value-types, then it will use basic value equality, if they are ID objects it will use reference type equality (unless you've implement IEquatable ... and thus we fall into a loop :) )

Upvotes: 0

Andre Pena
Andre Pena

Reputation: 59336

As @Stephen said, make sure your DistrictSupervisorViewModel model class implements IEquatable.

Change the comparing logic to meet your needs.

public class DistrictSupervisorViewModel  : IEquatable<DistrictSupervisorViewModel>
{
    public bool Equals(DistrictSupervisorViewModel other)
    {
        // Do your own comparing here
        return this.DistrictId == other.DistrictId;
    }
}

Upvotes: 0

Related Questions