带有解压缩接口的LinqToSql DataContext不会为函数组成SQL

时间:2012-01-06 23:42:00

标签: linq-to-sql

我已设置测试数据库和控制台应用以确认以下内容:

给定具有以下功能的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和接口方法,它们的区别仅在于对接口的引用和编译器生成的显示类没有&# 39;似乎与结果有关。

1 个答案:

答案 0 :(得分:1)

linq to sql在很大程度上依赖于将类(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