2016-11-01 24 views
0

idフィールドを示すラムダ式に基づいてEntity Frameworkを使用して汎用アイテムフィルタを実装しようとしています。次のコードはコンパイルされますが、EFは汎用関数を理解していないため動作しません:動的フィールドに基づくIQueryableのフィルタリング

public static IQueryable<T> Authorize<T>(this IQueryable<T> items, Func<T, Guid> idGetter) where T : class 
{ 
    return items.Where(i => idGetter(i) == new Guid("4A6FE5AF-AB63-4BB3-9D32-88766CF242CC")); 
} 

var result = context.Items.Authorize(i => i.Id); 

どのようにEFを使用してこれを行うには?式ツリーを使って比較するフィールドを教えてください。 Entity Frameworkで処理できるクエリで汎用名を使用する方法

答えて

0

(あなたのコードが示唆されたように)あなたのidフィールドは常にタイプGuidのであれば、あなたのクラスはタイプGuidのメンバーコールIdとのインタフェースを実装できます。

public interface MyInterface 
{ 
    Guid Id { get; set; } 
} 

public class Item : MyInterface 
{ 
    public Guid Id { get; set; } 
    // ... 
} 

を次に、あなたの承認の方法は次のようになりますこの:

public static IQueryable<T> Authorize<T>(this IQueryable<T> items) where T : MyInterface 
{ 
    return items.Where(i => i.Id == new Guid("4A6FE5AF-AB63-4BB3-9D32-88766CF242CC")); 
} 

、次のように、あなたはこれを使用することができます:

var result = items.AsQueryable().Authorize(); 
あなたのコメントに基づいて
+0

ありがとうございます。実際には既にこの実装を過負荷として使用しています。しかし、私はインターフェイスで指定された以外のフィールドを使用できるようにしたい。 – user1039407

+0

反射があなたに役立つかもしれません。あなたのidフィールドを1つの 'Attribute'で「飾り」し、' Authorize'メソッドでリフレクションを使用して –

0

と反射を利用して、これは私のアプローチです:

まず、あなたの(簡単な)Attributeあなたの「IDフィールド」飾るために:

[AttributeUsage(AttributeTargets.Property)] 
public class IdFieldAttribute : Attribute 
{ 
    public IdFieldAttribute() 
    { 
    } 
} 

を次に、あなたのクラスは、次のようになります。

public class Item 
{ 
    [IdFieldAttribute] 
    public Guid YourIdField{ get; set; } 
    // ... 
} 

ご希望のフィールドを取得するためのReflectionヘルパークラス:

public static class ReflectionHelper 
{ 
    public static PropertyInfo GetPropertyInfoByAttribute<T>(T o, Type attributeType) where T : class 
    { 
     var type = o.GetType(); 
     var propertyInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) 
      .FirstOrDefault(pi => Attribute.IsDefined(pi, attributeType)); 

     return propertyInfo; 
    } 
} 

あなたがこれをしたら、あなたのAuthorize方法は次のようになります。

public static IQueryable<T> Authorize<T>(this IQueryable<T> items) where T : class 
{ 
    return items.Where(i => (Guid)ReflectionHelper.GetPropertyInfoByAttribute(i, typeof(IdFieldAttribute)).GetValue(i) == new Guid("4A6FE5AF-AB63-4BB3-9D32-88766CF242CC")); 
} 

そして、次のようにあなたはそれを使用することができます。

var result = items.AsQueryable().Authorize(); 

をお探しのものがあれば、私にはわかりませんこのようなものです。多分このアプローチがあなたを助けるかもしれません。

+0

インテレステイングのアプローチをしてください、ありがとう。毎回ラムダを渡すよりも快適だと思います。しかし、とにかく私はそれをテストする必要はないと思う... Entity Frameworkはこのクエリーを確実に処理できないだろうか?だから私はちょうど今同じ問題を抱えていた 実際に質問は:どのようにEntity Frameworkによって処理することができるクエリで汎用名を使用するのですか? – user1039407

+0

'Authorize'メソッドを呼び出す前にクエリ(' .ToList() ')を具体化する必要があるかもしれません –

+0

確かに_possible_ですが、多くのオブジェクトでは非常に遅い – user1039407

関連する問題