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?
The ~ operator in C++ (and other C-like languages like C and Java) performs a bitwise NOT operation - all the 1 bits in the operand are set to 0 and all the 0 bits in the operand are set to 1. In other words, it creates the complement of the original number.
%d. a decimal integer (assumes base 10) %i. a decimal integer (detects the base automatically)
C++ is a superset of C, so both languages have similar syntax, code structure, and compilation. Almost all of C's keywords and operators are used in C++ and do the same thing. C and C++ both use the top-down execution flow and allow procedural and functional programming.
The question mark operator, ?:, is also found in C++. Some people call it the ternary operator because it is the only operator in C++ (and Java) that takes three operands. If you are not familiar with it, it's works like an if-else, but combines operators.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With