I ran across some code in an older project I am working on that I've never seen before, and has me confused on it's intent.
updatables.Select(r =>
{
// some operations are done here for each element in the list
return true;
}).ToArray();
It seems like a select statement is being used to iterate the updatables collection. Also seems the ToArray call isn't doing anything.
My question is, what does calling return true in the Select statement accomplish, if anything?
This looks very much like a hack to emulate ForEach:
ToArray() call is added to ensure that updatables will be iterated to completion,
return true is added to silence the compiler that does not allow Action<T>, but allows Func<T,bool> in LINQ's Select.
I would strongly recommend against writing code like this, because it is a lot less readable than an equivalent foreach loop.
Select takes a Func<T, TResult> - which means it won't accept an Action<T>. In other words, a lambda which does not return anything will result in a compilation error when passed to Select, so the author bypassed that "limitation" by having it return a dummy value.
The intent behind this code is likely to run a foreach loop on the collection using the LINQ syntax. However, the way it's done in this code is a bad practice, as LINQ methods are expected to be pure - that is, not modify any sort of state outside of the expression.
Related
I have some function (X) which return IQueryable with "OrderBy(x => x.Name)".
I want to use X function in new code, but in this code there is parameter which determine the order (asc/desc).
I prefer not to change (X) since it used in multiple places already.
there is option to get X(), then cancel it's "OrderBy", and apply new order?
(now it throws exception, since it is like Y.OrderBy(a => a.Name).OrderByDescending(a => a.Name))
"A column has been specified more than once in the order by list. Columns in the order by list must be unique.\r\nStatement(s) could not be prepared."
use
public void x(string order = string.empty)
{
Y.OrderBy(a => a.Name);
if (order == "desc")
{
Y = Y.Reverse();
}
}
I've tried to wiggle Expression object of IOrderedQueryable that your method is actually returning (am I wrong?) but so far no luck, and I can't see the option to manipulate System.Linq.Expression or System.Linq.EnumerableQuery easy enough to use it instead of changing X() method.
IMHO, you should choose from:
create somes kind of wrapper method using the Reverse() (#Eric Lizotte answer) or OrderByDescending() - it will be less time consuming I guess but for grouping, filtering etc. you will have to create brand new function.
remove OrderBy() from X() function body, and modify your old code - returning non-ordered result will give you more flexibility and opportunity to do what you want to do with the result via linq expressions in each scenario that you'll came across.
Can you clarify for me if you're talking about "function" you have in mind a sql function that is mapped via ORM (eg. Entity Framework) in your application or just a ordinary method which is using your custom provider to return IQueryable?
I'm using a delegate to hold a few methods that test a value and return a true/false result. After learning that a call to a delegate will only return the result of the last method in the delegate, I'm unsure of how to proceed.
I'd like to receive either the list of results from all the method calls in a delegate or if any of the calls returned true.
First I tried enumerating over the delegate with a foreach, which didn't work. I had to pull the methods out beforehand like so
System.Delegate[] methods = int_testers.GetInvocationList();
// Methods in int_testers returns true when a condition is met by the input value
Then enumerate with dynamic invokes on each member within 'methods'
foreach (var item in ds) {
if ((bool)item.DynamicInvoke(4))
return true;
}
However, I've read that DynamicInvoke is much slower (order of magnitude or more) than Invoke which is a trade off I'm not willing to make.
The alternative so far I've found is to have a list of Func<int,bool> and enumerate over those,
List<Func<int,bool>> methods = ....; // Add the methods into the list
foreach (var method in methods) {
if(method(4)) {
return true;
}
}
While this works, it seems like an issue delegates were made to solve. So, finally, is there a way to get a list of results from a delegate without simulating a delegate by hand?
This is essentially using the results of a map function in functional terms but I don't have enough C# experience to bring that idea nicely to what I'm doing.
I looked into LINQ a little for this and it seems it could work with the second method I've outlined though I can't seem to use LINQ with delegates in this case.
You could use Predicate<T> instead of delegate, and LINQ's Any() instead of a for loop:
var methods = new List<Predicate<T>>();
// add methods to list
return methods.Any(x => x(4));
I'm looking to give a talk about LINQ, and wanted to mention how querying collections used to work. Back in .Net 1.1, I seem to remember there being a method (Find() maybe?) where you would pass the address of another method which would interrogate each item in the collection and determine whether it should be included in the filtered collection.
Am I completely misremembering this? It stuck with me, as the syntax was unusual for the time.
I thought it was something like:
public bool ContainsFoo(string term){
if(term.contains("Foo"){
return true;
}
return false;
}
And you could call it like:
filteredCollection = collection.Find(ContainsFoo);
I seem to remember a lot of people commenting on how LINQ was so much faster to code because developers could now write functions in-line. How were we writing functions "out-line" previously?
Before LINQ you were just limited to all the built-in List/List<T> methods, and yes Find is one of them (still is). The difference is it expects a Predicate<T> as opposed to a Func<Boolean, T> which you can still do inline e.g.
var found = list.Find(delegate(Item item) { return item != null; });
Or as you demonstrated by using a named method.
I am having trouble mixing c# functions with conditions in Linq-To-SQL
suppose i have a database table "things" and a local c# Function : bool isGood(thing, params)
I want to use that function to select rows from the table.
var bad = dataContext.Things.Where(t=>t.type=mytype && !isGood(t,myparams))
dataContect.Things.deleteAllOnSubmit(bad);
or
if (dataContext.Things.Any(t=>t.type=mytype && isGood(t,myparams)))
{
return false;
}
Of course this does not work, Linq has no way of translating my function into a SQL statement. So this will produce:
NotSupportedException: Method 'Boolean isGood(thing,params)' has no supported translation to SQL.
What is the best way to redesign this so that it will work?
I can split the statements and convert to list like this:
List<Things> mythings dataContext.Things.Where(t=>t.type=mytype).toList()
if (mythings.Any(t=>isGood(t,myparams)))
{
return false;
}
this works, but seems inefficient, since the whole list has to be generated in every case.
And I don't think I can do a deleteAllOnSubmit with the result
I could do a foreach over mythings instead of calling toList(), that also works. Seems inelegant though.
What other options do I have, and what would be the recommended approach here?
edit:
calling asEnumerable() seems to be another option, and seems better than toList() at least. I.e.
dataContext.Things.Where(t=>t.type=mytype).asEnumerable().Any(t=>isGood(t,myparams))
Pulling the whole list back from the database to run a local c# function on it might seem inefficient, but that what you'd have to do if your isGood() function is local.
If you can translate your isGood() function into Linq, you could apply it before the toList() call, so it would get translated into SQL and the whole list wouldn't be retrieved.
In a previous question I asked how to make "Computed properties" in a linq to sql object. The answer supplied there was sufficient for that specific case but now I've hit a similar snag in another case.
I have a database with Items that have to pass through a number of Steps. I want to have a function in my database that retrieves the Current step of the item that I can then build on. For example:
var x = db.Items.Where(item => item.Steps.CurrentStep().Completed == null);
The code to get the current step is:
Steps.OrderByDescending(step => step.Created).First();
So I tried to add an extension method to the EntitySet<Step> that returned a single Step like so:
public static OrderFlowItemStep CurrentStep(this EntitySet<OrderFlowItemStep> steps)
{
return steps.OrderByDescending(o => o.Created).First();
}
But when I try to execute the query at the top I get an error saying that the CurrentStep() function has no translation to SQL. Is there a way to add this functionality to Linq-to-SQL in any way or do I have to manually write the query every time? I tried to write the entire query out first but it's very long and if I ever change the way to get the active step of an item I have to go over all the code again.
I'm guessing that the CurrentStep() method has to return a Linq expression of some kind but I'm stuck as to how to implement it.
The problem is that CurrentStep is a normal method. Hence, the Expression contains a call to that method, and naturally SQL cannot execute arbitrary .NET methods.
You will need to represent the code as an Expression. I have one in depth example here: http://www.atrevido.net/blog/2007/09/06/Complicated+Functions+In+LINQ+To+SQL.aspx
Unfortunately, the C# 3.0 compiler has a huge omission and you cannot generate calls to Expressions. (i.e., you can't write "x => MyExpression(x)"). Working around it either requires you to write the Expression manually, or to use a delegate as a placeholder. Jomo Fisher has an interesting post about manipulating Expression trees in general.
Without actually having done it, the way I'd probably approach it is by making the CurrentStep function take the predicate you want to add ("Completed == null"). Then you can create a full Expression> predicate to hand off to Where. I'm lazy, so I'm going to do an example using String and Char (String contains Chars, just like Item contains Steps):
using System;
using System.Linq;
using System.Linq.Expressions;
class Program {
static void Main(string[] args) {
Console.WriteLine(StringPredicate(c => Char.IsDigit(c)));
var func = StringPredicate(c => Char.IsDigit(c)).Compile();
Console.WriteLine(func("h2ello"));
Console.WriteLine(func("2ello"));
}
public static Expression<Func<string,bool>> StringPredicate(Expression<Func<char,bool>> pred) {
Expression<Func<string, char>> get = s => s.First();
var p = Expression.Parameter(typeof(string), "s");
return Expression.Lambda<Func<string, bool>>(
Expression.Invoke(pred, Expression.Invoke(get, p)),
p);
}
}
So "func" is created by using StringPredicate to create an Expression. For the example, we compile it to execute it locally. In your case, you'd pass the whole predicate to "Where" so it gets translated to SQL.
The "get" expression is where you put your "extension" stuff (OrderByWhatever, First, etc.). This is then passed in to the predicate that's given to you.
Don't worry if it looks complicated; it sorta is at first. If you haven't done this kinda stuff before, it'll take a bit of time (the first time I did this kinda stuff, it took hours to get it right :|.. now it comes slightly easier). Also, as I mentioned, you can write a helper method to do this re-writing for you (so you don't directly need to use the Expression.Whatever methods), but I haven't seen any examples and haven't really needed it yet.
Check out my answer to "switch statement in linq" and see if that points you in the right direction...
The technique i demonstrate there is the one that got me past the scary "no translation to SQL" error.