LINQtoSQL 生成的 SQL 中外连接过多
我对 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
为什么有两个外连接,而一个就足够了?
亲切的问候,
罗纳德
I have a question about a SQL statement generated by a LINQ2SQL query. I have two database tables (VisibleForDepartmentId
is a foreign key):
AssignableObject Department
---------------------- ------------
AssignableObjectId ┌────> DepartmentId
AssignableObjectType │
VisibleForDepartmentId ───┘
And the following mapping information (note that AssignableObject
is abstract):
<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>
And the following code:
var loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Asset>(a => a.VisibleForDepartment);
dataContext.LoadOptions = loadOptions;
var assets = from a in dataContext.Assets
select a;
This results in a SQL query with two identical left outer joins:
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
Why are there two outer joins where one would have been sufficient?
Kind regards,
Ronald
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我找出了导致这些重复的外连接的原因。 当持久类被两个或多个子类继承时,就会发生这种情况。 对于每个子类,如果使用
LoadWith
,则会将新的外部联接添加到生成的 SQL 语句中。在我的示例中,
AssignableObject
有两个子类:Asset
和Role
。 这会产生与Department
表的两个外部联接。 如果我添加另一个子类,则会添加第三个外部联接。我不确定 SQL Server 是否足够聪明,能够意识到外连接是重复的。 我已在 Microsoft Connect 上发布此内容。
编辑:显然我的问题是的重复另一个问题,并且不会在 LINQ2SQL 的下一版本中修复。
I found out what causes these duplicated outer joins. They occur when a persistent class is inherited by two or more subclasses. For each subclass a new outer join is added to the generated SQL statement if you use
LoadWith
.In my example,
AssignableObject
has two subclasses:Asset
andRole
. This results in two outer joins with theDepartment
table. If I add another subclass, a third outer join is added.I'm not sure whether SQL Server is smart enough to realize that the outer joins are duplicated. I've posted this on Microsoft Connect.
EDIT: Apparently my issue was a duplicate of another issue and it won't be fixed in the next release of LINQ2SQL.
您是否意外地在数据库中定义了 2 个外键关系
相同的 2 个表上的相同 2 列?
Do you accidentally have 2 foreign key relationships defined on your database between
the same 2 columns on the same 2 tables ?
您可以尝试在查询本身中进行左外连接。 我不确定生成了什么 SQL,因为我这里没有你的数据库。
You could try doing the left outer join in the query itself. I'm not sure what SQL is generated as I don't have your database here.
我使用其默认数据库在 LINQPad 中创建了一个类似的查询,
并按预期得到
Only one OUTER JOIN is use 。
I have created a similar query in LINQPad using its default database
and get
Only one OUTER JOIN is used as expected.