Home > Software design >  Results.Ok(output) versus Results.Ok(await output.ToArrayAsync())
Results.Ok(output) versus Results.Ok(await output.ToArrayAsync())

Time:09-17

If I use

// VERSION A
private static IResult Gets(AppDbContext db)
{
    var output = db.Courses.AsNoTracking().Select(c => new CourseDto { Id = c.Id, Credits = c.Credits });
    return Results.Ok(output);
}

instead of

// VERSION B
private static async Task<IResult> Gets(AppDbContext db)
{
    var output = db.Courses.AsNoTracking().Select(c => new CourseDto { Id = c.Id, Credits = c.Credits });
    return Results.Ok(await output.ToArrayAsync());
}

does the framework internally invoke one of ToArray(), ToArrayAsync(), ToList() or ToListAsync(), etc (among others) to "materialize" IQueryable<CourseDto> and produce JSON output?

One more question: Which approach should I choose? Version A or version B?

CodePudding user response:

It's not going to be able to create JSON from an IQueryable without materializing the query results.

So your first one is effectively return Results.Ok(output.ToArray()); (or ToList()) (well, it's likely cheaper than either ToArray or ToList - it's really just the cost of foreaching through the data). It's at that point that your query is executed.

If you explicitly use .ToArrayAsync(), then you are doing the query asynchronously and you get all the goodness that comes from async operations. Choosing the Blue pill here is the correct course of action

If you don't make the async call explicitly, I'm pretty sure the query is going to be done synchronously. Without an async notation, the compiler can't build the scaffolding to support asynchronous operations. Remember, async requires async all the way down the stack

CodePudding user response:

I'm no C# expert, but version B seems functionally the same as version A. await-ing an async method in this scenario accomplishes the same thing as just calling the synchronous method. I'd keep it simple & just use version A.

I don't believe this method will return JSON - just an IQueryable. I believe you can do:

private static IResult Gets(AppDbContext db)
{
    var output = db.Courses.AsNoTracking().Select(c => new CourseDto { Id = c.Id, Credits = c.Credits });
    return Json(output);
}

You may need to change the return type to ActionResult

  • Related