3

When I call DbSet.FirstOrDefault() by passing a predicate that compares generic type TId, I get the following exception:

unable to create a constant value of type 'system.object'. only primitive types or enumeration types are supported in this context.

Interface for type being queried:

interface IEntity<TId>
{
    TId id { get; set; }
}

The exception is thrown here:

public virtual TEntity Get<TEntity, TId>(TId id) where TEntity : class, IEntity<TId>
{
    return dbContext.Set<TEntity>().FirstOrDefault(e => e.Id.Equals(id));
}

The function will only work if TId is constrained as struct. How can I include string as supported type? If it's not possible, is it possible to accomplish the task a different way?

2 Answers 2

2

This will work for strings too:

public virtual TEntity Get<TEntity, TId>(TId id) 
    where TEntity : class, IEntity<TId>
    where TId: IEquatable<TId>
{
    return dbContext.Set<TEntity>().FirstOrDefault(e => e.Id.Equals(id));
}
Sign up to request clarification or add additional context in comments.

3 Comments

How can i extend it to work for arrays of these primitives too? Ex: int[] and string[]. Thanks.
I don't think you can. Equality for sets (RDBMSs have no concept of arrays) is too broad and there is no direct ==-like support for it in SQL. Consider for example [1,2] and [2,1]. Are they equal to you? Is ordering important? What about [null, 1] and [null,1]? Do you care about ternary logic here or not, etc.
I'm working with MS Sql which has Binary[] type. It gets converted to System.Byte[].
2

You can simply use Find method:

public virtual TEntity Get<TEntity, TId>(TId id) where TEntity : class, IEntity<TId>
{
    return dbContext.Set<TEntity>().Find(id);
}

3 Comments

I tried that and it works, but it fails for cases where the primary key is a composite key.
It is strange, how did you try it? dbContext.Set<TEntity>().Find(id1, id2);?
Just as you mentioned in your post. It's just that, using Find(), you can't choose to use just one of the keys.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.