I'd like to demonstrate in a bluntly obvious way how this asynchronous sample:
Thing[] stuff = await Context.Things
.Where(a => true)
.ToArrayAsync();
Console.WriteLine("Beep");
will execute in a different order than they synchronous version:
Thing[] stuff = Context.Things
.Where(a => true)
.ToArray();
Console.WriteLine("Boop");
I'd like to show that the second version always creates the array before the printout while the first one may perform differently.
Not sure how to do it obviously clear.
CodePudding user response:
I'd like to demonstrate in a bluntly obvious way how this asynchronous sample:
will execute in a different order than they synchronous versio
But you can't cause both versions will create array before the Console.WriteLine("Boop");
. In the first sample await
will stop the method execution until the asynchronous operation will finish.
Such experiments are not that easy with db contexts cause you will need some side effect. Much easier to use Task.Delay
for async simulation;
Your first snippet can be changed to:
var array = await Task.Run(async () =>
{
await Task.Delay(500); // simulate db call
Console.WriteLine("Array created");
return new int[]{};
});
Console.WriteLine("Beep");
Then you can compare it with:
var task = Task.Run(async () =>
{
await Task.Delay(500); // simulate db call
Console.WriteLine("Array created");
return new int[]{};
});
Console.WriteLine("Beep");
var array = await task;
As for trying to prove async nature of EF Core calls (1. assuming you are using this ORM 2. assuming that you are not querying Oracle database which AFAIK still does not provide truly async client) you will need to find a way to inject your side effect. For relatively easy way to do this you can look into EF Core Interceptors or events like ChangeTracker.Tracked
or just enabling logging and/or using diagnostic listener.
For example (should work in EF7):
class ObjectCreatedLoggerInterceptor : IMaterializationInterceptor
{
public object CreatedInstance(MaterializationInterceptionData materializationData, object entity)
{
Console.WriteLine("Array element created");
return entity;
}
}
public class SomeContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.AddInterceptors(new ObjectCreatedLoggerInterceptor());
base.OnConfiguring(optionsBuilder);
}
}
Which will write "Array element created"
every time an object is created by EF (query should return at least one record).
CodePudding user response:
You have to modify first example as following to prove it.
var task = Context.Things
.Where(a => true)
.ToArrayAsync();
Console.WriteLine("Beep");
Thing[] stuff = await task;
In this example, ToArray will be executed after the console as task is awaited later on.