5

由於EF4無法將某些表達式轉換爲SQL,因此我們在相當大的系統中使用EF4並偶爾遇到問題。目前,我們或者需要做一些奇特的步法(DB/Code),或者只是接受性能命中,並允許查詢在內存中執行。擴展EF4 SQL生成

不用說,這些都不是理想的,我們有時不得不使用的黑客降低可讀性/可維護性。

我們理想的想法是擴展EF4 SQL提供程序的SQL生成功能。很明顯,有些東西就像.Net方法調用一樣必須是客戶端,但是一些功能比如日期比較(例如[Linq到Entities的星期幾組)應該可用。

我已經谷歌搜索,但也許我使用錯誤的術語,因爲我所得到的是有關EF4 SQL生成的新功能的信息。

對於這樣一個靈活和可擴展的框架,如果這是不可能的,我會感到驚訝。在我的腦海中,我想象着從[SQL 2008]提供者繼承,並將其擴展爲處理其轉換爲SQL的表達式樹中的其他表達式/類似表達式。

任何幫助/指針讚賞。

我們使用VS2010 Ultimate,.Net 4(非客戶端配置文件)和EF4。該應用程序在ASP.Net,並在64位環境中運行,以防有所作爲。

更新:迴應一些澄清要求;

我們使用的是代碼優先的方法,並有一個控制檯應用程序來創建數據庫並填充一些引用表。

我寧願遠離存儲過程,除非它們也可以以類似的方式生成 - 目前,根據需要生成數據庫的新版本,並且單獨的過程會遷移/同步數據。 一切我們目前正在處理數據庫使用實體。我承認我不能給出一個很好的理由,但是在這種情況下運行SQL腳本來生成存儲過程感覺不對 - 但是如果我錯了,請糾正我的錯誤。

關於具體情況,恐怕我不能在沒有經過冗長的繁文exercise節練習的情況下從我們的代碼中提供一個代碼 - link mentioned above是我們嘗試的那類事情的一個很好的例子完成。在這個例子中,實現一種機制,允許日期計算:

DateTime firstDay = GetFirstDayOfFirstWeekOfYear(); 
var userTimes = from t in context.TrackedTimes 
       group t by new {t.User.UserName, WeekNumber = (t.TargetDate - firstDay).Days/7} into ut 
       select new 
       { 
        UserName = ut.Key.UserName, 
        WeekNumber = ut.Key.WeekNumber, 
        Minutes = ut.Sum(t => t.Minutes) 
       }; 

我可以看到一個辦法,這可以使用SQL孤單但不知道如何使用LINQ到實體(服務器端)做它來完成。

+0

很難回答這樣一個抽象的問題。你正準備支持什麼呢?有很多種方法來做這些事情(EdmFunctions,商店查詢,執行文字SQL等)。 – 2010-06-08 14:15:08

+0

確實 - 我已經擴展了這個問題來包含一個例子。我希望這更清楚? – Basic 2010-06-08 16:51:25

回答

9

我會先尋找建議在EntityFunctions(通用)或SqlFunctions(僅適用於SQL Server)的,其提供在正常的LINQ to Entities查詢中有許多內置的數據庫功能。如果這還不夠,可以使用EdmFunctionAttribute來映射內置數據庫函數或用戶定義的存儲過程。第三個選項是嘗試使其作爲實體SQL查詢來工作。

您建議的最後一個解決方案 - 編寫一個EF提供者 - 相當重量級。編寫一個包裝現有SQL提供程序的EF提供程序是可能的,但您至少必須將某些表達式樹更改爲Entity SQL。非常簡單的EF提供者包裝已在MSDN Code上發佈。不過,我認爲這是最後的手段。

+0

感謝您提供非常有用的鏈接。我需要做一些閱讀並回復你 – Basic 2010-06-08 17:14:41

+0

非常棒,謝謝 - 我們有很多選擇,我們可能會混合搭配 – Basic 2010-06-13 22:37:10

1

從您的基於.NET的LINQ查詢到SQL的轉換由LINQ To Entities Provider處理。我不相信這個非常複雜的核心翻譯/編譯過程是可擴展的。你將不得不從頭開始編寫自己的提供程序。

我還沒有遇到任何可以用SQL表示的查詢,這些查詢不能用LINQ表示。如果你確實有一個很難寫作LINQ查詢的查詢,你有沒有考慮過使用存儲過程呢?如果你能提供一些不會轉換的查詢的例子,這將有所幫助。

UPDATE:

另一種選擇是創建使用定製表達式以表格先進的擴展方法。這裏是模擬載有()函數來執行「其中」類型的查詢一個很好的例子:

'Contains()' workaround using Linq to Entities?

+0

感謝您的回答。 Contains()的鏈接非常有趣,但並不完全符合我們的要求。我們已經有適當的擴展方法,將Expression和Expression方法添加到Expressions.Expression(Of Func(Of T,Boolean))中,以便合適地合併表達式 - 這對於組合來自不同層的多個查詢非常方便應用程序(例如添加安全限制)但是,因爲我無法看到使用LINQ修改查詢的方式(例如,日期減法/日期分割),所以我不明白我該如何應用這種技術? – Basic 2010-06-08 17:09:01

+0

迴應你的答案的第一部分,這看起來正是我想要做的,我開始懷疑它不可擴展,因爲我沒有在其他地方找到任何信息,我當然不能寫 – Basic 2010-06-08 17:13:54

+0

CAST(DateTimeOffset as DateTime)<<<<<<祝你好運,在Linq-To-Entities中做到了這一點,它不可能完成,它非常簡單, DateTimeOffset的DateTime部分在linq-to-entities中是不可能的,所以你可以甚至沒有按照當地的日期和時間過濾DateTimeOffset列,這違背了它存在的全部目的。 – Triynko 2016-12-14 18:33:54