Understanding AsEnumerable in Linq to Objects [closed] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Written on msdn:
Returns the input typed as IEnumerable<T>.
I do not understand.
Help me to understand this method.

There are three implementations of AsEnumerable.
DataTableExtensions.AsEnumerable
Extends a DataTable to give it an IEnumerable interface so you can use Linq against the DataTable.
Enumerable.AsEnumerable<TSource> and ParallelEnumerable.AsEnumerable<TSource>
The AsEnumerable<TSource>(IEnumerable<TSource>) method has no effect
other than to change the compile-time type of source from a type that
implements IEnumerable<T> to IEnumerable<T> itself.
AsEnumerable<TSource>(IEnumerable<TSource>) can be used to choose
between query implementations when a sequence implements
IEnumerable<T> but also has a different set of public query methods
available. For example, given a generic class Table that implements
IEnumerable<T> and has its own methods such as Where, Select, and
SelectMany, a call to Where would invoke the public Where method of
Table. A Table type that represents a database table could have a
Where method that takes the predicate argument as an expression tree
and converts the tree to SQL for remote execution. If remote execution
is not desired, for example because the predicate invokes a local
method, the AsEnumerable<TSource> method can be used to hide the
custom methods and instead make the standard query operators
available.
In other words.
If I have an
IQueryable<X> sequence = ...;
from a Linq Provider, like Entity Framework, and I do,
sequence.Where(x => SomeUnusualPredicate(x));
that query will be composed on and run on the server. This will fail at runtime because Entity Framework doesn't know how to convert SomeUnusualPredicate into SQL.
If I want that to run the statement with Linq to Objects instead, I do,
sequence.AsEnumerable().Where(x => SomeUnusualPredicate(x));
now the server will return all the data and the Enumerable.Where from Linq to Objects will be used instead of the Query Provider's implementation.
It won't matter that Entity Framework doesn't know how to interpret SomeUnusualPredicate, my function will be used directly. (However, this may be an inefficient approach since all rows will be returned from the server.)

Related

Predicate to SQL through LINQ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 17 days ago.
Improve this question
Is there a way to translate predicate(Func<T,bool>) using LINQ to SQL query or something similar to this?
Found nothing on internet or MS guides.
ORMs (like Entity Framework, linq2db, and others) in C# usually use expression trees and IQueryable to be able to translate the code into actual SQL queries, so they need Expression<Func<T, bool>>, not just Func<T, bool>. If you are creating the predicate via lambda then compiler can also translate it to expression tree, i.e.:
Func<MyClass, bool> predicate = mc => mc.IntProp == 1;
Exppression<Func<MyClass, bool>> predicate = mc => mc.IntProp == 1;
Will work both well. So in some cases you can just change your method parameter and that's it.
Read more:
Expression Trees
What is the difference between IQueryable and IEnumerable?
LINQKit - interesting library which does some magic around LINQ
Short awnser : no
Long awnser : yes... but actually no
There is no way to accuratly translate a programming language into another without the risk of the function and meaning being altered
(you could use this but even that is no longer mantained)
I would recommend you learning LinQ in order to safely translate it without mistakes.
You could also post you query so anyone like me or other more fitted members to help you out in the translation.

Problems with converting List to IQueryable in Linq [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
EDIT
Actually this question should be more general: How to modify query to DB if Linq with IQueryable gives errors?
The correct answer is as far as I understand — to get as much of the query done at the database level. Because in this particular case my complicate query just can not be transform from Linq to sql.
So I just wrote a raw sql query with FromSqlRaw() method and errors have gone. Moreover I wrote query in the way that does not take all entries (with filtering) as opposed to ToList() method, so I have less doubt about performance (though I did not measure it).
Need some help with understanding how to use linq with converting List to IQueryable.
What I had:
A three tables in DB with IQueryable-based queries to one of them.
What I need:
To create a query that combine data from three tables by Linq and give me resulting specific column with data for every element of one of table with function of filtering by this column.
What I try:
Supplement IQueryable-based query. But I found problems with List to IQueryable converting. Method AsQueryable() gives errors.
What I achieve:
I rewrite queries with List-based logic in Linq and it gives me what I need. But I do not understand:
Is this practice good?
Why should I often must make ToList() conversion for avoiding errors?
Is the speed of my solution worse than IQueryable-based approach?
Here is fiddle with my exercises: https://dotnetfiddle.net/BAKi6r
What I need I get in listF var.
I totally replace CreateAsync method in it with Create method for List. Is it good?
I also try to use hardcoded Lists with CreateAsync method /items2moq, items3moq/, but they with filtered List-based query give The provider for the source IQueryable doesn't implement IAsyncQueryProvider error. Also I got Argument types do not match error when I use IQueryable for NamesIQ instead of List for NamesList. What exactly the source of this errors?
Why should I often must make ToList() conversion for avoiding errors?
I often think about Linq queries in three "levels":
IQueryable - there are designed to translate a Linq query into an equivalent database (or whatever data source you're using) query. Many Linq and non-Linq operations just can't be translated into its SQL or other equivalent, so this layer would throw an error. Even operations that seem simple (like splitting a string) are difficult if not impossible to do in SQL
IEnumerable - in this layer, Linq queries are done in memory, so there's much more flexibility to do custom operations. To get from the IQueryable layer to the IEnumerable layer, the AsEnumerable() call is the most straightforward. That separates the part of the query that gets raw data from the part that can create custom objects, do more complex filtering and aggregations, etc. Note that IEnumerable still uses "deferred execution", meaning that at this stage, the query is just a query - the results don;t actually get computed until you enumerate it, either with a foreach loop or by advancing to the next layer:
List/Array/etc. This is where queries are executed and turned into concrete collections. Some of the benefits of this layer are serializability (you can't "serialize" an enumerator) and eager-loading (as opposed to deferred execution described above).
So you're probably getting an error because you have some part of your query that can't be translated by the underlying Queryable provider, and using ToList is a convenient way to materialize the raw data into a list, which allows you to do more complex operations. Note that AsEnumerable() would do the same thing but would maintain deferred execution.
Is this practice good?
It can be, but you might easily be getting more data than you need by doing filtering at the list level rather than at the database level. My general practice is to get as much of the query done at the database level, and only moving to the enumerable/list level when there's no known way to translate the rest of the query to SQL.
Is the speed of my solution worse than IQueryable-based approach?
The only way to know is to try it both ways and measure the difference. But it's a pretty safe bet that if you get more raw data than you need and filter in memory that you'll have worse performance.

How would you correctly return a collection of objects asynchronously? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I need to define methods in my core interface that return lists. My project heavily relies on the use of async/await so I need to define my core references/interfaces as asynchronous as possible. I also use EF7 for my data-access layer. I currently use IAsyncEnumerable everywhere.
I am currently deciding whether to keep using IAsyncEnumerable or to revert back to using Task<IEnumerable<T>>. IAsyncEnumerable seems promising at this point. EF7 is using it as well. The trouble is, I don't know and can't figure out how to use it. There is almost nothing on the website that tells anyone how to use Ix.Net. There's a ToAsyncEnumerable extension that I can use on IEnumerable objects but this wouldn't do anything asynchronously (or does it??). Another drawback is that given the below signature:
IAsyncEnumerable GetPersons();
Because this isn't a function that returns Task, I can't use async/await inside the function block.
On the other hand, my gut is telling me that I should stick with using Task<IEnumerable<T>>. This of course has it's problems as well. EF does not have an extension method that returns this type. It has a ToArrayAsync and ToListAsync extension method but this of course requires you to call await inside the method because Task<T> isn't covariant. This potentially is a problem because this creates an extra operation which could be avoided if I simply return the Task object.
My questions is: Should I keep using IAsyncEnumerable (preferred) or should I change everything back to Task<IEnumerable<T>> (not preferred)? I'm open to other suggestions as well.
I would go with IAsyncEnumerable. It allows you to keep your operations both asynchronous and lazy.
Without it you need to return Task<IEnumerble> which means you're loading all the results into memory. This in many cases meaning querying and holding more memory than needed.
The classic case is having a query that the user calls Any on. If it's Task<IEnumerable> it will load all the results into memory first, and if it's IAsyncEnumerable loading one result will be enough.
Also relevant is that with Task<IEnumerable> you need to hold the entire result set in memory at the same time while with IAsyncEnumerable you can "stream" the results a few at a time.
Also, that's the direction the ecosystem is heading. It was added by reactive extension, by a new library suggested by Stephen Toub just this week and will probably be supported in the next version of C# natively.
You should just use Task<IEnumerable<T>> return types. The reason is simply that you don’t want to lazily run a new query against the database for every object you want to read, so just let EF query those at once, and then pass that collection on.
Of course you could make the async list into an async enumerable then, but why bother. Once you have the data in memory, there’s no reason to artificially delay access to it.

What is the difference between Queryable.OrderBy and Enumerable.OrderBy? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Suppose I have a LINQ to SQL (or EntityFramework) data context (object context). I want to query some data from it and sort the result set. The query would look like:
using(var dc = new TestDataContext) // = new TestEntities)
{
var query = dc.MyEntities.Where(e => /*my where clause*/)
.OrderBy(/*my sorting field*/)
.ThenBy(/*another sorting field*/);
foreach(var entity in query)
{
//...
}
}
Depending on the type of an argument different OrderBy and ThenBy methods may be used.
Queryable.OrderBy Method with Expression<Func<TSource, TKey>>
Enumerable.OrderBy Method with Func<TSource, TKey>
In DataContext.Log one can see that Queryable.OrderBy compiles the given expression into the SQL statement executed over the database, while when using Enumerable.OrderBy LINQ actually does the sorting over the objects in the programm's memory, i.e. the query over the database is executed without sorting...
What are other possible peculiarities, I may come across?
This question arised after this: SO How to make expression treat value type as a reference type?
In DataContext.Log one can see that Queryable.OrderBy compiles the
given expression into the SQL statement executed over the database,
while when using Enumerable.OrderBy LINQ actually does the sorting
over the objects in the programm's memory,
That's the only difference. And because compiler can translate your lambda Func<T> into Expression<Func<T>> the Queryable.OrderBy will be used by default.
When a lambda expression is assigned to a variable, field, or parameter whose type is Expression<TDelegate>, the compiler emits instructions to build an expression tree.
from Expression<TDelegate> Class
If you really need to perform LINQ to Objects Enumerable.OrderBy call AsEnumerable() before OrderBy call.
The difference here is that persistence frameworks such as NHibernate and Entity Framework have their own LINQ providers that traverse expression trees and build SQL queries. This is thanks to deferred execution. Nothing actually happens with an IQueryable until something forces the provider to evaluate it.
On the other hand.. LINQ can do in-memory queries AFTER the above has taken place. Maybe this will make more sense:
var result = db.Entities.Table
.Where(x => x.Id == 1) // SQL WHERE clause
.OrderBy(x => x.Id) // SQL ORDER BY clause
.ToList() // Query the database and store result
.Sum(x => x.SomethingElse) // Sum the field in memory
.ToList(); // convert back to a list.
As you can see.. halfway through that chain the provider hits the database with a generated query. The ToList() call forces the provider to query the database for results. After that, it's all in-memory.

Collection parameter in method/constructor? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
When some method/constructor accepts a collection parameter, should the parameter type be used as IEnumerable most of the time ? If so, should the method create a new List (.ToList()) to store the reference in a private variable or in method scoped local variable instead of storing the variable in a IEnumerable type variable?
Please let me know.
should the parameter type be used as IEnumerable most of the time ?
If you really mean IEnumerable<T> then yes. Unless the type needs something richer, then you could use one of the interfaces that extend IEnumerable<T>.
You should avoid the non-generic interfaces and collections (namespace System.Collections) in favour of generic ones (namespace System.Collections.Generic).
If so, should the method create a new List (.ToList()) to store the reference in a private variable or in method scoped local variable instead of storing the variable in a IEnumerable type variable?
Possibly yes.
The answer depends on the semantics of your type. If defined as holding a reference to the collection then don't copy it (eg. multiple ContactPerson in an Organisation may all share the list of Interaction with that organisation). In other cases where the new object will own the collection then it should make a copy.
I would say you should use it in a way, that makes you sure you're iterating over the collection only once.
So if you're just using simple foreach IEnumerable is OK, but if you'd like to make more complex things you should store it locally (using ToList(), ToArray() or similar) and than use that local variable instead of iterating over source collection over and over.
If you're going to use only for Read - use IEnumerable, if you want to update the collection, by Add, Remove elements, you should cast to a collection type which allows you to do these actions

Categories