mngeek206
mngeek206

Reputation: 5177

C# LINQ: Efficient way to set anonymous type property based on other values in query?

// The "myData" table contains two fields: name, value and type.
// The "myInfo" table contains two fields: type and value.

var myQuery = from x in myData
    select new {
        name = x.name,
        value = x.value,
        minValue = myInfo.Where(y => x.type == y.type).OrderBy(y => y.value).FirstOrDefault().value,
        isOverMinValue = (myInfo.Where(y => x.type == y.type).OrderBy(y => y.value).FirstOrDefault().value) > x.value ? true : false
    };

The myInfo table might contain multiple records matching the type from myData; I only want the minimum value. Then I want the isOverMinValue field to indicate whether the value in myData is greater than the minimum value found in myInfo.

In this example, it works, but as you can see I have to repeat the entire subquery twice. This can't be efficient. The alternative approach I had was:

var myQuery = from x in myData
    select new {
        name = x.name,
        value = x.value,
        minValue = myInfo.Where(y => x.type == y.type).OrderBy(y => y.value).FirstOrDefault().value,
        isOverMinValue = false
    };

foreach (var myRec in myQuery)
{
    if (myRec.minValue < x.Value) myRec.isOverMinValue = true;
}

This however won't work because it seems the properties on anonymous types are read-only.

Is there a more efficient way to do this?

(I can't do a join because like I said myInfo might contain multiple entries, and doing a normal LINQ join will end up producing many records based on how many matches are found in myInfo.)

Upvotes: 1

Views: 410

Answers (1)

Gert Arnold
Gert Arnold

Reputation: 109271

You can use the let keyword:

var myQuery = from x in myData
    let minvalue = myInfo.Where(y => x.type == y.type)
                         .OrderBy(y => y.value).FirstOrDefault().value
    select new {
        name = x.name,
        value = x.value,
        minValue = minvalue,
        isOverMinValue = minvalue > x.value
    };

By the way, I'm not sure if you've got the > sign right.

Upvotes: 4

Related Questions