關於作者:

本文由微軟最有價值專 MVP TerryChuang 提供。微軟十分感謝 MVP 主動地將他們的經驗與上百萬名其他技術使用者交流。MVP TerryChuang 同時也將此篇文章放在他的部落格內,歡迎您按 此處  瀏覽 MVP TerryChuang 更多的技術文章、經驗分享與觀點。

問題的來龍去脈

當您於 LINQ to Entities 中呼叫 .Net 函式時,可能會遇到【LINQ to Entities 無法辨識方法 '函式名稱(Function_Name)' 方法,而且這個方法無法轉譯成存放區運算式】的錯誤訊息。 

問題的發生原因

由於 LINQ to Entities 中不支援呼叫自訂的 .Net 函式,本文將介紹如何透過 EdmFunction 來解決這個問題。本文以 Northwind 資料庫為例,若使用下列程式碼嘗試統計 Orders 資料表中 OrderDate 所代表星期名稱,就會出現【LINQ to Entities 無法辨識方法 '函式名稱(Function_Name)' 方法,而且這個方法無法轉譯成存放區運算式】的錯誤訊息。

static void Main(string[] args)
{
using (NorthwindEntities context = new NorthwindEntities())
{
var query = from p in context.Orders
group p by GetWeekDay(p.OrderDate.Value) into q
select q;
foreach (var item in query)
{
Console.WriteLine(string.Format("WeekDay={0},Count={1}", item.Key, item.Count()));
}
}
Console.ReadKey();
}
private static string GetWeekDay(DateTime dt)
{
return dt.DayOfWeek.ToString();
}

問題的解決方法

解決方式也許很多種,本文將示範透過撰寫 SQL Server 上的使用者自訂函式(User Defined Function,以下簡稱 UDF)來轉換日期所代表的星期名稱,並搭配 EdmFunction 讓 LINQ to Entities 執行時得以呼叫 UDF,實作步驟如下:

1. 下列程式碼示範自訂 UDF 來進行日期與星期名稱之轉換:

USE [Northwind]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ufn_GetWeekDay]')
AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[ufn_GetWeekDay]
GO
USE [Northwind]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

create function [dbo].[ufn_GetWeekDay](@day datetime)
returns int
begin
return DatePart(dw,@day) -1
end
GO

2. 於.edmx 之 Entity Designer 視窗中加入 ufn_GetWeekDay 函式。



3. 加入 .edmx 的 UDF ufn_GetWeekDay 會出現在模型瀏覽器。





4. 於方案總管中 .edmx 檔案上按右鍵選擇【開啟方式】,以 XML(文字)編輯器開啟.edmx。





5. 找到 EdmFunction 所需要的 Namespace。

<Schema Namespace="NorthwindModel.Store" Alias="Self" Provider="System.Data.SqlClient" 
ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">


<Function Name="ufn_GetWeekDay" ReturnType="int" Aggregate="false" BuiltIn="false" NiladicFunction="false"
IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
<Parameter Name="day" Type="datetime" Mode="In" />
</Function>


6. 找到 EdmFunction 所需的存放區運算式名稱及回傳值。

 <Function Name="ufn_GetWeekDay" ReturnType="int" Aggregate="false" BuiltIn="false" NiladicFunction="false" 
IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
<Parameter Name="day" Type="datetime" Mode="In" />
</Function>


7. 匯入 System.Data.Objects.DataClasses 命名空間。

8. 將 GetWeekDay 加上 EdmFunctionAttribute 調整如下,其中 EdmFunctionAttribute 的第一個參數為 UDF 所對應的 Namespace(如步驟5),第二個參數為 UDF 所對  應的函式名稱(如步驟6),另特別注意回傳值得部分必須與步驟 6 的 ReturnType 相同。

 [EdmFunction("NorthwindModel.Store", "ufn_GetWeekDay")]
private static int GetWeekDay(DateTime dt)
{
return -1;
}

9.按下 F5 重新執行程式。執行結果如下:



其他相關資訊

EdmFunction 類別

請讓我們知道

還滿意我們寫的內容嗎?無論您是遇到了以下任何一種情況:
「太好了!問題解決了。」
「問題沒有解決,我有更好的建議。」
都歡迎您利用本篇文章底部的意見調查表,寫下您寶貴的意見。也期待您的鼓勵,讓我們為您創造更多實用的技術文章。

Need more help?

Expand your skills
Explore Training
Get new features first
Join Microsoft Insiders

Was this information helpful?

How satisfied are you with the translation quality?
What affected your experience?

Thank you for your feedback!

×