SingleOrDefaultAsync: what does it actually mean? - c#

As someone who deals with 'old' C# and now getting up to speed as I move to ASP.NET, I'm wondering if anybody could help me with this simple example. The built in wizard generates code like this:
var product = await _context.Products.SingleOrDefaultAsync(m => m.ProductId == id);
now, what do I get by the lamba expression m => m.ProductId == id? why can't it just be:
var product = await _context.Products.SingleOrDefaultAsync(m.ProductId);
I'm trying to read the documentation but it only adds to my confusion. it documents the query is:
public static Task<TSource> SingleOrDefaultAsync<TSource>(
this IQueryable<TSource> source
)
so... what does it mean that it returns a Task? is that a generic? what is the <TSource> doing there 3 times?
any reference to general reading that would clarify this will be highly appreciated... are these what's called expression trees? is this Linc...? where would i start? etc...
Thanks!

So the documentation for the correct overload of SingleOrDefaultAsync has the signature as:
public static Task<TSource> SingleOrDefaultAsync<TSource>(
this IQueryable<TSource> source,
Expression<Func<TSource, bool>> predicate
)
This is an extension method as indicated by the this preceding the first parameter. An extension method is a static method that is used (syntactically) as if it is a member method.
So, the first parameter source will be _context.Products.
The second parameter is an Expression<Func<>> which means the compiler will convert the lambda expression passed in into an Expression data structure representing the code. A lambda expression is used to allow you to specify any desired conditions for the query being executed e.g. you could have m => m.ProductId == id && m.Active to exclude inactivated products.
So, your second parameter predicate will be m => m.ProductId == id as an Expression tree, which the method can convert to SQL and send to the database.
Finally, the return type of Task<> indicates the method will be executed asynchronously and you will immediately get a Task object which you can use to get the actual result once it is available.
Calling await on the result causes this method to be paused in execution, control to return to the caller (which also gets a Task object), and this method to be resumed once the Task completes.

Related

Linq, c# execute method for every item in Collection (dynamic)

I got a method - methodToExecute() that returns a bool
also have a Collection something like this CollectionVM.SelectedItems.Cast<dynamic>()
I need to execute methodToExecute() for every item in my Collectionand see if at least one is false.
I tried something like this
CollectionVM.SelectedItems.Cast<dynamic>().Any(l => (methodToExecute(l.userId) == false))
but in runtime i got an error
Cannot use a lambda expression as an argument to a dynamically
dispatched operation
CAn anyone give an ideia how to solve this

LINQ Select only throws IOException when the Enumerable is looked at

I'm currently using LINQ to load a list of files into XDocuments, like so:
var fileNames = new List<string>(){ "C:\file.xml" };
var xDocs = fileNames.Select(XDocument.Load);
var xDocs2 = xDocs.ToList(); // Crashes here
If I deliberately 'lock' one of the files with a different process, the IOException is only thrown when I actually start to look at the XDocuments I've been generating, ie when ToList() is called.
Can anyone explain why this is, and how best to handle this error? I'd like to have access to the working XDocuments still, if possible.
Can anyone explain why this is
As many pointed out, this is because of the so called deferred execution of many LINQ methods. For instanse, the Enumerable.Select method documentation states
This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach in Visual C# or For Each in Visual Basic.
while the Enumerable.ToList documentation contains
The ToList<TSource>(IEnumerable<TSource>) method forces immediate query evaluation and returns a List that contains the query results. You can append this method to your query in order to obtain a cached copy of the query results.
So the XDocument.Load is really executed for each file name during the ToList call. I guess that covers the why part.
and how best to handle this error? I'd like to have access to the working XDocuments still, if possible.
I don't know what does "best" mean in this context, but if you want to ignore the errors and include the "working XDocuments", then you can use something like this
var xDocs = fileNames.Select(fileName =>
{
try { return XDocument.Load(fileName); }
catch { return null; }
});
and then either append .Where(doc => doc != null), or account for null documents when processing the list.
This is why the linq .Select is an IEnumerable and the elements are first called if you make your IEnumerable to an List. Then you go through all of your elements.

FindAll Vs Where [duplicate]

This question already has answers here:
LINQ, Where() vs FindAll()
(5 answers)
Closed 7 years ago.
I have an IEnumerable<T> that I wanted to filter based on a LINQ predicate. I tried using Where on the IEnumerable as I normally do, but this time I stumbled upon something interesting. When calling Where on the IEnumerable, with the predicate, i get an empty list in return. I know it has to produce a list with two items in it. If I instead use FindAll, with the same predicate, it then produces the correct result.
Can anyone explain to me, why this is happening? I always thought that Where was kind of a lazy version of FindAll, that also returned an IEnumerable instead of a List. There must be more to it than that? (I have done some research, but to no avail.)
Code:
IEnumerable<View> views = currentProject.Views.Where(
v => v.Entries.Any(e => e.Type == InputType.IMAGE || e.Type == InputType.VIDEO));
IEnumerable<View> views = currentProject.Views.FindAll(
v => v.Entries.Any(e => e.Type == InputType.IMAGE || e.Type == InputType.VIDEO));
You can find your answer here: LINQ, Where() vs FindAll() . Basically if you call .ToList() on your "Where" they would be the same.
You can find more about the differences between deferred and immediate execution: https://code.msdn.microsoft.com/LINQ-Query-Execution-ce0d3b95
My best guess would be that something happens between calling Where, which creates an enumerator and the place in your code where the results are actually used (i.e. where MoveNext and (get_)Current of that enumerator are actually called, e.g. from ToList).
Yes, Where is a lazy version of findall. FindAll() is a function on the List type, it's not a LINQ extension method like Where. The FindAll method on List, which is an instance method that returns a new List with the same element type. FindAll can only be used on List instances whereas LINQ extension methods work on any type that implements IEnumerable.
The main difference (besides what they're implemented on: IEnumerable vs. List) is that Where implements deferred execution, where it doesn't actually do the lookup until you need it, (using it in a foreach loop for example). FindAll is an immediate execution method.
I will refer to a data structure called an expression tree to understand deferred execution, you need only grasp that an expression tree is a data structure like a list or queue. It holds a LINQ to SQL query not the results of the query, but the actual elements of the query itself.
To understand the Where Working we need to see that if we write a code
var query = from customer in db.Customers
where customer.City == "Paris"
select customer;
Query does not execute here whereas it execute in the foreach loop
TO understand LINQ and Deferred Execution

Casting an IEnumerable<TEntity> to an IEnumerable<TResult> while ensuring deferred execution

In my application there are a fair number of existing "service commands" which generally return a List<TEntity>. However, I wrote them in such a way that any queries would not be evaluated until the very last statement, when they are cast ToList<TEntity> (or at least I think I did).
Now I need to start obtaining some "context-specific" information from the commands, and I am thinking about doing the following:
Keep existing commands largely the same as they are today, but make sure they return an IEnumerable<TEntity> rather than an IList<TEntity>.
Create new commands that call the old commands but return IEnumerable<TResult> where TResult is not an entity but rather a view model, result model, etc - some representation of the data that is useful for the application.
The first case in which I have needed this is while doing a search for a Group entity. In my schema, Groups come with User-specific permissions, but it is not realistic for me to spit out the entire list of users and permissions in my result - first, because there could be many users, second, because there are many permissions, and third, because that information should not be available to insufficiently-privileged users (ie a "guest" should not be able to see what a "member" can do).
So, I want to be able to take the result of the original command, an IEnumerable<Group>, and describe how each Group ought to be transformed into a GroupResult, given a specific input of User (by Username in this case).
If I try to iterate over the result of the original command with ForEach I know this will force the execution of the result and therefore potentially result in a needlessly longer execution time. What if I wanted to further compose the result of the "new" command (that returns GroupResult) and filter out certain groups? Then maybe I would be calculating a ton of privileges for the inputted user, only to filter out the parent GroupResult objects later on anyway!
I guess my question boils down to... how do I tell C# how I'd like to transform each member of the IEnumerable without necessarily doing it at the time the method is run?
To lazily cast an enumerable from one type to another you do this:
IEnumerable<TResult> result = source.Cast<TResult>();
This assumes that the elements of the source enumerable can be cast to TResult. If they can't you need to use a standard projection with .Select(x => ... ).
Also, be careful returning IEnumerable<T> from a service or database as often there are resources that you need to open to obtain the data so now you would need make sure those resources are open whenever you try to evaluate the enumerable. Keeping a database connection open is a bad idea. I would be more inclined to return an array that you've cast as an IEnumerable<>.
However, if you really want to get an IEnmerable<> from a service or database that is truly lazy and will automatically refresh the data then you need to try Microsoft's Reactive Framework Team's "Interactive Extensions" to help with it.
They have an nice IEnumerable<> extension called Using that makes a "hot" enumerable that opens a resource for each iteration.
It would look something like this:
var d =
EnumerableEx
.Using(
() => new DB(),
db => db.Data.Where(x => x == 2));
It creates a new DB instance every time the enumerable is iterated and will dispose of the database when the enumerable is completed. Something worth considering.
Use NuGet and look for "Ix-Main" for the Interactive Extensions.
You're looking for the yield return command.
When you define a method returning an IEnumerable, and return its data by yield return, the return value is iterated over in the consuming method. This is what it could look like:
IEnumerable<GroupResult> GetGroups(string userName)
{
foreach(var group in context.Groups.Where(g => <some user-specific condition>))
{
var result = new GroupResult()
... // Further compose the result.
yield return result;
}
}
In consuming code:
var groups = GetGroups("tacos");
// At this point no eumeration has occurred yet. Any breakpoints in GetGroups
// have not been hit.
foreach(var g in groups)
{
// Now iteration in GetGroups starts!
}

What does baking a method means?

I was reading this post here on micro ORM used on SO.
The author showed this stack-trace:
System.Reflection.Emit.DynamicMethod.CreateDelegate
System.Data.Linq.SqlClient.ObjectReaderCompiler.Compile
System.Data.Linq.SqlClient.SqlProvider.GetReaderFactory
System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Compile
System.Data.Linq.CommonDataServices+DeferredSourceFactory`1.ExecuteKeyQuery
System.Data.Linq.CommonDataServices+DeferredSourceFactory`1.Execute
System.Linq.Enumerable.SingleOrDefault
System.Data.Linq.EntityRef`1.get_Entity
Then said:
In the trace above you can see that 'EntityRef' is baking a method, which is not a problem, unless it is happening 100s of times a second.
Could someone explain the stack-trace in relation to what he meant by "baking a method" and why it would be a performance problem?
When you do something like:
int[] items = whatever;
IEnumerable<int> query = from item in items where item % 2 == 0 select item;
then the compiler turns that into something like:
static bool Predicate(int item) { return item % 2 == 0; }
...
IEnumerable<int> query = Enumerable.Where<int>(items, new Func<int, bool> (Predicate));
That is, the compiler generates the IL for the method. When you build the query object at runtime, the object returned by Where holds on to a delegate to the predicate, and executes the predicate when necessary.
But it is possible to build the IL for the delegate at runtime if you want to. What you do is persist the body of the predicate as an expression tree. At runtime the expression tree can dynamically compile itself into brand-new IL; basically we start up a very simplified compiler that knows how to generate IL for expression trees. That way you can change the details of the predicate at runtime and recompile the predicate without having to recompile the whole program.
The author of that comment is using "baking" as a slang for "dynamic lightweight code generation".
It refers to creating a method dynamically at run time, for example by using an expression tree. Compiling the expression tree to a method and returning a delegate for the compiled method could be called "baking" the method.
It's a fancy way of saying that they're emitting dynamic code using Refrection.Emit. A notoriously slow process.

Categories

Resources