2016-09-14 44 views
1

假設我有我的(代碼優先)實體框架模型中的實體,看起來像這樣:訂購實體框架的查詢由rowversion財產,在存儲和內存

public class Foo 
{ 
    [Key] 
    [MaxLength(50)] 
    public string FooId { get; set; } 

    [Timestamp] 
    [ConcurrencyCheck] 
    public byte[] Version { get; set; } 
} 

進一步假設,我需要取最近幾個這些項目。我可以用一個相當簡單的LINQ表達式來做到這一點,該表達式會被轉換成正確的SQL,並且運行良好。

var recentFoos = db.Foos.OrderBy(f => f.Version).Take(10); 

現在,如果該查詢發生在我也想測試的方法中,事情會變得更加複雜。我有一個虛假的上下文和實體集合的設置,並且這一切都正常工作。但是,因爲byte[]不能直接排序,試圖執行該代碼會拋出一個ArgumentException(「至少有一個對象必須實現IComparable。」)。另一方面,如果我使用OrderBy()的重載比較器,它會在內存中運行,但會拋出一個異常(「...該方法不能轉換成存儲表達式」),試圖運行數據庫。

有沒有辦法a)寫一個LINQ查詢,在兩種情況下都能正確運行,或b)可靠地檢測哪些情況屬於哪個屬性,以便我的代碼可以使用正確的重載進行排序?

+1

查詢應該以** real **查詢提供程序(本例中爲LINQ to Entities)支持的方式編寫,即完全如何執行。這是你的假上下文實現的問題,所以你需要找到一種方法來糾正它,而不是試圖調整生產代碼進行測試(最後聽起來荒謬的是我)。 –

+0

好的。你有關於如何做這項工作的具體建議?虛假的上下文設置非常標準(請參閱https://msdn.microsoft.com/zh-cn/library/dn314429.aspx)。 –

+0

而你在他們所提到的內容中是非常失敗的** EF內存測試的侷限性增加了一倍**(許多情況下他們沒有提到像使用僅適用於LINQ to Entities的規範函數或僅使用CLR方法在LINQ to Objects中)。這就是爲什麼我反對用假貨測試EF,我不這樣做,沒有問題。祝你好運。 –

回答

0

我最終實現瞭解決方案jnm2 suggested:編寫了一個ExpressionVisitor,將查詢從普通查詢使用的僅謂詞重載重寫爲內存查詢所需的重載。我必須修改original Microsoft sample code for fake DbSet以允許這些訪問者在正確的時刻插入並使用。

我的代碼爲can be found here。如果任何人都可以建議一個更優雅的方式來申請遊客,我肯定會接受建議。