2016-05-13 8 views
2

db.Usersとやり取りするときに常に特定の拡張を呼び出す必要がある方法。以下は、より具体的な情報です。DbSetを使用するときに特定の拡張メソッドが常に呼び出されるようにするEntity Frameworkユニットテスト(または同様の方法)

Entity Frameworkを介して、自分のデータベースと対話するとき、私は次のクエリ(DBはDbContextインスタンスである)を持つ:句が頻繁になりますWHEREこのクエリ

var user = db.Users 
       .FromOrganisation(someId) 
       .FirstOrDefault(u => u.Username == someUsername); 

は、(アプリケーション全体の時間のすべてを変えるだろう異なるものなど)。このため、返されるすべてのデータが最初に組織によってフィルタリングされるように、FromOrganisation()拡張メソッドを常に呼び出さなければならないという要件を作りたいと考えています。

これは、他の組織に属しているデータを見たことがないユーザーを防ぐためですが、これを達成する方法を厳密に守っています。

組織単位でフィルタリングせずにユーザーDbSetが使用されていることを開発者に警告するために書くことができる単体テストはありますか?そうでない場合、同じレベルの保護を達成するために私が取ることのできる代替ルートがありますか?

ことが重要だ場合は、拡張メソッド自体は次のようになります。次のように私は私のコンテキストを変更

public static IQueryable<User> FromOrganisation(this IQueryable<User> u, int organisationId) 
{ 
    return u.Where(x => x.OrganisationId == organisationId); 
} 

私の最終的な解決策

public DbSet<User> Users { get; set; } 

になった:

[Obsolete("MUST use service!")] 
public DbSet<User> UsersUnfiltered { get; set; } 


public IQueryable<User> Users(int id) 
{ 
    #pragma warning disable 618 
    return UsersUnfiltered.Where(x => x.OrganisationId == id); 
    #pragma warning restore 618 
} 

これは、Usersメソッドを使用して組織ごとにフィルタリングされたユーザーリストを返すことを推奨します。これは、通常どおりフィルタ、結合、照会などを行うことができます。

必要に応じてUsersUnfiltered DbSetにアクセスできますが、これを使用するとコンパイラの警告が生成されます。この警告は、#pragma warning disable 618ディレクティブの内部でアクセスすることで抑制できます。

これを実行すると、あなたが本当に意思表示しない限り、あなたが組織でフィルタリングせずにユーザーデータを使用することを防ぐためのコードがあなた側にあります。

@mark_hのおかげでこのソリューションに到達できました。

+0

あなたは 'Users'セットを公開する必要がありますか?あなたが 'IQueryable GetOrganisationUsers(int id)'を介してのみユーザをフェッチするとどうなりますか? – Default

+0

これは非常に興味深い点です。私の文脈では、現在DbSet のリストが公開されています。しかし、私はこれらを問合せに使うだけでなく、データベースに新しいレコードを追加するためにも使用します。そのため、行のどこかに公開しなければならないと思います。 –

+0

コンテキストに 'AddUser'メソッドを追加することができます。別のオプションは、EntityFramework.DynamicFiltersでグローバルフィルタを定義することです。 –

答えて

0

あなたが提案している問題は、その使用を強制できれば、コンテキストから最初のクエリを実行した後でも、一連のユーザをサブクエリする必要があるたびに実行する必要があるということです。

var allUsersOfOrganisation1 = db.Users.FromOrganisation(1) 
// some code... 
var someUsersOfOrganisation1 = allUsersOfOrganisation1.FromOrganisation(1).Where(...) 

あなたはすべてのユーザーを含むセットにクエリし、濾過したサブセットを区別する方法をあなたの拡張メソッドの使用を強制した場合?

エンティティモデルをラップし、ユニークな組織IDを適用するメソッドを通じてユーザーを公開するだけで、結果が得られます。

public class WrappedEntities 
{ 
    private MyEntityFramework Entities = new MyEntityFramework(); 

    //regular public entities 
    public DbSet<Organisation> Organisations { get { return Entities.Organisation; } set { Entities.Organisation = value as DbSet<Organisation>; } } 

    //Special case 
    public IQueryable<User> Users(int id) 
    { 
     return Entities.Users.Where(x => x.OrganisationId == organisationId); 
    } 

    //other wrapped methods... 
    public int SaveChanges() 
    { 
     return Entities.SaveChanges(); 
    } 
} 

このクラスにインターフェイスを与えた場合は、単体テストの目的でモックすることもできます。

+0

遅く返事を申し訳ありません - 私はこれを昨日実装しました。私は私の元の質問に私の最終的な解決策を掲示します。ご協力いただき誠にありがとうございます。 –

関連する問題