Reputation: 177
I probably could have worded the title better, but I'm venturing into areas of programming that I've never been to before, so I'm still learning the terminology. But here's what I'm trying to do:
I'm writing a program that can perform structural analyses on bolted joints. However, rather than have the user enter the bolt geometry every single time, I'd like to give them an option to select from a standard list of ASME Unified Thread Standard (UTS) sizes. So I've created a Bolt class and then a UTSBolt subclass. And I'm making an XML file for UTS bolt sizes. And so far, I can de-serialize the XML file, project it to an IEnumerable of my UTSBolts class, let the user select a bolt, and everything is hunky-dory.
But here's my problem...
UTS sizes will specify a bolt's diameter as well as it's thread density for both a coarse-thread (UNC) and a fine-thread (UNF) bolt. As such, I've formatted my XML file like this:
<Bolts_UTS>
<Bolt>
<Size>#0</Size>
<MajorDiameter>0.0600</MajorDiameter>
<ThreadDensity Series="UNF">80</ThreadDensity>
</Bolt>
<Bolt>
<Size>#1</Size>
<MajorDiameter>0.0730</MajorDiameter>
<ThreadDensity Series="UNC">64</ThreadDensity>
<ThreadDensity Series="UNF">72</ThreadDensity>
</Bolt>
<Bolt>
<Size>#2</Size>
<MajorDiameter>0.0860</MajorDiameter>
<ThreadDensity Series="UNC">56</ThreadDensity>
<ThreadDensity Series="UNF">64</ThreadDensity>
</Bolt>
<Bolt>
<Size>#3</Size>
<MajorDiameter>0.0990</MajorDiameter>
<ThreadDensity Series="UNC">48</ThreadDensity>
<ThreadDensity Series="UNF">56</ThreadDensity>
</Bolt>
<Bolt>
<Size>#4</Size>
<MajorDiameter>0.1120</MajorDiameter>
<ThreadDensity Series="UNC">40</ThreadDensity>
<ThreadDensity Series="UNF">48</ThreadDensity>
</Bolt>
</Bolts_UTS>
When the user selects a bolt size, I'd like them to be able to select a thread series (UNC/UNF) as well. But I can't seem to figure out how to properly set the filters to read in only ThreadDensity where the Series attribute is "UNF". My program always grabs the first ThreadDensity value, regardless of the attribute.
Can somebody please help me figure out what I'm doing wrong? Here's my code:
static void Main(string[] args)
{
string pathCurrent = Directory.GetCurrentDirectory();
string pathToXML = Path.GetFullPath(Path.Combine(pathCurrent, "Bolts_UTS.xml"));
XElement boltsUTS = XElement.Load(pathToXML);
IEnumerable<UTSBolt> boltList =
from el in boltsUTS.Elements("Bolt")
where (
from thread in el.Elements("ThreadDensity")
where
(string)thread.Attribute("Series") == "UNF"
select thread).Any() &&
((string)el.Element("Size") == "#1")
select new UTSBolt(
(string)el.Element("Size"),
(double)el.Element("MajorDiameter"),
(double)el.Element("ThreadDensity")
);
Console.WriteLine(" | Major |");
Console.WriteLine("UN Size\t| Dia. (inch) | Thr. / In.");
Console.WriteLine("--------|-------------|------------");
foreach (UTSBolt bolt in boltList)
Console.WriteLine(bolt);
Console.ReadLine();
}
Output:
| Major |
UN Size | Dia. (inch) | Thr. / In.
--------|-------------|------------
#1 | 0.07300 | 64
Upvotes: 3
Views: 89
Reputation: 1500903
You're only looking at the Series
attribute in this subquery:
where (
from thread in el.Elements("ThreadDensity")
where
(string)thread.Attribute("Series") == "UNF"
select thread).Any() &&
((string)el.Element("Size") == "#1")
That just checks whether any ThreadDensity
element within el
has the right series.
The code where you're actually creating the UTSBolt
just gets the first ThreadDensity
element:
select new UTSBolt(
(string)el.Element("Size"),
(double)el.Element("MajorDiameter"),
(double)el.Element("ThreadDensity")
);
I suspect you want something like:
var boltList =
from el in boltsUTS.Elements("Bolt")
let thread = el.Elements("ThreadDensity")
.FirstOrDefault(t => (string) t.Attribute("Series") == "UNF")
let size = (string) el.Element("Size")
where thread != null && size == "#1"
select new UTSBolt(size, (double) el.Element("MajorDiameter"), (double) thread);
Upvotes: 3