2012-05-13 71 views
1

我正在處理的一個新項目的要求之一是所有SQL查詢都必須使用存儲過程。我將使用實體框架&存儲庫模式來管理數據訪問,在我的存儲庫中,我將使用「Find(predicate)」和「FindAll()」方法。目前他們都使用相同的存儲過程(「select * from Foo」)。LINQ表達式如何與存儲過程一起使用?

因爲我無法訪問SQL Profiler我不太清楚LINQ表達式在我的Find(謂詞)方法中如何轉換?如果我有這樣的:

List<Foo> myFoo = repository.Find(f => f.Country == "Australia" && f.Status = "New"); 

我在承擔,這將通過存儲過程檢索的所有記錄,在內存中過濾得到的數據是否正確?如果是這種情況,我怎樣才能構建sproc以僅檢索所需的記錄,同時允許使用linq表達式(需要允許使用& &,||,!=等)?這是甚至可以不用溝渠sprocs?

+2

幾乎不可能同時有效地使用查詢組合LINQ和query-sprocs。您將基本上使用EF作爲精心設計的方式來編寫圍繞sprocs的包裝代碼。 –

回答

3

如果你不得不使用存儲過程來處理所有事情,那麼使用EF就沒什麼意義了。實際上,EF最大的優點之一就是它可以自動生成查詢,具有大量的參數和正確的查詢sintax來獲取/插入/更新/刪除數據。

有EF的兩個優點,你將失去:

  • 導航,即容易得到相關的數據,與渴望,明示或延遲加載
  • 形數據,即得到具有特性的實體其他實體或實體集合
  • 自動生成簡單CRUD操作(惰性/更新/刪除/選擇)。你可以爲這個操作指定stoed procs
  • 如果數據庫改變了簡單的改變模型(這可以是幾乎自動的,取決於你使用EF的方式)來獲得正確的查詢如果你的數據發生了變化,你會必須修改相關的存儲的特效 *自動生成查詢特設過濾器

如果你不讓EF生成的查詢(其中有超過不同的列不同SETOF條件過濾器),你不會有容易導航,形狀化數據,自動生成正確的查詢和過濾器等等。只要你在模型中做了非常努力的工作,他就會有可能。但是,你的一些變化可能如果更新如果您在使用EF的場合中是合理的使用存儲的特效模型,形成數據庫

丟失是:

  • 您需要修改數據不能由EF直接修改(即舊版EF中的可更新查詢是不支持的)
  • 您優化了要使用的存儲過程,而不是EF生成的查詢,即優化的複雜過濾器
  • 存儲過程,使很多事情(那些不是簡單的插入/更新/刪除或選擇程序)
  • 存儲過程將提供優於自動生成的查詢的任何其他場合。

對於所有其他的查詢,它是更好的讓我們爲你做的工作。

如果您需要爲所有內容使用存儲過程,使用EF的優勢將是數據自動映射到實體,但是您將失去EF的許多其他優勢。

你必須這樣做:

  • 你需要定義儘可能多的實體不同的數據返回的形式存儲的特效
  • 你必須映射每個存儲過程的(它們被映射到函數),函數或修改模型(edmx),讓它知道使用哪個過程來插入/更新/刪除並獲得

這將很難定義通過與它們之間有關係的實體之間的關係來建模。

至於repository.Find(...)在最好的情況下,你是對的,所有的數據將被查詢,然後,在客戶端進行過濾。在最糟糕的情況下,如果您的模型沒有正確定義,它可能會失敗。

如果您讓EF創建查詢,它會將正確的過濾器發送到數據庫(在像您的示例一樣的情況下)。 如果你有專門的存儲過程,以特定的方式過濾,你將不得不忘記LINQ,並直接調用映射函數。

所以,除非有足夠的理由使用SP,否則讓EF爲您創建查詢會更好。

+0

有點晚更新我的問題,但我做了一些擺弄,並得出了相同的結論。我們暫時放棄了對sproc的要求,並會在性能成爲問題時重新審視它(看起來不會)。 –

1

你是對的,開箱即用的,你會在內存中檢索所有記錄和過濾器。我不會說盡可能無法編寫表達式和sprocs,但它是非常不切實際的,可能首先會破壞您的sproc需求的目的。您必須解釋表達式樹並生成參數化的sql並將其傳遞給sproc(可能會破壞sproc需求的目的),或者解釋表達式樹並正確地將參數傳遞給「通用sproc」。 「Generic」意味着它對於任何你想要過濾的參數都有可空的參數(非常不切實際,並且會有很多限制 - 沒有聯接等)。

如果你尊重sproc需求,我會放棄任何暴露IQueryable的數據訪問API(你將失去構建表達式和sprocs的能力,除非你願意在內存中執行你的表達式) 。即使沒有表達式和sprocs之間的可組合性,就像JotaBe指出的那樣,EF仍然可以在處理模型時提供方便,並且避免了模板的粗俗化。