Is there a way to delay - execute delegate against IQueryable <T> after / at runtime?

I am exposing the IQueryable method from my business layer for use in other layers. I would like to execute a function against each of the enumeration elements as soon as the request completes the lower level.

It seems that an event should occur that occurs after the query is completed so that I can then work with the results of this general level.

Sort of:

public IQueryable<User> Query() { return _Repository.Query<User>().ForEachDelayed(u=> AppendData(u)); } 

I want the ForEachDelayed function to return IQueryable without executing the query. The idea is that after the request is completed, the results are passed through this delegate.

Is there something similar? If not, is there an event like "IQueryable.OnExecute" that I can subscribe to?

Any help would be awesome - thanks!

EDIT:

I thought I had an answer with this:

 var users = from u in _Repository.Query<User>() select AppendData(u); return users; 

But now I get the following error:

The AppendData (User) method does not support SQL translation.

I really need a delegate to run AFTER the request is complete.

+4
source share
4 answers

Easy way

Another option, which is much simpler, would be to add what you need using Iterator , see the example below. The disadvantage of this approach is that everything would be pulled into memory while the iteration is being performed so that AppendData is only executed on the returned data. This is similar to the @Chris parameter, but you should not create a new Func and Select request every time you want to use this method.

 static void Main(string[] args) { var data = new List<int> { 1, 2, 3, 4, 5 }.AsQueryable().AppendData(); Console.WriteLine("Before execute"); Console.Write("{ "); foreach (var x in data) Console.Write("{0}, ", x); Console.WriteLine( "}"); Console.WriteLine("After execute"); Console.Read(); } // Append extra data. From this point on everything is in memory // This should be generic, ie AppendData<T>, but I an easy way to "append" static IEnumerable<int> AppendData(this IEnumerable<int> data) { Console.WriteLine("Adding"); foreach (var x in data) yield return x * 2; } 

Hard way

I don't believe there are any built-in events like this, but you could probably add your own by implementing your own IQueryable packaging.

Here is a series about writing a complete IQueryable provider, which will also show you where you could put your wrapper, most likely around that IQueryProvider .

Good luck and hope it helps.

+1
source

Do you have a look at ToExpandable ()?

http://tomasp.net/blog/linq-expand.aspx

You can always call ToList () before executing the code - which will call SQL, then you can run your code in the result set -

 var users = from u in _Repository.Query<User>().ToList(); //this will invoke AppendData() for each u var retVal = from u in users select AppendData(u); return retVal; 
+1
source

You are currently using ORM, right? I'm sure you can achieve this by using the lambda expression form, explicitly using the IEnumerable select version, instead of IQueryable.

 var users = (_Repository.Query<User>() as IEnumerable<User>).Select(u => AppendDate(u)); return users; 

When the query is actually executed, it will retrieve all the data returned by Query (), and then make a selection in memory.

0
source

I have not tried it, but I think you could use automapper to map to another or similar object that returns IQuerible, and use "AfterMap" to map to execute your code after the request has completed.

0
source

Source: https://habr.com/ru/post/1300096/


All Articles