2015-10-05 56 views
2

我做我所做的最終原因是爲DbContext提供了一些緩存功能。爲了實現這一點,我試圖通過覆蓋上下文中的Set<T>()方法來擴展默認DbSet功能,並返回直接從通用DbSet類派生的類型對象。就像這樣:EF6:從派生DbSet獲取數據

public class Context : DbContext 
{ 
    ... 

    public override DbSet<TEntity> Set<TEntity>() 
    { 
     //var set = base.Set<TEntity>(); 
     var set = new XxSet<TEntity>(); 
     return set; 
    } 
} 

class XxSet<TEntity> : System.Data.Entity.DbSet<TEntity> 
    where TEntity : class 
{ 
    public override TEntity Find(params object[] keyValues) 
    { 
     return base.Find(keyValues); 
    } 
} 

看起來簡單明瞭,但是當我在這個運行我的測試中,EF給我一個錯誤:

The member 'IQueryable.Provider' has not been implemented on type 'XxSetˊ1' which inherits from 'DbSetˊ1'. Test doubles for 'DbSetˊ1' must provide implementations of methods and properties that are used.

它要求我執行的IQueryable接口。這是我明白,但爲什麼?它不應該已經在基類中實現了嗎? 我想它必須,否則,將如何工作Set<T>()方法的基本功能,該方法返回的對象由System.Data.Entity.DbSet<TEntity>類型實例化。

我在這裏錯過了什麼嗎?

順便說一句。我知道關於創建內存中DbSets的Microsoft示例。我只是想明白爲什麼我不能這麼簡單。

+1

我不知道爲什麼它不工作,這看起來像是可以做的事情,但實體不喜歡它,在這個鏈接:http://stackoverflow.com/questions/21069986/nsubstitute- dbset-iqueryablet也有類似的錯誤,對不起,如果它根本沒有幫助你 –

+0

嗯,它實際上幫助了我。我錯過了'DbSet'中顯式'IQueryable'實現的事實。感謝您的鏈接。 – drty

回答

0

我不知道爲什麼會這麼想的工作,這看起來像的東西,可能已經完成,但實體這麼想的喜歡,​​在這個環節上:

NSubstitute DbSet/IQueryable<T>

也有類似的錯誤,對不起,如果它根本沒有幫助你 -

這是答案呢?很高興幫助你。

+1

類別。發生該問題是因爲某些內部EF功能不希望將'DbSet'實例強制轉換爲'IQueryable'來解決接口成員問題,而是傾向於尋求它的隱式實現。仍然不知道他們爲什麼選擇這種方法。 – drty

+0

實體以神祕的方式工作! –

0

我已經有一些類實現接口繼承IDbSet的這些問題。這是因爲所有(或至少大多數)IQueryable方法都不是在DbSet中實現的,而是Queryable類的擴展方法。大多數模擬框架不能模擬靜態擴展方法。我加入的方法來我的派生接口克服的問題,並實現在我的類中的方法:IDerivedDbSet按照這些例子:

public IQueryable<T> Where(Expression<Func<T, bool>> predicate) 
    { 
     return this._dbSet.Where(predicate); 
    } 

    public bool Any(Expression<Func<T, bool>> predicate) 
    { 
     return this._dbSet.Any(predicate); 
    } 

測試,其中這些方法均採用的是有點髒,但因爲你現在必須嘲笑該方法,而不是依靠實際在由模擬注入的IQueryable上執行的擴展。下面是一個例子:

this._context = Substitute.For<IDerivedContext>(); 
this._permissionSet = Substitute.For<IDerivedSet<Permission>>(); 
this._permission1 = new Permission 
     { 
      UserID = 1, 
      MenuID = 26, 
      PermissionAllow = true 
     }; 
var queryable = (new List<Permission> { this._permissionLink1 }).AsQueryable(); 
this._permissionSet.Any(Arg.Any<Expression<Func<Permission, bool>>>()).Returns(x => queryable.Any((Expression<Func<Permission, bool>>)x[0])); 

var result = this._permissionsProvider.HasPermissionToSomething(this._context, 1); 
Assert.IsTrue(result); 

髒位是,對於IDerivedDbSet.Any方法表達參數隨後被用作用於直接援引上可查詢的Queryable.Any擴展方法表達參數。這並不是很好,因爲它假定兩個Any方法都做同樣的事情,但它確實允許我模擬實現的實際查詢並聲明被測試的類在此基礎上返回正確的結果。如果我更改了測試類方法中的查詢,則測試失敗。