2016-05-27 16 views
1

私はこれらの2つのエラーの間で、約50のクラスで共有されているエンティティコードを汎用化しようとしています。エンティティの一般的なキー

'System.Object'型の定数値を作成できません。このコンテキストでは、プリミティブ型または列挙型のみがサポートされています。演算子 '==' はタイプのオペランドに適用することはできません

'TKEY' と 'TKEY'

public abstract class BaseRepository<TEntity, TKey> : BaseRepository 
    where TEntity : KeyedBaseModel<TEntity, TKey> 
{ 
    public BaseRepository(MyProjectContext context) 
    { 
     Context = context; 
    } 

    protected MyProjectContext Context { get; set; } 

    public async Task<TEntity> SelectById(TKey id) 
    { 
     return await Context.Set<TEntity>().FirstOrDefaultAsync(s => s.Id == id); 
    } 
} 

問題がここに存在します:

s => s.Id == id 

私が使用している場合== I Guidをプライマリキーとして使用するオブジェクトにエラーが発生し、使用するとエラーが発生します...

s => s.Id.Equals(id) 

EntityがSystem.Object型の定数を作成できないというエラーが発生します。

+0

動作しますが、私はに興味ラムダを使うことができるもの – StrangeWill

+0

's.Id.Equals'を使用すると、結果の式は' s.Id'を「定数オブジェクト」( 'Expression.Constant')とEntity Frameworkにキャスト/変換するので、Entity Frameworkでは動作しませんそれで動作することはできません。一方、 's.Id == id'は、C#コンパイラがequals演算子と何をするべきか分からないのでコンパイルされません。オーバーロードされた' == 'を発見しようとするべきでしょうか?それは 'TKey'タイプのものであればボックスに入れて参照の比較をするべきでしょうか? –

+0

ところで、私はあなたが 'Expression.Equals'、' Expression.Parameter'、 'Expression.Property'と' Expression.Constant'の組み合わせを使ってあなた自身の述語式*を書くならば、コンパイラをバイパスすることができると思います。何かこのような[リンク](http://stackoverflow.com/questions/15977908/creating-a-linq-expression-where-parameter-equals-object) –

答えて

0

あなたは私はあなたがこれは私の知る限りとして動作します。この

public async Task<TEntity> SelectById(TKey id) 
    { 
     var idEquals = KeyedBaseModel<TEntity, TKey>.IdEquals(id); 
     return await Context.Set<TEntity>().FirstOrDefaultAsync(idEquals); 
    } 

よう

public class KeyedBaseModel<TEntity, TKey> 
{ 
    public static readonly Type EntityType = typeof(TEntity); 
    public static readonly Type KeyType = typeof(TKey); 
    public static readonly PropertyInfo KeyProperty = EntityType.GetProperty(nameof(Id), BindingFlags.Public | BindingFlags.Instance); 

    public static Expression<Func<TEntity, bool>> IdEquals(TKey key) 
    { 
     var parameter = Expression.Parameter(EntityType, "x"); // x => 
     var property = Expression.Property(parameter, KeyProperty); // x => x.Id 
     var constant = Expression.Constant(key, KeyType); // id 
     var equal = Expression.Equal(property, constant); // x => x.Id == id 

     return Expression.Lambda<Func<TEntity, bool>>(equal, parameter); 
    }  

    public TKey Id { get; protected set; } 
} 

のようなものがあなたのリポジトリで使用されることになるでしょうと思い

Type t=typeof(Tkey); 
Func<TEntity, bool> predicate=s=>s.Id==id; 
if(t==typeof(Guid)) 
{ 
    predicate=s=>s.Id.Equals(id); 
} 
return await Context.Set<TEntity>().FirstOrDefaultAsync(predicate); 
2

を使用して試すことができますテストしましたが、私はこのデザインが好きではありません私はちょうどGuidをキーにして、KeyedBaseModelを単一パラメータジェネリック型または非ジェネリックベースエンティティ型に変換します。

EDIT 私はちょうどEntittyフレームワークコア(RC 2)でこれを試みたのだが、このために私の問題を解決しないことが判明()を使用

public async Task<TEntity> SelectById(TKey id) 
{ 
    return await Context.Set<TEntity>().FirstOrDefaultAsync(s => s.Id.Equals(id)); 
} 
+0

あなた自身の表現を1曲ずつ作り上げるのは楽しいことです...これはこれを行うにあたり_really_ nastyな方法だと思いますが、それは唯一の方法かもしれません。私は、2つの厳密な型のKeyedBaseModels、1つはGuid、もう1つはintのために見つけて、さらに悪い方向に動くと思います。誰も他の人がもう少し実践的なことを見つけないなら、私は先に進んでこれを答えにします。 – StrangeWill

関連する問題