2017-12-12 24 views
0

DbSet<dbo_Deal>を使用する多くの既存のクエリがあり、権限のないユーザーの機密取引を除外する必要があります。私はDbSet<dbo_Deal>を無効にする方法があるかどうかを知りたいので、デフォルトの動作ではなくテーブル値のパラメータを使用して選択します。Entity Framework DbSetを選択するときにテーブル値関数を呼び出すことはできますか?

[DbFunction("MyDbContext", "GetDeals")] 
[CodeFirstStoreFunctions.DbFunctionDetails(DatabaseSchema = "dbo")] 
public IQueryable<dbo_Deal> GetDeals() 
{ 
    var userKeyParam = new System.Data.Entity.Core.Objects.ObjectParameter("UserKey", typeof(int)) { Value = _userKey }; 
    return ((System.Data.Entity.Infrastructure.IObjectContextAdapter)this).ObjectContext.CreateQuery<dbo_Deal>("[MyDbContext].[GetDeals](@UserKey)", userKeyParam); 
} 
:SQLの関数を呼び出すには、私のDbContextに次

CREATE FUNCTION [dbo].[GetDeals](@UserKey int) 
RETURNS TABLE 
RETURN (
    SELECT d.* 
    FROM dbo.Deal d 
    WHERE d.Confidentiality = 0 
    OR EXISTS(SELECT * 
       FROM dbo.UserRole ur 
       WHERE ur.UserKey = @UserKey 
       AND ur.Role = 'Admin') 
); 

は、私も追加しました:ユーザーがアクセス権を持っていない場合

私は秘密の取引を除外し、次のTVFを作成しました

私はこの関数を呼び出すためにすべてのクエリをリファクタリングできることは知っていますが、Entity Frameworkに何らかの理由でこの関数を使用するように指示できれば素晴らしいでしょう。それは可能ですか?

+0

インターセプタを見て、それがうまくいくかどうかを確認します。 :) –

答えて

0

私は、SQL関数を使用したかった方法を使用液を得ることができなかったので、代わりに私がDbSetをラップされ、このFilteredDbSetを使用。それを実装するために必要だったのは、DbContext内の自分のプロパティの戻り値の型をFilteredDbSetにして、それをコンストラクタ内で目的のフィルタでインスタンス化することでした。クラスのプライベートコンストラクタも公開していますので、単体テストのためにそれを気にすることができました。

これは、既存のLinqのすべてのクエリをリファクタリングする必要がなくなり、今後のクエリで自動的にこの動作が行われるため、非常に良い解決策になりました。

public class FilteredDbSet<TEntity> : IDbSet<TEntity>, IOrderedQueryable<TEntity>, IListSource where TEntity : class 
{ 
    private readonly DbSet<TEntity> _set; 
    private readonly Action<TEntity> _initializeEntity; 
    private readonly Expression<Func<TEntity, bool>> _filter; 

    public FilteredDbSet(DbContext context, Expression<Func<TEntity, bool>> filter, Action<TEntity> initializeEntity) 
    : this(context.Set<TEntity>(), filter, initializeEntity) 
    { 
    } 

    public IQueryable<TEntity> Include(string path) 
    { 
    return _set.Include(path).Where(_filter).AsQueryable(); 
    } 

    private FilteredDbSet(DbSet<TEntity> set, Expression<Func<TEntity, bool>> filter, Action<TEntity> initializeEntity) 
    { 
    _set = set; 
    _filter = filter; 
    _initializeEntity = initializeEntity; 
    } 

    public IQueryable<TEntity> Unfiltered() 
    { 
    return _set; 
    } 

    public TEntity Add(TEntity entity) 
    { 
    DoInitializeEntity(entity); 
    return _set.Add(entity); 
    } 
    public void AddOrUpdate(TEntity entity) 
    { 
    DoInitializeEntity(entity); 
    _set.AddOrUpdate(entity); 
    } 
    public TEntity Attach(TEntity entity) 
    { 
    DoInitializeEntity(entity); 
    return _set.Attach(entity); 
    } 

    public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, TEntity 
    { 
    var entity = _set.Create<TDerivedEntity>(); 
    DoInitializeEntity(entity); 
    return entity; 
    } 

    public TEntity Create() 
    { 
    var entity = _set.Create(); 
    DoInitializeEntity(entity); 
    return entity; 
    } 

    public TEntity Find(params object[] keyValues) 
    { 
    var entity = _set.Find(keyValues); 
    if (entity == null) 
     return null; 


    return entity; 
    } 

    public TEntity Remove(TEntity entity) 
    { 
    if (!_set.Local.Contains(entity)) 
    { 
     _set.Attach(entity); 
    } 
    return _set.Remove(entity); 
    } 


    public ObservableCollection<TEntity> Local 
    { 
    get { return _set.Local; } 
    } 

    IEnumerator<TEntity> IEnumerable<TEntity>.GetEnumerator() 
    { 
    return _set.Where(_filter).GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
    return _set.Where(_filter).GetEnumerator(); 
    } 

    Type IQueryable.ElementType 
    { 
    get { return typeof(TEntity); } 
    } 

    Expression IQueryable.Expression 
    { 
    get 
    { 
     return _set.Where(_filter).Expression; 
    } 
    } 

    IQueryProvider IQueryable.Provider 
    { 
    get 
    { 
     return _set.AsQueryable().Provider; 
    } 
    } 

    bool IListSource.ContainsListCollection 
    { 
    get { return false; } 
    } 

    IList IListSource.GetList() 
    { 
    throw new InvalidOperationException(); 
    } 

    void DoInitializeEntity(TEntity entity) 
    { 
    if (_initializeEntity != null) 
     _initializeEntity(entity); 
    } 

    public DbSqlQuery<TEntity> SqlQuery(string sql, params object[] parameters) 
    { 
    return _set.SqlQuery(sql, parameters); 
    } 
} 
0

MoqあなたDbSetに試してみてください。

public class YourContext: DbContext 
{ 
    public YourContext() 
    { 
     var tvf = GetDeals(); 

     var mockSet = new Mock<DbSet<dbo_Deal>>();  

     mockSet.As<IQueryable<dbo_Deal>>().Setup(m => m.Provider).Returns(tvf.Provider); 
     mockSet.As<IQueryable<dbo_Deal>>().Setup(m => m.Expression).Returns(tvf.Expression); 
     mockSet.As<IQueryable<dbo_Deal>>().Setup(m => m.ElementType).Returns(tvf.ElementType); 
     mockSet.As<IQueryable<dbo_Deal>>().Setup(m => m.GetEnumerator()).Returns(() => tvf.GetEnumerator());   

     //your DbSet: 
     dbo_Deals = mockSet.Object; 
    } 
} 
+0

興味深い考えですが、これはまだ挿入や更新のための通常のように動作しますか? – adam0101

+0

それは挿入と更新のためには機能しませんが、あなたの質問の目的のためにはおそらくそれが機能することは明らかです。 –

関連する問題