Question

var dic = context.Treasure.Include("TreasureShare")
  .Where(t => t.TreasureShare.IsShared && t.TreasureShare.EvaluationContent.Contains(keyword))
  .ToDictionary(t => t.ProductUrl, t => t.ProductId, EqualityComparer<string>.Default);

I got an error:

An item with the same key has already been added.

So why the equalitycomparer not work, and how to use a equalitycomparer to get different records while querying to database.

Updated:

I know IEqualityComparer can only be executed locally, but I didn't get an error like:

LINQ to Entities does not recognize the method 'System.Linq.IQueryable1[Panli.Service.Share.DataAccess.DbData.Treasure] Distinct[Treasure](System.Linq.IQueryable1[Panli.Service.Share.DataAccess.DbData.Treasure], System.Collections.Generic.IEqualityComparer`1[Panli.Service.Share.DataAccess.DbData.Treasure])' method, and this method cannot be translated into a store expression.

except I change the codes to below:

dic = context.Treasure.Include("TreasureShare")
  .Where(t => t.TreasureShare.IsShared && t.TreasureShare.EvaluationContent.Contains(theme))
  .Distinct(new TreasureEqualityComparer()).ToDictionary(t => t.ProductUrl, t => t.ProductId);

This is my TreasureEqualityComparer:

public class TreasureEqualityComparer : EqualityComparer<Treasure>
{
    public override bool Equals(Treasure x, Treasure y)
    {
        return x.ProductUrl.ToLower() == y.ProductUrl.ToLower();
    }

    public override int GetHashCode(Treasure obj)
    {
        return obj.ProductUrl.ToLower().GetHashCode();
    }
}

So why not throw an exception just like the Distinct() when I use ToDictionary(..) which has an IEqualityComparer param ? Anyone can explain this ?

Was it helpful?

Solution 2

Dictionary key has to be unique. In this case you are using ProductUrl as dictionary key and ProductId as value, unfortunately as the error indicated there are more then one records in Table having same ProductUrl. So you can't use it as a dictionary key.

OTHER TIPS

So why not throw an exception?

The ToDictionary part is executed in memory. This is apparent when you investigate the SQL that is executed: nothing that shows any preparation for a conversion to Dictionary.

The query expression with Distinct on the other hand is translated into SQL as a whole (except it isn't because it fails). EF tries to let the database do the hard work of returning distinct values, but of course a comparer can't be translated into SQL, so this overload of Distinct() is not supported.

As for the duplicate key: apparently there are duplicate URL's (ignoring case). Maybe you should use group by.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top