それを回避する簡単な方法があると思いますが、それはハックです。もう一度強調しておきますが、これは本当にハックです。あなたはこれを試すことができます:
Repository.Get<TEntity, TKey>(e => (object)e.Id == (object)EntityId);
上記のコードは一般的には機能しないはずです。CLRの世界では、値はボックス化され、参照によって比較されます。ボックス化された値が同じであっても、参照は異なるため、結果はfalseになります。ただし、EFクエリはCLRによって実行されませんが、SQLに変換されます。その結果、クエリは次のように変換されますWHERE Id = {EntityId}
。これが必要なものです。繰り返しますが、これを使用するには、このようなものがどのように、そしてなぜ機能するのかを理解する必要があり、おそらく少し危険です。ただし、ハックがあるため、よりクリーンなソリューションが必要です。実際、クリーンな(そしてここでは簡単な解決策ではありません)のは、上記の式を手動で作成することです。次に例を示します(申し訳ありませんが、お客様のエンティティを正確に使用していません)。
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);
}
Filterメソッドでは、作成できるフィルター式を作成することに注意してください。この例では、効果的なクエリは次のようになりますDbSet()。Where(e => e.Id == idValue).First()(上記のハックに似ています)が、このクエリの上に他のlinq演算子を使用できます(複数の基準でフィルタリングするためのFilterメソッドの結果に対するFilterメソッドの呼び出しを含む)
エンティティとコンテキストを次のように定義しました。
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; }
}
次のようにGetEntityメソッドを呼び出します。var e2 = GetEntity(e => e.Id, guidKey);