2012-01-06 31 views
2

SQL我已經建立了測試數據庫和控制檯應用程序,以確認以下內容:LinqToSql DataContext的與提取的接口並不構成對功能

給定一個SQL數據庫具有以下功能:

CREATE FUNCTION ufn_GTFO 
(
    @Guid as uniqueidentifier 
) 
RETURNS VARCHAR(100) 
AS 
BEGIN 
    -- Declare the return variable here 
    DECLARE @Result as VARCHAR(100) 

    -- Add the T-SQL statements to compute the return value here 
    SELECT @Result = 'This is a test' 

    -- Return the result of the function 
    RETURN @Result 
END 
GO 

而且下表:

CREATE TABLE [dbo].[Test](
    [PKey] [int] IDENTITY(1,1) NOT NULL, 
    [WFT] [uniqueidentifier] NULL, 
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
    [PKey] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

的標量值函數ufn_GTFO通常是可組合的,從而使下面的C#:

static void ConcreteTest() 
{ 
    DataClasses1DataContext db = new DataClasses1DataContext(); 
    var q = from t in db.Tests 
      select new { t.PKey, GTFO = db.ufn_GTFO(t.WFT) }; 

    var p = q.ToArray(); 
} 

翻譯成下面的SQL:

SELECT [t0].[PKey], [dbo].[ufn_GTFO]([t0].[WFT]) AS [GTFO] FROM [dbo].[Test] AS [t0] 

但是,如果我用重構 - 上的DataContext>提取接口,並且使用的是一個實例:

static void InterfaceTest() 
{ 
    IDataClasses1DataContext db = new DataClasses1DataContext(); 
    var q = from t in db.Tests 
      select new { t.PKey, GTFO = db.ufn_GTFO(t.WFT) }; 

    var p = q.ToArray(); 
} 

我獲取以下SQL,並且對每條記錄調用ufn_GTFO會發生一次,如.ToArray()枚舉結果。

SELECT [t0].[PKey], [t0].[WFT] AS [guid] 
FROM [dbo].[Test] AS [t0] 

所以,我的問題是,爲什麼會發生這種情況,我能做些什麼來防止它同時仍使用界面?

更新1:我比較了IL的具體方法與接口方法產生的,並且它們僅在參考到接口和一個編譯器生成的顯示類,似乎不具有任何不同影響結果。

+0

我不會發佈一個答案,因爲我不從LINQ的角度知道,但我確實知道,SQL服務器也會在第一個查詢中爲每一行運行ufn_GTFO。 – Eric 2012-01-10 18:35:12

+0

@eric - 你是對的,但在本地運行它vs.每行另一個調用與性能角度大不相同。 – 2012-01-11 02:20:53

回答

1

linq to sql嚴重依賴於屬性來將class(datacontext)成員映射到數據庫成員。您的接口可能沒有通過ufn_GRFO方法的FunctionAttribute。如果沒有該屬性,C#世界和SQL函數之間的鏈接就會被切斷;然而。你的接口也沒有用DatabaseAttribute裝飾,因爲該屬性只對類而不是接口有效。沒有這個屬性,你已經切斷了C#和整個數據庫之間的鏈接。默認情況下,Linq使用AttributeMappingSource來映射DataContext中的類型成員。感覺接口是有問題的類型,並且該類型已切斷與該數據庫的鏈接,由於您無法將數據庫屬性應用於該數據庫,因此默認映射源將不會將函數ufn_GRFO映射到數據庫函數,相反,linq會把它當作一個.NET函數來調用來自WFT領域的數據。

我懷疑解決此問題的方法是爲您的datacontext提供自定義MappingSource實現,並忽略DatabaseAttribute並只考慮屬性的屬性。

http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.functionattribute.aspx

http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.databaseattribute.aspx

http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.attributemappingsource.aspx

http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.mappingsource.aspx