2013-02-18 193 views
9

大概的東西很容易,但我看不出它......相同(?)C#和VB.NET LINQ查詢返回不同的結果

我複製在LINQ的MS Access查詢。我首先用C#編寫它來測試它,因爲我更喜歡C#,然後將它轉換爲VB.Net語法。 據我可以告訴兩個查詢應該是相同的,但雖然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查詢:

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() 

在C#和VB.Net table1table2是相同的,所以它必須是失敗Join

編輯

我只是在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#使用值相等來比較兩個對象,比較屬性的值。

VB.Net使用參考相等來比較這兩個對象,因此結果是False

爲了使您的代碼的工作,你必須明確地告訴VB.Net使用Key關鍵字進行比較的屬性:

主要特性與非關鍵屬性不同幾種基本方法:

  • 只有比較關鍵屬性的值才能確定兩個實例是否相等。
  • 關鍵屬性的值是隻讀的,不能更改。
  • 只有關鍵屬性值包含在匿名類型的編譯器生成的散列碼算法中。
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'關鍵字抓住了。我想我會打印出你的解釋並貼到我的電腦上,這樣我就不會再忘記這件事了。非常感謝! – 2013-02-18 09:06:22

相關問題