質問編集履歴

3 タグを追加 (LINQ to Entities, Entity Framework)

sk_3122

sk_3122 score 1015

2017/02/07 15:44  投稿

LINQ to Entities : LEFT JOIN の結合条件にテーブル同士の大小比較
###前提・実現したいこと
SQL (SQL Server) で書く際、LEFT JOIN の結合条件に **テーブル同士の値で大小比較** を入れているケースがあるのですが、
これを LINQ to Entities (VB.NET) で書きたいです。
```sql
SELECT *
FROM MAIN m
LEFT JOIN AAA a ON (
a.ID = m.ID
AND a.IsDeleted = 0
AND a.BeginYmd <= m.Ymd AND m.Ymd <= a.EndYmd -- ★こういう条件
)
```
###発生している問題
LEFT JOIN の結合条件に「テーブル同士の値で大小比較」を指定する方法が分かりません。
###試したソースコード
以下の書き方だと、★の部分で
> 'Equals' の両辺で、少なくとも 1 つの範囲変数を参照しなければなりません。
> 'Equals' 演算子の一方で 1 つ以上の範囲変数 'm' を参照し、他方で 1 つ以上の範囲変数 'a' を参照する必要があります。
というエラーになります。
```VBnet
Dim query1 = (
From m In dbContext.MAIN
Group Join a In dbContext.AAA On New With {
m.ID,
.IsDeleted = CType(0, Integer),
.CheckYmd = True
} Equals New With {
a.ID,
a.IsDeleted,
.CheckYmd = (a.BeginYmd <= m.Ymd AndAlso m.Ymd <= a.EndYmd) ← ★ m.*** でコンパイルエラー
}
Into _a = Group From a In _a.DefaultIfEmpty()
Select New With {
.ID = m.ID,
.StoreId = a.StoreID,
.StartYmd = a.StartYmd,
.EndYmd = a.EndYmd
}
)
```
リテラル値 (IsDeletedの部分) を指定するのと同じよう名前を付けてあげればいけるかと思ったのですが、違うようでした。
検索してみたのですが、解決方法と思われるものを見つけられませんでした。
----
↓ これは通る
```VBnet
...
Group Join a In dbContext.AAA On New With {
m.ID,
.IsDeleted = CType(0, Integer),
.CheckYmd = True
} Equals New With {
a.ID,
a.IsDeleted,
.CheckYmd = True ← ★リテラル値なら問題ない
}
...
```
↓ これも通る
```VBnet
...
Group Join a In dbContext.AAA On New With {
m.ID,
.IsDeleted = CType(0, Integer),
.CheckYmd = True
} Equals New With {
a.ID,
a.IsDeleted,
.CheckYmd = (a.BeginYmd <> "") ← ★a の値を見るのも問題ない
}
...
```
↓ これは駄目
```VBnet
...
Group Join a In dbContext.AAA On New With {
m.ID,
.IsDeleted = CType(0, Integer),
.CheckYmd = True
} Equals New With {
a.ID,
a.IsDeleted,
.CheckYmd = (m.Ymd <> "") ← ★ここで m を見ようとすると駄目
}
...
```
↓ これは駄目
```VBnet
...
Group Join a In dbContext.AAA On New With {
m.ID,
.IsDeleted = CType(0, Integer),
.CheckYmd = (a.Ymd <> "") ← ★左辺と右辺を入れ替えると、逆に m はOKだが a が駄目になる
} Equals New With {
a.ID,
a.IsDeleted,
.CheckYmd = True
}
...
```
なんとなく駄目なパターンはわかったのですが、どうすれば目的の条件で抽出できるのかわかりません。
###追記:IEquatable を実装してみた版(うまくいかず)
```VBnet
Public Class JoinParamMainAndAAA : Implements IEquatable(Of Object)
Public Property ID As String = Nothing
Public Property StartYmd As String = Nothing
Public Property EndYmd As String = Nothing
Public Property Ymd As String = Nothing
Public Enum TableTypes
Main
AAA
End Enum
Public Property TableType As TableTypes
Public Overloads Function Equals(ByVal obj As Object) As Boolean Implements IEquatable(Of Object).Equals
' 想定している型でなければ抜ける
If obj Is Nothing OrElse obj.GetType() IsNot GetType(JoinParamMainAndAAA) Then
Return False
End If
Dim chk = CType(obj, JoinParamMainAndAAA)
Dim m As JoinParamMainAndAAA = Nothing
Dim a As JoinParamMainAndAAA = Nothing
Select Case(Me.TableType)
Case TableTypes.Main:
' 自分がMainの場合は相手はAAA
If chk.TableType = TableTypes.AAA Then
m = Me
a = chk
End If
Case TableTypes.AAA:
' 自分がAAAの場合は相手はMain
If chk.TableType = TableTypes.Main Then
m = chk
a = Me
End If
End Select
If m Is Nothing OrElse a Is Nothing Then Return False
' 比較
If m.ID = a.ID AndAlso
a.StartYmd <= m.Ymd AndAlso m.Ymd <= a.EndYmd Then
Return True
End If
Return False
End Function
Public Overrides Function GetHashCode() As Integer
Return CType(Me.ID.GetHashCode() ^ Me.Ymd.GetHashCode() ^ Me.StartYmd.GetHashCode() ^ Me.EndYmd.GetHashCode(), Integer)
End Function
End Class
```
```VBnet
...
Group Join a In dbContext.AAA On New JoinParamMainAndAAA With {
.TableType = JoinParamMainAndAAA.TableTypes.Main,
.ID = m.ID,
.Ymd = m.Ymd,
.StartYmd = Nothing,
.EndYmd = Nothing
} Equals New JoinParamMainAndAAA With {
.TableType = JoinParamMainAndAAA.TableTypes.AAA,
.ID = a.ID,
.Ymd = Nothing,
.StartYmd = a.StartYmd,
.EndYmd = a.EndYmd
}
...
' 不要な値にもNothingをセットしているのは、そうしないと以下のエラーが出た為
' The type 'TestTest.JoinParamMainAndAAA' appears in two structurally incompatible initializations within a single LINQ to Entities query. A type can be initialized in two places in the same query, but only if the same properties are set in both places and those properties are set in the same order.
```
実際に発行されたSQLを確認したところ、LEFT JOIN の結合が 1 = 0 となっていました。
というかEqualsの先頭にブレイクポイントをはっても止まりませんでしたが… 実装がおかしい?
```SQL
SELECT
1 AS [C1],
[Extent1].[ID] AS [ID],
[Extent2].[StartYmd] AS [StartYmd],
[Extent2].[EndYmd] AS [EndYmd]
FROM [dbo].[MAIN] AS [Extent1]
LEFT OUTER JOIN [dbo].[AAA] AS [Extent2] ON 1 = 0
```
### 追記:StackOverflowで見つけた内容
http://stackoverflow.com/questions/10642421/using-equal-and-not-equal-in-a-linq-join
> A join clause performs an equijoin. In other words, you can only base matches on the equality of two keys.
> Other types of comparisons such as "greater than" or "not equals" are not supported.
> join節が等価結合を実行します。 言い換えれば、2つのキーが等しいかどうかに基づいて照合を行うことができます。
> 「より大きい」または「等しくない」などの他のタイプの比較はサポートされていません。
上記の質問内容は `LEFT JOIN AAA ON (AAA.RoleName <> 'Admin')` みたいなのはできないの?という内容で 私の問題とは少し違うのですが… 系統的には似てるかなと。
結局 単純な等価評価しかサポートしていないということでしょうか。
# EntityFramework を使う人は適用期間を見たりするSQLとかって組まないのでしょうか…?
###一応考えた方法
Where 句で見る…? というのを一応考えたのですが、他に方法がないものかと思い質問させて頂きました。
```VBnet
Dim query1 = (
From m In dbContext.MAIN
Group Join a In dbContext.AAA On New With {
m.ID,
.IsDeleted = CType(0, Integer)
} Equals New With {
a.ID,
a.IsDeleted
}
Into _a = Group From a In _a.DefaultIfEmpty()
Where (a.ID = Nothing OrElse (a.BeginYmd <= m.Ymd AndAlso m.Ymd <= a.EndYmd))
Select New With {
.ID = m.ID,
.StoreId = a.StoreID,
.StartYmd = a.StartYmd,
.EndYmd = a.EndYmd
}
)
```
###補足情報(言語/FW/ツール等のバージョンなど)
開発環境等
Windows10
Visual Studio 2013
.NET Framework 4
VB.NET
足りない情報等ありましたらご指摘ください。
御存知の方がいらっしゃいましたらよろしくお願いします。
  • LINQ

    154 questions

    LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

  • VB.NET

    1306 questions

    Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

  • Entity Framework

    70 questions

    Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

  • LINQ to Entities

    6 questions

    LINQ to Entitiesは、言語統合クエリであるLINQをEDMに行う機能を指します。C#/VBといった言語に統合されており、Visual StudioのIntelliSense機能を始めとするコーディングの様々なサポートを受けることが可能です。

2 StackOverflowで見つけた内容

sk_3122

sk_3122 score 1015

2017/02/07 13:16  投稿

LINQ to Entities : LEFT JOIN の結合条件にテーブル同士の大小比較
###前提・実現したいこと
SQL (SQL Server) で書く際、LEFT JOIN の結合条件に **テーブル同士の値で大小比較** を入れているケースがあるのですが、
これを LINQ to Entities (VB.NET) で書きたいです。
```sql
SELECT *
FROM MAIN m
LEFT JOIN AAA a ON (
   a.ID = m.ID
   AND a.IsDeleted = 0
   AND a.BeginYmd <= m.Ymd AND m.Ymd <= a.EndYmd -- ★こういう条件
)
```
###発生している問題
LEFT JOIN の結合条件に「テーブル同士の値で大小比較」を指定する方法が分かりません。
###試したソースコード
以下の書き方だと、★の部分で
> 'Equals' の両辺で、少なくとも 1 つの範囲変数を参照しなければなりません。
> 'Equals' 演算子の一方で 1 つ以上の範囲変数 'm' を参照し、他方で 1 つ以上の範囲変数 'a' を参照する必要があります。
というエラーになります。
```VBnet
Dim query1 = (
   From m In dbContext.MAIN
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer),
       .CheckYmd = True
   } Equals New With {
       a.ID,
       a.IsDeleted,
       .CheckYmd = (a.BeginYmd <= m.Ymd AndAlso m.Ymd <= a.EndYmd)   ← ★ m.*** でコンパイルエラー
   }
   Into _a = Group From a In _a.DefaultIfEmpty()
   Select New With {
       .ID      = m.ID,
       .StoreId = a.StoreID,
       .StartYmd = a.StartYmd,
       .EndYmd  = a.EndYmd
   }
)
```
リテラル値 (IsDeletedの部分) を指定するのと同じよう名前を付けてあげればいけるかと思ったのですが、違うようでした。
検索してみたのですが、解決方法と思われるものを見つけられませんでした。
----
↓ これは通る
```VBnet
   ...
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer),
       .CheckYmd = True
   } Equals New With {
       a.ID,
       a.IsDeleted,
       .CheckYmd = True   ← ★リテラル値なら問題ない
   }
   ...
```
↓ これも通る
```VBnet
   ...
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer),
       .CheckYmd = True
   } Equals New With {
       a.ID,
       a.IsDeleted,
       .CheckYmd = (a.BeginYmd <> "")   ← ★a の値を見るのも問題ない
   }
   ...
```
↓ これは駄目
```VBnet
   ...
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer),
       .CheckYmd = True
   } Equals New With {
       a.ID,
       a.IsDeleted,
       .CheckYmd = (m.Ymd <> "")   ← ★ここで m を見ようとすると駄目
   }
   ...
```
↓ これは駄目
```VBnet
   ...
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer),
       .CheckYmd = (a.Ymd <> "")   ← ★左辺と右辺を入れ替えると、逆に m はOKだが a が駄目になる
   } Equals New With {
       a.ID,
       a.IsDeleted,
       .CheckYmd = True
   }
   ...
```
なんとなく駄目なパターンはわかったのですが、どうすれば目的の条件で抽出できるのかわかりません。
###追記:IEquatable を実装してみた版(うまくいかず)
```VBnet
Public Class JoinParamMainAndAAA : Implements IEquatable(Of Object)
   Public Property ID As String = Nothing
   Public Property StartYmd As String = Nothing
   Public Property EndYmd As String = Nothing
   Public Property Ymd As String = Nothing
   Public Enum TableTypes
       Main
       AAA
   End Enum
   Public Property TableType As TableTypes
   Public Overloads Function Equals(ByVal obj As Object) As Boolean Implements IEquatable(Of Object).Equals
       ' 想定している型でなければ抜ける
       If obj Is Nothing OrElse obj.GetType() IsNot GetType(JoinParamMainAndAAA) Then
           Return False
       End If
       Dim chk = CType(obj, JoinParamMainAndAAA)
       Dim m As JoinParamMainAndAAA = Nothing
       Dim a As JoinParamMainAndAAA = Nothing
       Select Case(Me.TableType)
           Case TableTypes.Main:
               ' 自分がMainの場合は相手はAAA
               If chk.TableType = TableTypes.AAA Then
                   m = Me
                   a = chk
               End If
           Case TableTypes.AAA:
               ' 自分がAAAの場合は相手はMain
               If chk.TableType = TableTypes.Main Then
                   m = chk
                   a = Me
               End If
       End Select
       If m Is Nothing OrElse a Is Nothing Then Return False
       ' 比較
       If m.ID = a.ID AndAlso
          a.StartYmd <= m.Ymd AndAlso m.Ymd <= a.EndYmd Then
           Return True
       End If
       Return False
   End Function
   Public Overrides Function GetHashCode() As Integer
       Return CType(Me.ID.GetHashCode() ^ Me.Ymd.GetHashCode() ^ Me.StartYmd.GetHashCode() ^ Me.EndYmd.GetHashCode(), Integer)
   End Function
End Class
```
```VBnet
   ...
   Group Join a In dbContext.AAA On New JoinParamMainAndAAA With {
       .TableType = JoinParamMainAndAAA.TableTypes.Main,
       .ID = m.ID,
       .Ymd = m.Ymd,
       .StartYmd = Nothing,
       .EndYmd = Nothing
   } Equals New JoinParamMainAndAAA With {
       .TableType = JoinParamMainAndAAA.TableTypes.AAA,
       .ID = a.ID,
       .Ymd = Nothing,
       .StartYmd = a.StartYmd,
       .EndYmd = a.EndYmd
   }
   ...
   ' 不要な値にもNothingをセットしているのは、そうしないと以下のエラーが出た為
   ' The type 'TestTest.JoinParamMainAndAAA' appears in two structurally incompatible initializations within a single LINQ to Entities query. A type can be initialized in two places in the same query, but only if the same properties are set in both places and those properties are set in the same order.
```
実際に発行されたSQLを確認したところ、LEFT JOIN の結合が 1 = 0 となっていました。
というかEqualsの先頭にブレイクポイントをはっても止まりませんでしたが… 実装がおかしい?
```SQL
SELECT
   1 AS [C1],
   [Extent1].[ID] AS [ID],
   [Extent2].[StartYmd] AS [StartYmd],
   [Extent2].[EndYmd] AS [EndYmd]
   FROM [dbo].[MAIN] AS [Extent1]
   LEFT OUTER JOIN [dbo].[AAA] AS [Extent2] ON 1 = 0
```
### 追記:StackOverflowで見つけた内容  
 
http://stackoverflow.com/questions/10642421/using-equal-and-not-equal-in-a-linq-join  
 
> A join clause performs an equijoin. In other words, you can only base matches on the equality of two keys.  
> Other types of comparisons such as "greater than" or "not equals" are not supported.  
 
   
> join節が等価結合を実行します。 言い換えれば、2つのキーが等しいかどうかに基づいて照合を行うことができます。  
> 「より大きい」または「等しくない」などの他のタイプの比較はサポートされていません。  
 
上記の質問内容は `LEFT JOIN AAA ON (AAA.RoleName <> 'Admin')` みたいなのはできないの?という内容で 私の問題とは少し違うのですが… 系統的には似てるかなと。  
 
結局 単純な等価評価しかサポートしていないということでしょうか。  
 
# EntityFramework を使う人は適用期間を見たりするSQLとかって組まないのでしょうか…?  
 
###一応考えた方法
Where 句で見る…? というのを一応考えたのですが、他に方法がないものかと思い質問させて頂きました。
```VBnet
Dim query1 = (
   From m In dbContext.MAIN
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer)
   } Equals New With {
       a.ID,
       a.IsDeleted
   }
   Into _a = Group From a In _a.DefaultIfEmpty()
   Where (a.ID = Nothing OrElse (a.BeginYmd <= m.Ymd AndAlso m.Ymd <= a.EndYmd))
   Select New With {
       .ID      = m.ID,
       .StoreId = a.StoreID,
       .StartYmd = a.StartYmd,
       .EndYmd  = a.EndYmd
   }
)
```
###補足情報(言語/FW/ツール等のバージョンなど)
開発環境等
Windows10
Visual Studio 2013
.NET Framework 4
VB.NET
足りない情報等ありましたらご指摘ください。
御存知の方がいらっしゃいましたらよろしくお願いします。
  • LINQ

    154 questions

    LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

  • VB.NET

    1306 questions

    Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

1 IEquatableを実装してみました

sk_3122

sk_3122 score 1015

2017/02/07 13:05  投稿

LINQ to Entities : LEFT JOIN の結合条件にテーブル同士の大小比較
###前提・実現したいこと
SQL (SQL Server) で書く際、LEFT JOIN の結合条件に **テーブル同士の値で大小比較** を入れているケースがあるのですが、
これを LINQ to Entities (VB.NET) で書きたいです。
```sql
SELECT *
FROM MAIN m
LEFT JOIN AAA a ON (
   a.ID = m.ID
   AND a.IsDeleted = 0
   AND a.BeginYmd <= m.Ymd AND m.Ymd <= a.EndYmd -- ★こういう条件
)
```
###発生している問題
LEFT JOIN の結合条件に「テーブル同士の値で大小比較」を指定する方法が分かりません。
###試したソースコード
以下の書き方だと、★の部分で
> 'Equals' の両辺で、少なくとも 1 つの範囲変数を参照しなければなりません。
> 'Equals' 演算子の一方で 1 つ以上の範囲変数 'm' を参照し、他方で 1 つ以上の範囲変数 'a' を参照する必要があります。
というエラーになります。
```VBnet
Dim query1 = (
   From m In dbContext.MAIN
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer),
       .CheckYmd = True
   } Equals New With {
       a.ID,
       a.IsDeleted,
       .CheckYmd = (a.BeginYmd <= m.Ymd AndAlso m.Ymd <= a.EndYmd)   ← ★ m.*** でコンパイルエラー
   }
   Into _a = Group From a In _a.DefaultIfEmpty()
   Select New With {
       .ID      = m.ID,
       .StoreId = a.StoreID,
       .StartYmd = a.StartYmd,
       .EndYmd  = a.EndYmd
   }
)
```
リテラル値 (IsDeletedの部分) を指定するのと同じよう名前を付けてあげればいけるかと思ったのですが、違うようでした。
検索してみたのですが、解決方法と思われるものを見つけられませんでした。
----
↓ これは通る
```VBnet
   ...
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer),
       .CheckYmd = True
   } Equals New With {
       a.ID,
       a.IsDeleted,
       .CheckYmd = True   ← ★リテラル値なら問題ない
   }
   ...
```
↓ これも通る
```VBnet
   ...
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer),
       .CheckYmd = True
   } Equals New With {
       a.ID,
       a.IsDeleted,
       .CheckYmd = (a.BeginYmd <> "")   ← ★a の値を見るのも問題ない
   }
   ...
```
↓ これは駄目
```VBnet
   ...
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer),
       .CheckYmd = True
   } Equals New With {
       a.ID,
       a.IsDeleted,
       .CheckYmd = (m.Ymd <> "")   ← ★ここで m を見ようとすると駄目
   }
   ...
```
↓ これは駄目
```VBnet
   ...
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer),
       .CheckYmd = (a.Ymd <> "")   ← ★左辺と右辺を入れ替えると、逆に m はOKだが a が駄目になる
   } Equals New With {
       a.ID,
       a.IsDeleted,
       .CheckYmd = True
   }
   ...
```
なんとなく駄目なパターンはわかったのですが、どうすれば目的の条件で抽出できるのかわかりません。
###追記:IEquatable を実装してみた版(うまくいかず)  
 
```VBnet  
Public Class JoinParamMainAndAAA : Implements IEquatable(Of Object)  
   Public Property ID As String = Nothing  
   Public Property StartYmd As String = Nothing  
   Public Property EndYmd As String = Nothing  
   Public Property Ymd As String = Nothing  
   Public Enum TableTypes  
       Main  
       AAA  
   End Enum  
   Public Property TableType As TableTypes  
 
   Public Overloads Function Equals(ByVal obj As Object) As Boolean Implements IEquatable(Of Object).Equals  
       ' 想定している型でなければ抜ける  
       If obj Is Nothing OrElse obj.GetType() IsNot GetType(JoinParamMainAndAAA) Then  
           Return False  
       End If  
       Dim chk = CType(obj, JoinParamMainAndAAA)  
 
       Dim m As JoinParamMainAndAAA = Nothing  
       Dim a As JoinParamMainAndAAA = Nothing  
       Select Case(Me.TableType)  
           Case TableTypes.Main:  
               ' 自分がMainの場合は相手はAAA  
               If chk.TableType = TableTypes.AAA Then  
                   m = Me  
                   a = chk  
               End If  
           Case TableTypes.AAA:  
               ' 自分がAAAの場合は相手はMain  
               If chk.TableType = TableTypes.Main Then  
                   m = chk  
                   a = Me  
               End If  
       End Select  
       If m Is Nothing OrElse a Is Nothing Then Return False  
 
       ' 比較  
       If m.ID = a.ID AndAlso  
          a.StartYmd <= m.Ymd AndAlso m.Ymd <= a.EndYmd Then  
           Return True  
       End If  
 
       Return False  
   End Function  
 
   Public Overrides Function GetHashCode() As Integer  
       Return CType(Me.ID.GetHashCode() ^ Me.Ymd.GetHashCode() ^ Me.StartYmd.GetHashCode() ^ Me.EndYmd.GetHashCode(), Integer)  
   End Function  
End Class  
```  
 
```VBnet  
   ...  
   Group Join a In dbContext.AAA On New JoinParamMainAndAAA With {  
       .TableType = JoinParamMainAndAAA.TableTypes.Main,  
       .ID = m.ID,  
       .Ymd = m.Ymd,  
       .StartYmd = Nothing,  
       .EndYmd = Nothing  
   } Equals New JoinParamMainAndAAA With {  
       .TableType = JoinParamMainAndAAA.TableTypes.AAA,  
       .ID = a.ID,  
       .Ymd = Nothing,  
       .StartYmd = a.StartYmd,  
       .EndYmd = a.EndYmd  
   }  
   ...  
 
   ' 不要な値にもNothingをセットしているのは、そうしないと以下のエラーが出た為  
   ' The type 'TestTest.JoinParamMainAndAAA' appears in two structurally incompatible initializations within a single LINQ to Entities query. A type can be initialized in two places in the same query, but only if the same properties are set in both places and those properties are set in the same order.  
```  
 
実際に発行されたSQLを確認したところ、LEFT JOIN の結合が 1 = 0 となっていました。  
というかEqualsの先頭にブレイクポイントをはっても止まりませんでしたが… 実装がおかしい?  
 
```SQL  
SELECT  
   1 AS [C1],  
   [Extent1].[ID] AS [ID],  
   [Extent2].[StartYmd] AS [StartYmd],  
   [Extent2].[EndYmd] AS [EndYmd]  
   FROM [dbo].[MAIN] AS [Extent1]  
   LEFT OUTER JOIN [dbo].[AAA] AS [Extent2] ON 1 = 0  
```  
 
###一応考えた方法
Where 句で見る…? というのを一応考えたのですが、他に方法がないものかと思い質問させて頂きました。
```VBnet
Dim query1 = (
   From m In dbContext.MAIN
   Group Join a In dbContext.AAA On New With {
       m.ID,
       .IsDeleted = CType(0, Integer)
   } Equals New With {
       a.ID,
       a.IsDeleted
   }
   Into _a = Group From a In _a.DefaultIfEmpty()
   Where (a.ID = Nothing OrElse (a.BeginYmd <= m.Ymd AndAlso m.Ymd <= a.EndYmd))
   Select New With {
       .ID      = m.ID,
       .StoreId = a.StoreID,
       .StartYmd = a.StartYmd,
       .EndYmd  = a.EndYmd
   }
)
```
###補足情報(言語/FW/ツール等のバージョンなど)
開発環境等
Windows10
Visual Studio 2013
.NET Framework 4
VB.NET
足りない情報等ありましたらご指摘ください。
御存知の方がいらっしゃいましたらよろしくお願いします。
  • LINQ

    154 questions

    LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

  • VB.NET

    1306 questions

    Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る