大概的东西很容易,但我无法看到它......
我复制在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}
其中给出正确的结果。但我真的不明白这是怎么从扩展的方法不同的加入
语法?
当您使用的 加入
扩展方法,你提供尽可能 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 int
s and double
s.