我对LINQ2SQL查询生成的SQL语句有疑问。我有两个数据库表(VisibleForDepartmentId
是外键):
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 :(得分:3)
我发现了导致这些重复外连接的原因。当持久化类由两个或更多子类继承时,就会发生这种情况。对于每个子类,如果使用LoadWith
,则会向生成的SQL语句添加新的外部联接。
在我的示例中,AssignableObject
有两个子类:Asset
和Role
。这导致与Department
表的两个外部联接。如果我添加另一个子类,则添加第三个外连接。
我不确定SQL Server是否足够聪明才能意识到外连接是重复的。我在Microsoft Connect上posted this。
编辑:显然我的问题与another issue重复,并且不会在LINQ2SQL的下一个版本中修复。
答案 1 :(得分:1)
您是否意外地在数据库之间定义了2个外键关系 相同的2个表上相同的2列?
答案 2 :(得分: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;
答案 3 :(得分:0)
我在LINQPad中使用默认数据库
创建了一个类似的查询var loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Products>(a => a.Category);
LoadOptions = loadOptions;
var products = from a in Products
select a;
products.Dump();
并获取
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。