2009-04-16 63 views
1

我對LINQ2SQL查詢生成的SQL語句有疑問。我有兩個數據庫表(VisibleForDepartmentId是一個外鍵):LINQtoSQL生成的外部連接太多SQL

AssignableObject     Department 
----------------------   ------------ 
AssignableObjectId  ┌────> DepartmentId 
AssignableObjectType  │ 
VisibleForDepartmentId ───┘ 

而下面的映射信息(注意:AssignableObject是抽象的):

<Database Name="SO_755661" Class="DataClassesDataContext"> 
    <Table Name="dbo.AssignableObject" Member="AssignableObjects"> 
    <Type Name="AssignableObject" Modifier="Abstract"> 
     <Column Name="AssignableObjectId" Type="System.Int32" 
       DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" 
       IsDbGenerated="true" CanBeNull="false" /> 
     <Column Name="AssignableObjectType" Type="System.String" 
       DbType="VarChar(50) NOT NULL" CanBeNull="false" 
       AccessModifier="Private" IsDiscriminator="true"/> 
     <Column Name="VisibleForDepartmentId" Type="System.Int32" 
       DbType="Int" CanBeNull="true" /> 
     <Association Name="Department_AssignableObject" Member="VisibleForDepartment" 
        ThisKey="VisibleForDepartmentId" OtherKey="DepartmentId" 
        Type="Department" IsForeignKey="true" /> 
     <Type Name="Asset" InheritanceCode="Asset" IsInheritanceDefault="true" /> 
     <Type Name="Role" InheritanceCode="Role" /> 
    </Type> 
    </Table> 
    <Table Name="dbo.Department" Member="Departments"> 
    <Type Name="Department"> 
     <Column Name="DepartmentId" Type="System.Int32" 
       DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" 
       IsDbGenerated="true" CanBeNull="false" /> 
     <Column Name="Name" Type="System.String" DbType="VarChar(50) NOT NULL" 
       CanBeNull="false" /> 
     <Association Name="Department_AssignableObject" Member="AssignableObjects" 
        ThisKey="DepartmentId" OtherKey="VisibleForDepartmentId" 
        Type="AssignableObject" /> 
    </Type> 
    </Table> 
</Database> 

以下代碼:

var loadOptions = new DataLoadOptions(); 
loadOptions.LoadWith<Asset>(a => a.VisibleForDepartment); 
dataContext.LoadOptions = loadOptions; 
var assets = from a in dataContext.Assets 
      select a; 

這導致帶有兩個相同的左外連接的SQL查詢:

SELECT t0.AssignableObjectType, t0.AssignableObjectId, t0.VisibleForDepartmentId, 
     t2.test, t2.DepartmentId, t2.Name, t4.test AS test2, 
     t4.DepartmentId AS DepartmentId2, t4.Name AS Name2 
FROM dbo.AssignableObject AS t0 
LEFT OUTER JOIN (
    SELECT 1 AS test, t1.DepartmentId, t1.Name 
    FROM dbo.Department AS t1 
    ) AS t2 ON t2.DepartmentId = t0.VisibleForDepartmentId 
LEFT OUTER JOIN (
    SELECT 1 AS test, t3.DepartmentId, t3.Name 
    FROM dbo.Department AS t3 
    ) AS t4 ON t4.DepartmentId = t0.VisibleForDepartmentId 

爲什麼會有兩個外部連接,其中一個足夠?

親切的問候,

羅納德

+0

你可以發佈你的對象定義嗎?我想也許你應該做一個.LoadWith(x => x.Department)? – RobS 2009-04-20 06:49:25

回答

3

我發現了什麼導致這些重複的外連接。當一個持久化類被兩個或多個子類繼承時,它們就會發生。對於每個子類,如果使用LoadWith,則會將新外部聯接添加到生成的SQL語句中。

在我的示例中,AssignableObject有兩個子類:AssetRole。這會導致兩個外部連接與Department表。如果我添加另一個子類,則會添加第三個外部聯接。

我不確定SQL Server是否足夠聰明,可以意識到外連接是重複的。我在Microsoft Connect上有posted this

編輯:顯然我的問題是another issue的重複,它不會在下一版本的LINQ2SQL中修復。

1

你不小心有相同的兩列在同一表2之間 對數據庫定義2個外鍵關係?

+0

這幾乎會太簡單:)但事實並非如此。兩桌之間我只有一個外國人。 – 2009-04-16 11:39:01

+0

你可以發表你的表格defnitions爲這兩個表,因爲當我用2個樣本表,其中Dept.DeptID是一個PK和Asset.DeptID是一個FK,我得到一個Inner Join這是我所期望的 – 2009-04-16 12:10:25

0

您可以嘗試在查詢本身中執行左外連接。我不確定生成的SQL是什麼,因爲我沒有你的數據庫。

var assets = from a in dataContext.Assets 
      join d in dataContext.Departments on 
        a.VisibleForDepartmentId equals d.DepartmentId 
        into temp 
      from t in temp.DefaultIfEmpty() 
      select a; 
0

我一直在使用它的默認數據庫

var loadOptions = new DataLoadOptions(); 
loadOptions.LoadWith<Products>(a => a.Category); 
LoadOptions = loadOptions; 

var products = from a in Products 
       select a; 

products.Dump(); 

創造了一個類似的查詢在LINQPad並獲得

SELECT [t0].[ProductID], [t0].[ProductName], [t0].[CategoryID], [t2].[test], [t2].[CategoryID] AS [CategoryID2], [t2].[CategoryName] 
FROM [Products] AS [t0] 
LEFT OUTER JOIN (
    SELECT 1 AS [test], [t1].[CategoryID], [t1].[CategoryName] 
    FROM [Categories] AS [t1] 
    ) AS [t2] ON [t2].[CategoryID] = [t0].[CategoryID] 

只有一個OUTER預期JOIN使用。