相同的(?)C#和VB.NET LINQ查询返回不同的结果不同、结果、VB、NET

2023-09-03 03:22:34 作者:静待另一片天

大概的东西很容易,但我无法看到它......

我复制在LINQ的MS Access查询。我写在C#中先行先试,因为我preFER C#,然后我把它翻译到VB.Net语法。 据我可以告诉这两个查询应该是相同的,但同时C#的查询返回正确的结果,VB.NET的其中一个返回结果为零。

任何人能看到的差异可能?

C#的查询:

 无功表1 = dc.MainTable.Where(O => o.Year == 423)。.ToList()选择(O =>新建
{
    Key_ID = o.Key_ID.Value,
    CropID = o.CropID.Value,
    组ID = o.GroupID.Value,
    Surface1 = o.Surface1.Value,
    Surface2 = o.Surface2.Value
});

无功表2 = dc.OtherTable.Where(O => o.Year == 423)。.ToList()选择(O =>新建
{
    Key_ID = o.Key_ID.Value,
    CropID = int.Parse(o.SAKU_CD)
    组ID = int.Parse(o.SAN_DAN_NO)
    Surface1 = Convert.ToDouble(o.KEIHAN_MEN.Value)
    Surface2 = Convert.ToDouble(o.SAKU_MEN.Value)
});

无功输出= table1.Join(表2中,t1 =>新建
{
    t1.Key_ID,
    t1.CropID,
    t1.GroupID,
    t1.Surface1,
    t1.Surface2
},
T2 =>新
{
    t2.Key_ID,
    t2.CropID,
    t2.GroupID,
    t2.Surface1,
    t2.Surface2
},(T1,T2)=>新OutputDataType()
{
    Key_ID = t1.Key_ID,
    年= 423
})了ToList()。
 

在VB.NET查询:

 暗淡表1 = MainTable.Where(功能(O)o.Year.Value = 423).ToList(),选择(功能(O)新增功能
{
    .Key_ID = o.Key_ID.Value,
    .CropID = o.CropID.Value,
    .GroupID = o.GroupID.Value,
    .Surface1 = o.Surface1.Value,
    .Surface2 = o.Surface2.Value
})。了ToList()

昏暗的表2 = OtherTable.Where(功能(O)o.Year.Value = 423).ToList(),选择(功能(O)新增功能
{
    .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()

昏暗的输出= table1.Join(表2,功能(T1)新增功能
{
    t1.Key_ID,
    t1.CropID,
    t1.GroupID,
    t1.Surface1,
    t1.Surface2
},功能(T2)新增功能
{
    t2.Key_ID,
    t2.CropID,
    t2.GroupID,
    t2.Surface1,
    t2.Surface2
},功能(T1,T2)新OutputDataType随着{.Key_ID = t1.Key_ID,.Year = 423})。了ToList()
 

在C#和VB.Net 表1 表2 是相同的,所以它一定是加入这将失败。

修改

我只是改变了加入在VB.Net查询语法,像这样的:

 暗淡输出=从T1在MainTable
                 加入T2在OtherTable
                 在t1.Key_ID等于t2.Key_ID而t1.GroupID等于t2.GroupID而t1.CropID等于t2.CropID而t1.Surface1等于t2.Surface1而t1.Surface2等于t2.Surface2
                 选择新OutputDataTypeData随着{.Key_ID = t1.Key_ID,.Year = 423}
 
VB NET

其中给出正确的结果。但我真的不明白这是怎么从扩展的方法不同的加入语法?

解决方案

当您使用的 加入 扩展方法,你提供尽可能 outerKeySelector 键和 innerKeySelector 参数使用等于方法。

相比,

不过,C#和VB.Net手柄的匿名类型不同的位置:

C#

  VAR一个=新{美孚= 1,酒吧= 2};
变种B = {新富= 1,酒吧= 2};
布尔结果= a.Equals(B); // 真正
 

VB.Net

 暗淡=新与{.Foo = 1,.BAR = 2}
昏暗B =新与{.Foo = 1,.BAR = 2}
昏暗的结果= a.Equals(二)假
 

这里发生了什么?

C#使用的的值相等的比较两个对象,比较属性的值。

VB.Net使用的引用相等的比较两个对象,因此结果是

要拥有你的code的工作,你必须明确地告诉VB.Net使用的 关键字:

  

关键特性从非关键性质不同的几个基本方面:

        只有密钥属性的值进行比较,以确定两个实例是否相等。   是只读关键属性的值,并且不能被改变。   在唯一的关键属性值都包含在一个匿名类型编译器生成散列code算法。   

 暗淡=新与{重点.Foo = 1,重点.BAR = 2}
昏暗B =新与{重点.Foo = 1,重点.BAR = 2}
昏暗的结果= a.Equals(二)#真
 

查询语法有效,因为在这种情况下,你是不是比较匿名类型/对象,而只是 INT 秒。

Probably something really easy, but I just can't see it...

I am replicating an MS Access query in LINQ. I wrote it in C# first to test it, because I prefer C#, then I translated it to VB.Net syntax. As far as I can tell the two queries should be identical, but whilst the C# query returns the correct results, the VB.NET one returns zero results.

Can anybody see where the difference might be?

The C# query:

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

The VB.NET query:

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

In both C# and VB.Net table1 and table2 are the same, so it must be the Join which fails.

EDIT

I just changed the Join in VB.Net to query syntax, like this:

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}

Which gives the correct result. But I really don't get how this is different from the extension method Join syntax?

解决方案

When you use the Join extension method, the keys you provide as outerKeySelector and innerKeySelector arguments are compared using the Equals method.

But C# and VB.Net handle anonymous types differently here:

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 '

What's happening here?

C# uses value equality to compare the two objects, comparing the values of the properties.

VB.Net uses reference equality to compare the two objects, hence the result is False.

To have your code work, you have to explicitly tell VB.Net to compare the properties using the Key keyword:

Key properties differ from non-key properties in several fundamental ways:

Only the values of key properties are compared in order to determine whether two instances are equal. The values of key properties are read-only and cannot be changed. Only key property values are included in the compiler-generated hash code algorithm for an anonymous type.

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

The query syntax works because in this case you are not comparing the anonymous types/objects but simply ints and doubles.

 
精彩推荐
图片推荐