0

在使用 Linq 2 SQL 在示例应用程序中实现 AdventureWorks 数据库时,我遇到了一个问题,即 Linq 2 SQL 为我的 DBML 中定义的继承映射中的派生类型生成 SQL 语句的方式。

我的 DBML 中有两个实体,Person 和 PersonPhone(一个 Person 到多个 PersonPhone),没有定义任何继承映射(Person 将在后面的示例中成为继承基类)。如果我随后运行以下 Linq 语句,我注意到在进行跟踪时会按预期生成以下 SQL:

void Main()
{
this.DeferredLoadingEnabled = false;

DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Person>(n => n.PersonPhones);
this.LoadOptions = dlo;

Person person = this.Persons.SingleOrDefault(n => n.BusinessEntityID == 291);
person.PersonPhones.Dump(); 
}

DECLARE @p0 Int = 291
SELECT [t0].[BusinessEntityID], [t0].[PersonType], [t0].[NameStyle], [t0].[Title], [t0].[FirstName], [t0].[MiddleName], [t0].[LastName], [t0].[Suffix], [t0].[EmailPromotion], [t0].[AdditionalContactInfo], [t0].[Demographics], [t0].[rowguid], [t0].[ModifiedDate], [t1].[BusinessEntityID] AS [BusinessEntityID2], [t1].[PhoneNumber], [t1].[PhoneNumberTypeID], [t1].[ModifiedDate] AS [ModifiedDate2], (
    SELECT COUNT(*)
    FROM [Person].[PersonPhone] AS [t2]
    WHERE [t2].[BusinessEntityID] = [t0].[BusinessEntityID]
    ) AS [value]
FROM [Person].[Person] AS [t0]
LEFT OUTER JOIN [Person].[PersonPhone] AS [t1] ON [t1].[BusinessEntityID] = [t0].[BusinessEntityID]
WHERE [t0].[BusinessEntityID] = @p0
ORDER BY [t0].[BusinessEntityID], [t1].[PhoneNumber], [t1].[PhoneNumberTypeID]

结果是在单个语句中生成 SQL。请忽略这可能是低效的 SQL 的事实,我要说的是它在单个语句中运行。

但是,如果我在我的 DBML 中包含继承映射信息并定义一个名为 StoreContact(从 Person 派生)的新实体类型并运行完全相同的查询,我实际上会得到不同的结果,如下所示。在那两个 SQL 语句实际上运行。

DECLARE @p0 Int = 291
SELECT [t0].[PersonType], [t0].[BusinessEntityID], [t0].[NameStyle], [t0].[Title], [t0].[FirstName], [t0].[MiddleName], [t0].[LastName], [t0].[Suffix], [t0].[EmailPromotion], [t0].[AdditionalContactInfo], [t0].[Demographics], [t0].[rowguid], [t0].[ModifiedDate]
FROM [Person].[Person] AS [t0]
WHERE [t0].[BusinessEntityID] = @p0
GO

DECLARE @x1 Int = 291
SELECT [t0].[BusinessEntityID], [t0].[PhoneNumber], [t0].[PhoneNumberTypeID], [t0].[ModifiedDate]
FROM [Person].[PersonPhone] AS [t0]
WHERE [t0].[BusinessEntityID] = @x1

这有点问题,因为这将大大降低我们的应用程序的速度,因为在实现继承功能的情况下,Linq 2 SQL 需要对数据库进行重复调用。看起来拥有 OOP 模型确实是有代价的。

是否有解决此问题的方法可以使 SQL 在单个语句中运行?

4

1 回答 1

0

不幸的是,这不是我正在寻找的答案,但升级到实体框架可以在保持继承的同时解决问题。

如果我运行以下 EF 等效查询:

void Main()
{
    StoreContact person  =(StoreContact)this.People.Include("PersonPhones").SingleOrDefault(n => n.BusinessEntityID == 291);
    person.PersonPhones.Dump(); 
}

我得到以下 SQL 结果:

SELECT 
[Project2].[BusinessEntityID] AS [BusinessEntityID], 
[Project2].[C1] AS [C1], 
[Project2].[NameStyle] AS [NameStyle], 
[Project2].[Title] AS [Title], 
[Project2].[FirstName] AS [FirstName], 
[Project2].[MiddleName] AS [MiddleName], 
[Project2].[LastName] AS [LastName], 
[Project2].[Suffix] AS [Suffix], 
[Project2].[EmailPromotion] AS [EmailPromotion], 
[Project2].[AdditionalContactInfo] AS [AdditionalContactInfo], 
[Project2].[Demographics] AS [Demographics], 
[Project2].[rowguid] AS [rowguid], 
[Project2].[ModifiedDate] AS [ModifiedDate], 
[Project2].[C2] AS [C2], 
[Project2].[BusinessEntityID1] AS [BusinessEntityID1], 
[Project2].[PhoneNumber] AS [PhoneNumber], 
[Project2].[PhoneNumberTypeID] AS [PhoneNumberTypeID], 
[Project2].[ModifiedDate1] AS [ModifiedDate1]
FROM ( SELECT 
    [Limit1].[BusinessEntityID] AS [BusinessEntityID], 
    [Limit1].[NameStyle] AS [NameStyle], 
    [Limit1].[Title] AS [Title], 
    [Limit1].[FirstName] AS [FirstName], 
    [Limit1].[MiddleName] AS [MiddleName], 
    [Limit1].[LastName] AS [LastName], 
    [Limit1].[Suffix] AS [Suffix], 
    [Limit1].[EmailPromotion] AS [EmailPromotion], 
    [Limit1].[AdditionalContactInfo] AS [AdditionalContactInfo], 
    [Limit1].[Demographics] AS [Demographics], 
    [Limit1].[rowguid] AS [rowguid], 
    [Limit1].[ModifiedDate] AS [ModifiedDate], 
    [Limit1].[C1] AS [C1], 
    [Extent2].[BusinessEntityID] AS [BusinessEntityID1], 
    [Extent2].[PhoneNumber] AS [PhoneNumber], 
    [Extent2].[PhoneNumberTypeID] AS [PhoneNumberTypeID], 
    [Extent2].[ModifiedDate] AS [ModifiedDate1], 
    CASE WHEN ([Extent2].[BusinessEntityID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
    FROM   (SELECT TOP (2) 
        [Extent1].[BusinessEntityID] AS [BusinessEntityID], 
        [Extent1].[NameStyle] AS [NameStyle], 
        [Extent1].[Title] AS [Title], 
        [Extent1].[FirstName] AS [FirstName], 
        [Extent1].[MiddleName] AS [MiddleName], 
        [Extent1].[LastName] AS [LastName], 
        [Extent1].[Suffix] AS [Suffix], 
        [Extent1].[EmailPromotion] AS [EmailPromotion], 
        [Extent1].[AdditionalContactInfo] AS [AdditionalContactInfo], 
        [Extent1].[Demographics] AS [Demographics], 
        [Extent1].[rowguid] AS [rowguid], 
        [Extent1].[ModifiedDate] AS [ModifiedDate], 
        '0X0X' AS [C1]
        FROM [Person].[Person] AS [Extent1]
        WHERE 291 = [Extent1].[BusinessEntityID] ) AS [Limit1]
    LEFT OUTER JOIN [Person].[PersonPhone] AS [Extent2] ON [Limit1].[BusinessEntityID] = [Extent2].[BusinessEntityID]
)  AS [Project2]
ORDER BY [Project2].[BusinessEntityID] ASC, [Project2].[C2] ASC

SQL 语句在单个查询中返回结果。

这不是我正在寻找的答案的原因是,对于现有应用程序从 Linq 到 SQL 到实体框架的过渡是相当大的一步。

于 2013-02-18T17:18:41.520 回答