2009-04-16 62 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使用。