In Linq, is a SELECT required when WHERE is used? - c#

If you have a Linq statement that uses a WHERE clause, for example:
var result = someCollection.Where(x => x.value > 5).Select(x => x);
Is the SELECT required, or is it redundant? It appears that I can safely omit the SELECT if I'm not trying to get at an object property, but am not sure if this is proper...

In your case No, it is not required, since you are selecting the object. So you can have:
var result = someCollection.Where(x => x.value > 5);
as far as better practice is concerned, I would remove the redundant code.
But, if you are going to select a specific property then that could be useful, like:
var result = someCollection.Where(x => x.value > 5)
.Select(x=> x.SomeSpecificProperty);
One more thing to add, with query expression you will need the select.
var result = from x in someCollection
where x.Value > 5
select x;
but at compile time the above query expression will be converted to Method Expression, without Select.

It's redundant. Select is more like the functional map (see JavaScript, Haskell, Ruby). If you aren't going to transform the input object into a different form than it is currently in, there's no need to use Select.

In Linq, is a SELECT required when WHERE is used?
No, it isnt.

No... is not necessary this time... may be if you want to select a new object different than "someCollection" it will be necessary
something like:
var result = someCollection.Where(x => x.value > 5).Select(x => new ObjName() { name = x.name, lastname = x.lastname });

Related

method syntax for linq query with multiple from clauses

I was trying to figure out how to replace the nested from clause to a method syntax. I was trying with .Select or .SelectMany, but I didn't manage to get the same result.
var query = (from DirectToStoreStore s in dtsOrder.Stores
from DirectToStoreProduct p in s.Products
where p.DirectToStoreOrderLineID == directToOrderLineID
select p);
There's plenty of ways you could write it.
var query = dtsOrder.Stores.Cast<DirectToStoreStore>()
.SelectMany(s => s.Products.Cast<DirectToStoreProduct>()
.Where(p => p.DirectToStoreOrderLineID == directToOrderLineID)
);
Though the casts may not be necessary, but they're only there since you explicitly declared them in your query. It'll probably be safe to remove them.

Why is LINQ not letting me OrderBy one of my data points?

I have this code:
return inventoryItems
.Where(i => 0 < String.Compare(i.ID, ID))
.Take(CountToFetch);
...but I want to order the results, like so:
return inventoryItems
.Where(i => 0 < String.Compare(i.ID, ID))
.Take(CountToFetch)
.OrderBy(i.pksize);
...however, the final i is red/out of scope. Why? Trying to position the OrderBy() prior to the Take() makes no difference.
return inventoryItems.Where(i => 0 < String.Compare(i.ID, ID))
.Take(CountToFetch)
.OrderBy(i => i.pksize);
And maybe you should change OrderBy and Take order to make results predictable:
return inventoryItems.Where(i => 0 < String.Compare(i.ID, ID))
.OrderBy(i => i.pksize)
.Take(CountToFetch);
There's no i in the OrderBy.
You want OrderBy(i => i.pksize) (or indeed x => x.pksize, whatever => whatever.pksize, etc.)
The sort of syntax that allows from x in something where x.IsOkay orderby x.Priority etc. uses the same variable label all the way through, but it gets turned into more than one lambda expression, which are each separate from each other. (something.Where(x => x.IsOkay).OrderBy(x => x.Priority), but they need to each be full expressions.
It looks like you've tried to use the i you declared in Where. If you look closely at the brackets, you should see that it is actually no longer in scope within the OrderBy. So the first problem is you're trying to use an out-of-scope variable.
OrderBy actually needs to be able to check the property on each element in the IEnumerable, so it doesn't make sense to only pass it the value of one element's property. It needs to know how to get the property for each element, which is why you typically pass in a lambda expression, anonymous delegate or method.
As the others pointed out, you can solve the problem by using an lambda expression like you did in Where:
.OrderBy(i => i.pksize)

and operator in Linq and select distinct values using linq

I am new to .net. I have a form in which there are two comboboxes cbProduct and cbBrandName and also a label lblPrice.
I am trying to implement the below code but it is showing blue scribbles to &&.
(Error: operator '&&' cannot be applied to operands of type 'lambda expression' and 'lambda expression')
I tried the below code: (not working)
lblPrice.Text = string.Empty;
lblPrice.Text = doc.Descendants("items"
).Where((x => x.Element("productname"
).Value.Equals(cbProduct.SelectedItem.ToString())) && /*blue scribbles to '&&'*/
(y => y.Element("brandname").Value.Equals(cbBrandName.SelectedItem.ToString()
))).Select(k => k.Element("price"
).Value).ToString();
My other question is that i want to make the selected values of cbProduct as distinct. The below code takes all the values instead of distinct values:
cbProduct.Items.AddRange(doc.Descendants("items"
).Select(x => x.Element("productname").Value
).ToArray<string>());//adds all products
cbProduct.SelectedIndex = 0;
giving any one answer is ok
Please assist me
Thanks in advance
It looks like you are passing 2 lambdas to the Where function and trying to logical-and (&&) them together. You can't do that. The && has to occur inside the Where lambda. Or you can chain 2 Where functions together. Something like this:
lblPrice.Text = doc.Descendants("items")
.Where(x => x.Element("productname").Value.Equals(cbProduct.SelectedItem.ToString()) &&
x.Element("brandname").Value.Equals(cbBrandName.SelectedItem.ToString()))
.Select(k => k.Element("price").Value).ToString();
The other issue I see is you are ending your query with a select, but never actually enumerating it. You probably want to do something like this:
lblPrice.Text = doc.Descendants("items")
.Where(x => x.Element("productname").Value.Equals(cbProduct.SelectedItem.ToString()) &&
x.Element("brandname").Value.Equals(cbBrandName.SelectedItem.ToString()))
.Select(k => k.Element("price").Value)
.FirstOrDefault();
Which will return the string you are looking for, or null if nothing exists (so you probably want to skip the final .ToString() call in this case, since you are already returning a string from Select and .ToString() on a null will throw an exception).
For the first question, it looks like you just want to select the one price. This code will work, assuming that the item is found by the .Single(). It will throw otherwise, in which case you should use .SingleOrDefault() and check for null on the found item.
lblPrice.Text =
doc.Descendants("items")
.Single(x => x.Element("productname").Value == cbProduct.SelectedItem.ToString() &&
x.Element("brandname").Value == cbBrandName.SelectedItem.ToString())
.Element("price").Value;
For the second question, you need to close off your .Select with a bracket, then you can call .Distinct() and .ToArray() to filter to distincts and project the result to string[]. I've also thrown an .OrderBy() in there, as there's nothing more annoying than a ComboBox in a random order. Try this:
cbProduct.Items.AddRange(doc.Descendants("items")
.Select(item => item.Element("productname").Value)
.Distinct()
.OrderBy(item => item)
.ToArray());

Need help to use Expression Tree to build a LINQ query

I need to build an epression tree for a LINQ query that looks something like this:
collection.OrderBy(e => ((MyObject)e["PropertyIndex"]).dictionary.Where(k => k.Key == "keyName").Select(k => k.Value).Single());
I looked at this link that explains how to chain OrderBy methods. I don't know how do I add Where inside OrderBy using Expression Tree.
Update:
I need to sort data in memory dynamically. So the linq query could look something like this:
collection.OrederBy(field1).ThenByDescending(field2).ThenBy(field3)
I know only at runtime how many fields I need to sort by.
Any of fieldX can be a complex object. The type of the object of course will be known at runtime. One of the object has a structure like you see in the LINQ query above. It has a dictionary and I have to sort for a specific key. In my case dictionary contains localized data like:
{{"en-US", "word (en)"}, {"es-ES", "word (es)"} , ....}
I need to sort by specific language.
It appears your query is doing this:
from k in collection
where k.Key == "keyName"
orderby ((MyObject)k)["PropertyIndex"]
select k.Value
and you could add more where clauses like this:
from k in collection
where k.Key == "keyName"
&& k.OtherProperty == OtherValue
orderby ((MyObject)k)["PropertyIndex"]
select k.Value
EDIT: With the clarified requirements, I'd recommend you first do all your where clauses (no need to sort data you'll just ignore), then apply all the .OrderBy(). If you can make them lambdas, that's much easier than the link you suggested (pun intended):
.OrderBy( e => e.Property1 ).OrderBy( e => e.Property2 )
If you'd like to "dynamically" form these, do something like this:
var query = (from k in collection select k);
query = query.Where( e => e.Property1 == "value" );
var orderedQuery = query.OrderBy( e => e.Property1 );
orderedQuery = query.Orderby( e => e.Property2 );
var result = orderedQuery.Select( e => e.Value ).Single();
Sprinkle some conditions around these things, and you'll be golden. Note that query is of type IQueriable<T> and orderedQuery is of type IOrderedQueriable<T>, which is why you can't (without casting) reuse the same var.
You just need to apply first order field by OrderBy and all other fields by ThenBy. Of cource you have to use temporarry variable of type IOrderedEnumerable.
If you need to add some filters, then you have to add Where BEFORE any Order.
If there is many possible order options and you don't want to hardcode them, then you can use Dynamic LinQ and specify order fields as strings.

Change the order by field based on a condition

I have a scenario where I have to change the order by field based on some condition.
from summaryRows in _summaryTable.AsEnumerable()
where summaryRows.Field<string>("AirlineDisplayName")
.Equals(airlineName_, StringComparison.OrdinalIgnoreCase)
orderby summaryRows.Field<decimal>("FareAdult")
select new
{
summaryTableRow = summaryRows
};
Based on the condition, I have to change the order by field to orderby summaryRows.Field<double>("BasePricePlusTaxAndFees")
Here, both the field data type is different. How can I do it in one query?
I think this will be the most readable using fluent Linq syntax and introducing an if-statement while building the query.. Since you do not explain your condition, I assume that you have a boolean variable called condition with the appropriate value:
var query = _summaryTable.AsEnumerable()
.Where(
summaryRows => summaryRows.Field<string>("AirlineDisplayName")
.Equals(airlineName_, StringComparison.OrdinalIgnoreCase));
if (condition)
query = query.OrderBy(summaryRows => summaryRows.Field<decimal>("FareAdult"));
else
query = query.OrderBy(summaryRows => summaryRows.Field<double>("BasePricePlusTaxAndFees"));
var resultQuery = query.Select(summaryRows => new
{
summaryTableRow = summaryRows
});
Disclaimer: I have not tested it, but good luck.
What about this:
orderby conditionIsTrue ? (IComparable)summaryRows.Field<double>("BasePricePlusTaxAndFees") : (IComparable)summaryRows.Field<decimal>("FareAdult")

Categories

Resources