I have the following code:
public interface IKeyed<TKey>
{
TKey Id { get; }
}
// This is the entity framework generated model. I have added the
// IKeyed<Guid> interface
public partial class Person : IKeyed<Guid>
{
public Guid Id { get; set; }
}
public class Repository<TKey, TEntity> : IKeyedRepository<TKey, TEntity>
where TEntity : class, IKeyed<TKey>
{
private readonly IObjectSet<TEntity> _objectSet;
public Repository(IOjectSet<TEntity> objectSet)
{
_objectSet = objectSet;
}
public TEntity FindBy(TKey id)
{
return _objectSet.FirstOrDefault(x => x.Id.Equals(id));
}
}
[Update]
Here is how I am calling this:
Db2Entities context = new Db2Entities(_connectionString); // This is the EF context
IObjectSet<Person> objectSet = context.CreateObjectSet<Person>();
IKeyedRepository<Guid, Person> repo = new Repository<Guid, Person>(objectSet);
Guid id = Guid.NewGuid();
Person person = repo.FindBy(id); // This throws the exception.
The above code compiles. When the ‘FindBy’ method is executed, I get the following error:
Unable to create a constant value of type ‘Closure type’. Only primitive types (for instance Int32, String and Guid) are supported in this context.
Since the type of my ‘Id’ is a Guid (one of the primitive types supported) it seems like I should be able to massage this into working.
Anyone know if this is possible?
Thanks,
Bob
It doesn’t work this way. You cannot call
Equalsbecause EF doesn’t know how to translate it to SQL. When you pass expression toFirstOrDefaultit must be always only code which can be translated to SQL. It is probably possible to solve your problem with some manual building of expression tree but I can reference other solutions already discussed on Stack Overflow.ObjectContextoffers method namedGetObjectByKeywhich is exactly what you are trying to do. The problem is that it requiresEntityKeyas parameter. Here are two answers which show how to use this method and how to getEntityKey:In your case the code will be less complicated because you know the name of the key property so you generally need only something like this:
The problem here is that you cannot get
entitySetNamefromIObjectSetso you must either pass it to repository constructor or you must passObjectSet.Just in case you will want to use DbContext API (EFv4.1) in the future instead of ObjectContext API it will be much simplified because
DbSetoffersFindmethod: