0

I'm converting the Linq query below from C# to VB.Net. Can you spot my error? The query joins 3 XML datasets. Thanks in advance!

C# - This one works great.

List<Course> courses =
  (from course in CourseXML.Descendants(ns + "row")
  join coursecategory in CourseCategoryXML.Descendants("Table") on (string)course.Attribute("code") equals (string)coursecategory.Element("DATA")
  join category in CategoryXML.Descendants("Table") on (string)coursecategory.Element("GRP") equals (string)category.Element("GRP")
  where (string)coursecategory.Element("RECTYPE") == "C"
  select new Course {
    CategoryCode = category.Element("GRP").Value,
      Code = course.Attribute("code").Value
  }).ToList<Course>();

VB - I'm getting no results from this, so I suspect I'm either casting improperly or joining improperly.

Dim result = (From course In CourseXML.Descendants(ns + "row") _
Join coursecategory In CourseCategoryXML.Descendants("Table") On CType(course.Attribute("code"), String) Equals CType(coursecategory.Element("DATA"), String) _
Join category In CategoryXML.Descendants("Table") On CType(coursecategory.Element("GRP"), String) Equals CType(category.Element("GRP"), String) _
Where CType(coursecategory.Element("RECTYPE"), String) = "C" _
Select New Course() With _ 
{ _
  .CategoryCode = category.Element("GRP").Value, _
  .Code = course.Attribute("code").Value _
}).ToList()
6
  • What does the object initialization code look like? Perhaps the error is in there... Commented Dec 1, 2009 at 1:56
  • "The query joins 3 XML datasets" ... Descendents is not a member of DataSet or XmlDataDocument, it's on XDocument however, so I guess you must be using XDocument? Commented Dec 1, 2009 at 2:21
  • Good point Andrew - I added it. Commented Dec 1, 2009 at 2:22
  • @ Richard - Yes, that's correct. Using XDocument. Commented Dec 1, 2009 at 2:24
  • 1
    Can you post some examples of the xml files? Commented Dec 1, 2009 at 4:54

2 Answers 2

1

I used the following site to convert: http://www.developerfusion.com/tools/convert/csharp-to-vb/

Dim courses As List(Of Course) = (From course In CourseXML.Descendants(ns & "row") _
    Join coursecategory In CourseCategoryXML.Descendants("Table") On DirectCast(course.Attribute("code"), String) = DirectCast(coursecategory.Element("DATA"), String) _
    Join category In CategoryXML.Descendants("Table") On DirectCast(coursecategory.Element("GRP"), String) = DirectCast(category.Element("GRP"), String) _
    Where DirectCast(coursecategory.Element("RECTYPE"), String) = "C" _
    Select New Course()).ToList(Of Course)()

The main difference is the last Select.

Sign up to request clarification or add additional context in comments.

1 Comment

I actually used the same site for the initial conversion. Very handy. However, the current tool doesn't deal well with LINQ yet. But +1 since this is certainly a relevant site for others.
0

You are getting different results because of the casts.

coursecategory.Element("RECTYPE").Value returns a different result than
(string)coursecategory.Element("RECTYPE") == "C" (and obviously CType(coursecategory.Element("RECTYPE"), String) = "C").

If one of your elements is missing a child RECTYPE node, you will not have any results if you properly cast it, which you did in VB.NET.

In C# you didn't cast (string)coursecategory.Element("RECTYPE") == "C" right. If you use ToString() or .Value you would get the correct results.

Use coursecategory.Element("RECTYPE").Value instead, and avoid the casts altogether.

You could test this by changing your select to return:

select new { 
Wrong = (string)coursecategory.Element("RECTYPE"),  // No exception ... incorrect result!
//Maybe = coursecategory.Element("RECTYPE").ToString() //throws NullReferenceException
//Right = (string)coursecategory.Element("RECTYPE").Value // throws NullReferenceException because of a missing element.
CategoryCode = category.Element("GRP").Value,      
Code = course.Attribute("code").Value

});

4 Comments

XElement has static explicit operator string(XElement) defined in it, so (string)Element("Foo") is exactly equivalent to Element("Foo").ToString(), except that the former won't throw on null.
... sorry, equivalent to Element().Value.
"(string)Element("Foo") is exactly equivalent to Element("Foo").ToString(), except that the former won't throw on null", so therefore they are not exactly equivalent and you've proven my point.
Thanks for the reply Richard, I actually found my call to the method this Linq query is in was bogus so the issue wasn't even with the query itself. However, regarding throwing an exception, I'd actually prefer the joins operate like an inner join. So which solution are you suggesting in that case?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.