2009-04-16 11 views
1

LINQ2SQLクエリによって生成されたSQL文について質問があります。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; 
私は2つのデータベーステーブルを( VisibleForDepartmentIdが外部キーである)を持ちます

この結果、2つの同一の左外部結合を持つ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 

2つの外部結合で十分であったのはなぜですか?

敬具、

ロナルド

+0

オブジェクト定義を投稿できますか?おそらくあなたは.LoadWith(x => x.Department)をやっているはずですか? – RobS

答えて

3

これらの重複した外部結合の原因を突き止めました。永続クラスが2つ以上のサブクラスによって継承されたときに発生します。サブクラスごとに、LoadWithを使用すると、新しい外部結合が生成されたSQL文に追加されます。

私の例では、AssignableObjectには、AssetRoleという2つのサブクラスがあります。これにより、テーブルがDepartmentの2つの外部結合になります。別のサブクラスを追加すると、3番目の外部結合が追加されます。

SQL Serverが外部結合が重複していることを認識するほどスマートであるかどうかはわかりません。私はposted thisをMicrosoft Connectに持っています。

EDIT:明らかに私の問題はanother issueの複製であり、LINQ2SQLの次のリリースでは修正されません。

1

誤って同じ2つのテーブルに同じ2列 の間、データベースに定義された2体の外部キー関係を持っていますか?

+0

それはほとんど簡単すぎるだろう:)しかし、そうではありません。私は2つのテーブルの間に1つしか外国人を持っていません。 –

+0

Dept.DeptIDがPKでAsset.DeptIDがFKの2つのサンプルテーブルを試してみると、私が期待していたInner Joinが得られるので、これらの2つのテーブルのテーブル定義を投稿できます –

+0

Hm私は私の例をあまり単純化しているかもしれません...現実の世界では、これらのテーブルにはもっと多くの列があります。しかし、私はいくつかの他の情報を残しているかもしれません。異なる点の1つは、Assetが抽象永続基本クラスのサブクラスであるという事実です。私はもっ​​と情報を投稿しようとします。 –

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で同様のクエリを作成し、OUTER JOINを

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] 

つだけを取得しているが使用されています。

+0

内部選択で「1 AS [テスト]」とは何ですか? –

+0

このクエリはLINQ to SQLによって自動的に生成されるため、推測することしかできません。 –

関連する問題