Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine two LINQ queries from different sources into single object

Tags:

c#

linq

I am gathering data from two different sources with the intention of populating a single object. My class is

public class SampleClient
{
    public string ClientId { get; set; }
    public string JobName { get; set; }
    public string JobUrl { get; set; }
    public string Version { get; set; }
}

The first LINQ query populates a collection of SampleClient objects obtaining values for all except Version. I then need to loop through the collection of SampleClient and utilize ClientId value in the second query. The result of the second query is the Version value. Here is my first LINQ query:

    private void btnProjects_Click(object sender, EventArgs e)
    {
        string[] stringArray = { "demo", "sample", "test", "training" };
        List<SampleClient> jobList =
        (
            from x in XDocument.Load(XML URL VALUE HERE).Root.Elements("job")
            where x.Element("name").Value.Contains("-config") && x.Element("name").Value.StartsWith("oba-")
            && (!stringArray.Any(s => x.Element("name").Value.Contains(s)))
            select new SampleClient
            {
                ClientId = getClientId((string)x.Element("name")),
                JobName = (string)x.Element("name"),
                JobUrl = (string)x.Element("url"),
            }).ToList();

        foreach (SampleClient job in jobList)
        {
            //Display the results in a textbox
            txtResults.Text += "Job Name = " + job.JobName + " | Job URL = " + job.JobUrl + " | ";
        }
    }

In the query that obtains the version, I currently have:

var version = from item in doc.Descendants(ns + "properties")
select new SampleClient
{
    ClientId = strClientId,
    Version = (string)item.Element(ns + "product.version").Value
};

It is important to note that the URL source used in the second query is created using the ClientId that was obtained from the first. I could have a routine loop through and cleanup / merge objects, but this feels like a hack. Is there a cleaner way of handling this?

This is a sample of the XML from the first query:

<?xml version="1.0"?>
<allView>
    <description>PROD</description>
    <job>
        <name>abc</name>
        <url>http://ci-client.company.net/job/abc/</url>
        <color>blue</color>
    </job>
    <job>
        <name>acme</name>
        <url>http://ci-client.company.net/job/acme/</url>
        <color>blue</color>
    </job>
</allView>

The second query URL is dynamically created by using the clientID from the results of the first. I am using this to load in a Maven POM file and grab version information. Here is a snippet of the XML from the POM file.

<?xml version="1.0" encoding="UTF-8" ?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion> 
    <groupId>com.company.xyz</groupId> 
    <artifactId>io</artifactId> 
    <version>6.11.7-ACME-SNAPSHOT</version> 
    <packaging>pom</packaging> 
    <properties>
        <product.version>6.11.7</product.version> 
        <db.version>1.4</db.version> 
    </properties>
    <modules>
        <module>policies</module> 
        <module>templates</module> 
        <module>assemble</module> 
    </modules>
</project>
like image 849
Todd Zetlan Avatar asked Oct 07 '22 00:10

Todd Zetlan


1 Answers

I hope I understand your question..

This will merge them together (although, my test data only had ClientId, JobName and Version..). Query 1 contains ClientId and JobName, Query2 contains ClientId and Version.

IList<SampleClient> mergedList = firstQuery.Concat(secondQuery)
    .ToLookup(x => x.ClientId)
    .Select(x => x.Aggregate((query1, query2) => 
            new SampleClient() { 
                    ClientId = query1.ClientId, 
                    JobName = query1.JobName,
                    Version = query2.Version 
                }
            )
    ).ToList();

..possibly not as efficient as your manual method.. however I have nothing to benchmark against..

like image 96
Simon Whitehead Avatar answered Oct 10 '22 02:10

Simon Whitehead