John John
John John

Reputation: 1

writing async Repository methods inside my asp.net mvc5 web application

I am working on an asp.net mvc5 web application + Entity Framework 6. and I want to have a repository model class inside my application. currently I am following this approach to have async action methods and async repository model class.

for example I have the following repository save method:

public class Repository
{
    private Entities t = newEntities();

    public async Task Save()
    {
        await t.SaveChangesAsync();
    }

which I am calling from my action methods as follow:

Repository repository = new Repository();
 public async Task<ActionResult> GetResourceByName(string resourcename)
      {
         await  repository.Save();
      }

so is this a correct approach? as I am doing the following:

  1. I define the repository method as a Task & also the Action method as Task. so should I have both of them as Task(s).?

  2. I am using await twice on the action method (when calling the repo method) and on the repository? so are these await redundant?

//please note that this is only a simple example of a repository method which is just used to save model,, but I am asking about the approach itself as I will be using this approach in a more complex repository methods ..

Upvotes: 1

Views: 1356

Answers (4)

Maxime
Maxime

Reputation: 8979

To answer your questions:

  1. Yes, they should both return Tasks.
  2. Yes, the await make sense. No, they are not redundant.

To understand why you might (not necessary) need to await twice, I suggest you take a look at this article which gives a pretty clear example of how and why it works:

C# async and await: Why Do We Need Them?

If you want to use repositories and may want to consider using services for you business logic, I would recommend you check this project that is easily extensible and generic:

URF - Unit of Work & Repositories Framework

Before you consider developing everything from scratch, you should check it out. I really love this project!

Upvotes: 0

Paulo Morgado
Paulo Morgado

Reputation: 14856

Regardless of the other answers, here is why you should use await and more.

ASP.NET has a synchronization context that will be captured on each await and the continuation (the rest of the async method) will be posted for that context. That means not only thread switching but populating the switched to thread with the ASP.NET context.

If you suffix your asynchronous calls (those with await with a call to ConfigureAwait(false) the ASP.NET context switching won't happen (although the thread switching will).

Because the action view engine most probably need the ASP.NET context, you can't use ConfigureAwait(false) on the MVC action method. But you should use on all methods called by it.

So, your code should be something like this:

public class Repository
{
    private Entities t = new Entities();
    public async Task SaveAsync()
    {
        await t.SaveChangesAsync().ConfigureAwait(false);
    }
}


Repository repository = new Repository();
public async Task<ActionResult> GetResourceByName(string resourcename)
{
    await repository.SaveAsync();
}

Because you might not have an ASP.NET context after an await with a call to ConfigureAwait(false) you should pass as arguments everything you need from the ASP.NET context.

Upvotes: 1

jimSampica
jimSampica

Reputation: 12420

Contrary to both answers two awaits are not necessary. await and async are only necessary if you need the result from a Task before continuing. If you don't need that result then you don't need to mark your method async.

This means this method...

public async Task Save()
{
    await t.SaveChangesAsync();
}

Can be simplified into

public Task Save()
{
    return t.SaveChangesAsync();
}

Even though these are functionally the same, I like the second version because it shows recognition that Task is the asynchronous work and async/await are only signals to the compiler to wait for that work to complete.

Upvotes: 2

Aram
Aram

Reputation: 5705

  1. Q1: Yes both should return Task and that's how it should be and it is completely fine.
  2. Q2: Yes both should have the await (if you have more layers, then all those function calls in all those layers should have await).

Basically: Once you go async/await, all the call chain should be async/await to avoid thread related issues...

If you don't await then that is called: "Fire and Forget" which is not recommended, because then this request will be returned to the user with success message, but at a later time, the call that you made without the await could fail and throw an exception and you wont have any idea of what is that exception...

Upvotes: 2

Related Questions