2013-02-18 61 views
9

Có lẽ một cái gì đó thực sự dễ dàng, nhưng tôi chỉ không thể nhìn thấy nó ...giống hệt (?) C# và VB.NET LINQ truy vấn trả lại kết quả khác nhau

Tôi tái tạo một truy vấn MS Access trong LINQ. Tôi đã viết nó trong C# đầu tiên để kiểm tra nó, bởi vì tôi thích C#, sau đó tôi dịch nó sang cú pháp VB.Net. Theo như tôi có thể nói hai truy vấn phải giống hệt nhau, nhưng trong khi truy vấn C# trả lại kết quả chính xác, thì VB.NET trả về kết quả bằng không.

Ai có thể biết sự khác biệt có thể là ở đâu?

C# truy vấn:

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

Truy vấn 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() 

Trong cả hai C# và VB.Net table1table2 đều giống nhau, vì vậy nó phải là Join mà thất bại .

EDIT

Tôi chỉ thay đổi Join trong VB.Net để truy vấn cú pháp như sau:

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} 

Mà cho kết quả chính xác. Nhưng tôi thực sự không nhận được làm thế nào điều này là khác nhau từ các phương pháp mở rộng cú pháp Join?

Trả lời

10

Khi bạn sử dụng phương pháp mở rộng Join, các khóa bạn cung cấp dưới dạng các đối số outerKeySelectorinnerKeySelector được so sánh bằng phương pháp Equals.

Nhưng C# và VB.Net xử lý kiểu nặc danh khác nhau ở đây:

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 ' 

gì đang xảy ra ở đây?

C# sử dụng giá trị bình đẳng để so sánh hai đối tượng, so sánh giá trị của thuộc tính.

VB.Net sử dụng tham chiếu bình đẳng để so sánh hai đối tượng, do đó kết quả là False.

Để có công việc mã của bạn, bạn phải nói rõ ràng VB.Net để so sánh các thuộc tính bằng cách sử dụng Key keyword:

tính chính khác với tính chất phi chính trong một số cách cơ bản:

  • Chỉ các giá trị của thuộc tính khóa được so sánh để xác định xem hai trường hợp có bằng nhau hay không.
  • Giá trị của thuộc tính khóa là chỉ đọc và không thể thay đổi.
  • Chỉ các giá trị thuộc tính khóa mới được bao gồm trong thuật toán mã băm do trình biên dịch tạo ra cho một loại ẩn danh.
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 

Truy vấn công trình cú pháp vì trong trường hợp này bạn không phải so sánh các loại vô danh/đối tượng mà chỉ đơn giản int s và double s.

+2

Cảm ơn !! Tôi đã bị bắt bởi từ khóa 'Key' trước đây. Tôi nghĩ rằng tôi sẽ in ra lời giải thích của bạn và dán nó vào máy tính của tôi, vì vậy tôi không quên điều này nữa. Cám ơn rất nhiều! –

Các vấn đề liên quan