2013-02-18 159 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

相关问题