2013-02-18 5 views
9

おそらく何か本当に簡単に異なる結果を返すが、私はLINQでのMS Accessクエリを複製しています同じ(?)C#とVB.NET LINQクエリは

私はちょうど...それを見ることができません。私はC#を好むので、最初にC#でテストしました。そして、VB.Netの構文に変換しました。 2つのクエリは同一でなければならないが、C#クエリが正しい結果を返す限り、VB.NETの結果はゼロの結果を返します。

どこに違いがあるのでしょうか。

C#のクエリ:

var table1 = dc.MainTable.Where(o => o.Year == 423).ToList().Select(o => new 
{ 
    Key_ID = o.Key_ID.Value, 
    CropID = o.CropID.Value, 
    GroupID = o.GroupID.Value, 
    Surface1 = o.Surface1.Value, 
    Surface2 = o.Surface2.Value 
}); 

var table2 = dc.OtherTable.Where(o => o.Year == 423).ToList().Select(o => new 
{ 
    Key_ID = o.Key_ID.Value, 
    CropID = int.Parse(o.SAKU_CD), 
    GroupID = int.Parse(o.SAN_DAN_NO), 
    Surface1 = Convert.ToDouble(o.KEIHAN_MEN.Value), 
    Surface2 = Convert.ToDouble(o.SAKU_MEN.Value) 
}); 

var output = table1.Join(table2, t1 => new 
{ 
    t1.Key_ID, 
    t1.CropID, 
    t1.GroupID, 
    t1.Surface1, 
    t1.Surface2 
}, 
t2 => new 
{ 
    t2.Key_ID, 
    t2.CropID, 
    t2.GroupID, 
    t2.Surface1, 
    t2.Surface2 
}, (t1, t2) => new OutputDataType() 
{ 
    Key_ID = t1.Key_ID, 
    Year = 423 
}).ToList(); 

VB.NETクエリ:それは失敗Joinなければならないので、C#とVB.Net table1table2両方において

Dim table1 = MainTable.Where(Function(o) o.Year.Value = 423).ToList().Select(Function(o) New With 
{ 
    .Key_ID = o.Key_ID.Value, 
    .CropID = o.CropID.Value, 
    .GroupID = o.GroupID.Value, 
    .Surface1 = o.Surface1.Value, 
    .Surface2 = o.Surface2.Value 
}).ToList() 

Dim table2 = OtherTable.Where(Function(o) o.Year.Value = 423).ToList().Select(Function(o) New With 
{ 
    .Key_ID = o.Key_ID.Value, 
    .CropID = Convert.ToInt32(o.SAKU_CD), 
    .GroupID = Convert.ToInt32(o.SAN_DAN_NO), 
    .Surface1 = Convert.ToDouble(o.KEIHAN_MEN.Value), 
    .Surface2 = Convert.ToDouble(o.SAKU_MEN.Value) 
}).ToList() 

Dim output = table1.Join(table2, Function(t1) New With 
{ 
    t1.Key_ID, 
    t1.CropID, 
    t1.GroupID, 
    t1.Surface1, 
    t1.Surface2 
}, Function(t2) New With 
{ 
    t2.Key_ID, 
    t2.CropID, 
    t2.GroupID, 
    t2.Surface1, 
    t2.Surface2 
}, Function(t1, t2) New OutputDataType With {.Key_ID = t1.Key_ID, .Year = 423}).ToList() 

は、同じです。

EDIT

は、私はちょうどこのように、構文を照会するためにVB.NetでJoinを変更:正しい結果を与える

Dim output = From t1 In MainTable 
       Join t2 In OtherTable 
       On t1.Key_ID Equals t2.Key_ID And t1.GroupID Equals t2.GroupID And t1.CropID Equals t2.CropID And t1.Surface1 Equals t2.Surface1 And t1.Surface2 Equals t2.Surface2 
       Select New OutputDataTypeData With {.Key_ID = t1.Key_ID, .Year = 423} 

を。しかし、私は実際にこれが拡張メソッドJoinの構文とどのように違うのか分からないのですか?

答えて

10

Join拡張メソッドを使用する場合、outerKeySelectorinnerKeySelector引数として指定するキーは、Equalsメソッドを使用して比較されます。

しかし、C#とVB.Netは異なり、ここで匿名型扱う:

C#

var a = new {Foo = 1, Bar = 2 }; 
var b = new {Foo = 1, Bar = 2 }; 
bool result = a.Equals(b); // true 

をVB.Net

Dim a = new with {.Foo = 1, .Bar = 2} 
Dim b = new with {.Foo = 1, .Bar = 2} 
Dim result = a.Equals(b) ' False ' 

ここで何が起こっていますか?

C#は、値同値を使用して、2つのオブジェクトを比較し、プロパティの値を比較します。

VB.Netは、参照equalityを使用して2つのオブジェクトを比較するため、結果はFalseです。

キープロパティは、いくつかの基本的な方法で非キープロパティとは異なります:

    は、明示的Keyキーワードを使用してプロパティを比較するためにVB.Netを伝える必要があり、あなたのコードの仕事を持っているために、

  • 2つのインスタンスが等しいかどうかを判断するために、キーのプロパティの値のみが比較されます。
  • キープロパティの値は読み取り専用であり、変更することはできません。
  • 匿名型のコンパイラ生成ハッシュコードアルゴリズムには、主要なプロパティ値のみが含まれています。
Dim a = new with {Key .Foo = 1, Key .Bar = 2} 
Dim b = new with {Key .Foo = 1, Key .Bar = 2} 
Dim result = a.Equals(b) # True 

この場合には、あなたが匿名型/オブジェクトを比較するが、単にint sおよびdouble秒されていないため、クエリ構文は動作します。

+2

ありがとうございます!私はすでに以前の 'Key'キーワードでキャッチした。私はあなたの説明を印刷してそれを私のPCに貼りつけるつもりだと思うので、もうこれを忘れないでください。本当にありがとう! –