I think there is an easy way around it but it is a hack. Let me stress it again - it really is a hack. You can try this:
Repository.Get<TEntity, TKey>(e => (object)e.Id == (object)EntityId);
The code above in general should not work. In the CLR world the values would be boxed and will be compared by references. Even if the boxed values were the same the references would be different and therfore the result will be false. However EF queries are not executed by the CLR but translated to SQL. As a result the query will be translated to something like: WHERE Id = {EntityId}
which is what you need. Again, using this requires understanding how and why this stuff works and is probably a bit risky. However since there is a hack there should be a cleaner solution. In fact the clean (and not easy solution here) is to build the above expression manually. Here is an example (Sorry I am not using exactly your entities):
private static TEntity GetEntity<TEntity, TKey>(Expression<Func<TEntity, TKey>> property, TKey keyValue)
where TKey : struct
where TEntity : BaseEntity<TKey>
{
using (var ctx = new Context2())
{
var query = Filter(ctx.Set<TEntity>(), property, keyValue);
return query.First();
}
}
private static IQueryable<TEntity> Filter<TEntity, TProperty>(IQueryable<TEntity> dbSet,
Expression<Func<TEntity, TProperty>> property,
TProperty value)
where TProperty : struct
{
var memberExpression = property.Body as MemberExpression;
if (memberExpression == null || !(memberExpression.Member is PropertyInfo))
{
throw new ArgumentException("Property expected", "property");
}
Expression left = property.Body;
Expression right = Expression.Constant(value, typeof (TProperty));
Expression searchExpression = Expression.Equal(left, right);
var lambda = Expression.Lambda<Func<TEntity, bool>>(Expression.Equal(left, right),
new ParameterExpression[] {property.Parameters.Single()});
return dbSet.Where(lambda);
}
Note that in the Filter method I build a filter expression that I can compose on. In this example the effective query looks something like this DbSet().Where(e => e.Id == idValue).First() (looks similar to the hack above) but you can use other linq operators on top of this query (including invoking Filter method on the result of the Filter method to filter by multiple criteria)
I defined the entities and the context as follows:
public class BaseEntity<TKey> where TKey : struct
{
public TKey Id { get; set; }
}
public class EntityWithIntKey : BaseEntity<int>
{
public string Name { get; set; }
}
public class EntityWithGuidKey : BaseEntity<Guid>
{
public string Name { get; set; }
}
public class Context2 : DbContext
{
public DbSet<EntityWithIntKey> EntitiesWithIntKey { get; set; }
public DbSet<EntityWithGuidKey> EntitiesWithGuidKey { get; set; }
}
You invoke the GetEntity method like this: var e2 = GetEntity(e => e.Id, guidKey);
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…