views:

46

answers:

4

Is it possible to merge the below linq query into one query?

var checkBoxes = from x in FindAll<CheckBox>()
                 where x.Checked
                 select new
                 {
                     RecordType = Type.GetType(x.Attributes["RecordType"]),
                     RecordId = Int32.Parse(x.Attributes["RecordId"])
                 };

checkBoxes = from x in checkBoxes
             where x.RecordType != typeof(DomainModel.Group)
             select x;
+5  A: 
var checkBoxes = from x in FindAll<CheckBox>()
                 let recordType = Type.GetType(x.Attributes["RecordType"])
                 where x.Checked && recordType != typeof(DomainModel.Group)
                 select new
                 {
                     RecordType = recordType,
                     RecordId = Int32.Parse(x.Attributes["RecordId"])
                 };
lasseespeholt
Ah. Of course :) Thank you for a quick response!
asgerhallas
It will be accepted in 8 minutes.
asgerhallas
+1 using let keyword is a good idea. btw can we use some method like "let" keyword in generic linq expressions? see my answer.
Danny Chen
@Danny Yes, you can just include it in a select. Ex Enumerable.Range(1,10).Select(i => new { i, d = i * 2 }).Where(x => x.d == something).Select(x => x.i); Where d is what I could put in a "let". (This is a very simplified example)
lasseespeholt
Now there are two very acceptable answers. I mark this one for being first... I hope it isn't against the SO ethicetta and that everybody finds it fair :)
asgerhallas
A: 
var checkboxes = FindAll<CheckBox>()
                  .Where(x => x.Checked && Type.GetType(x.Attributes["RecordType"]) != typeof(DomainModel.Group))
                  .Select(new{
                          RecordType = Type.GetType(x.Attributes["RecordType"]),
                          RecordId = Int32.Parse(x.Attributes["RecordId"])
                  });
Danny Chen
+3  A: 

lasseespeholt's answer is perfectly good (preferable, even - there's no point in doing a projection if you're going to throw away the result), but if you want to apply this more generally, you can use a query continuation:

var checkBoxes = from x in FindAll<CheckBox>()
                 where x.Checked
                 select new
                 {
                     RecordType = Type.GetType(x.Attributes["RecordType"]),
                     RecordId = Int32.Parse(x.Attributes["RecordId"])
                 } into y
                 where y.RecordType != typeof(DomainModel.Group)
                 select y;

Here I've changed the second variable from x to y to make it clear that it's distinct from the original x, but you don't have to do that.

Another alternative which avoids calling Type.GetType twice but still putting the where clause before the final projection is to use a let clause (which introduces another projection itself, admittedly):

var checkBoxes = from x in FindAll<CheckBox>()
                 where x.Checked
                 let t = Type.GetType(x.Attributes["RecordType]")
                 where t != typeof(DomainModel.Group)
                 select new
                 {
                     RecordType = t
                     RecordId = Int32.Parse(x.Attributes["RecordId"])
                 };
Jon Skeet
+1 For "select ... into ...". Personally, I think it is prettier to not have "let"´s inside "where" clauses.
lasseespeholt
@lasseespeholt: It's note really "inside" the where clause - there are two where clauses and a let clause, all independent.
Jon Skeet
Sorry for my improper english. I meant inside = between :)
lasseespeholt
Very nice. I learned a lot from this. Thank you.
asgerhallas
I marked lasseespeholt's answers as accepted, but +1 and thanks for the very good elaboration on the subject!
asgerhallas
@lasseespeholt: Okay... you could put the `let` before a compound `where` of course - but that would mean more calls to `Type.GetType`.
Jon Skeet
A: 

Why would you want to change into one linq query? Linq uses deferred execution and will only execute when you actually use the output somewhere. In the mean time in keeps building up the expression tree. What you have is perfectly readable. I would only change it if you think it makes it more readable.

uriDium