Hasan Ünal
Hasan Ünal

Reputation: 1

Linq expression does not allow Generic Property Type

Error: Unable to create a constant value of type 'System.Object'. Only primitive types or enumeration types are supported in this context.

Ok here is the deal, I have a Generic Base Entity as shown below:

public abstract class Entity<Tkey> : IEntity<Tkey>
    where Tkey:IComparable
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public abstract Tkey Id { get; set;}

}

I prefer this, because you know, some table's Identity column type is Guid, some int and some long.

So, in my Generic repository I have some method like this one:

public class FRepository<TEntity,Tkey>:IDisposable where TEntity : Entity<Tkey>, new()
    where Tkey:IComparable

{

    public TEntity Find(Tkey id)
    {
        return this.GetAll().Where(e=> e.Id.CompareTo(id)==0).FirstOrDefault();
    }
}

GetAll() method returns IQueryable<TEntity>.

But when I use Linq to find specific entity, it throws exception as I write begining of this post.

Note: The entity which I am trying to find has Id with int type, so it is a primitive type...

Note-1: I can't able to use '==' operator with generic type TKey. I get compilation error.

Note-2: I also tried this Where(e=>e.Id.GetHashCode()==id.GetHashCode()). This throws another error(run-time).

LINQ to Entities does not recognize the method 'Int32 GetHashCode()' method, and this method cannot be translated into a store expression.

Upvotes: 0

Views: 495

Answers (1)

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

Reputation: 64943

Instead of attempting to solve the original issue, as some others users have already commented out that not all valid expressions are translatable to SQL under the hoods, I'll try to give you some advises...

Summary:

  • You want Id to implement IEquatable<TId>, not IComparable<TId>. Thus, you'll be able to write typed equalities like this: id.Equals(id2). BTW EF can't handle IEquatable<T>.Equals either (see Is it possible to use IComparable to compare entities in Entity Framework?). Anyway, you're not going to go this route anymore but the advise is still valid, you want IEquatable<T>, not a comparison. See the next point to know why.
  • You don't want a GetAll method on your repositories to later look for an entity by Id. Entity Framework already has IDbSet<T>.Find method for this exact use case.

Also, I would encourage you to read some answer I composed in 2011 (a long time ago) against GetAll in repositories: Repository design pattern. In addition, I've documented the repository pattern here where I explain the thing against GetAll too.

Upvotes: 2

Related Questions