2012-01-06 51 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