这是在服务/存储库层的MVC中正确使用async / await吗? [英] Is this the correct usage of async/await in MVC with service/repository layer?

查看:121
本文介绍了这是在服务/存储库层的MVC中正确使用async / await吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用VS2013,EF6.1.1,MVC5,.net 4.5。

Using VS2013, EF6.1.1, MVC5, .net 4.5.

我刚刚开始研究异步/等待第一次,我不知道这样做正确。它似乎工作,但可以更简单吗?

I have just started looking into async/await for the first time and I am not sure if this is doing it properly. It appears to work, but could it be simpler? I seem to be sticking async/await in a lot of places for one method call down multiple layers.

为了简洁起见,所有的代码都被简化了。

All code has been simplified for brevity.

在我的MVC控制器操作方法中,我有:

In my MVC controller action method I have:

public async Task<ActionResult> TestAction1()
{
    var testResponse = await _testService.TestMethod1(1);

    if (testResponse != null)
    {
        _unitOfWork.CommitAsync();
        return View(testResponse);
    }

    return RedirectToAction("TestAction2");
}

我的服务类如下:

public class TestService : ITestService
{
    public async Task<TestObject> TestMethod1()
    {
        var testObject1 = await privateMethod1Async();
        if (testObject1 != null) return testObject1;

        testObject1 = await privateMethod2Async();

        return testObject1;
    }

    private async Task<TestObject> privateMethod1Async()
    {
        return await _testRepository.FirstOrDefaultAsync();
    }

    private async Task<TestObject> privateMethod2Async()
    {
        return await _testRepository.FirstOrDefaultAsync();
    }
}

我的存储库方法:

public async Task<TEntity> FirstOrDefaultAsync()
{
    return await _entitySet.FirstOrDefaultAsync();
}

基本上,我有一个控制器方法,调用一个服务方法。服务方法是以异步方式调用数据库层两次。但是我觉得我正在改变每一种处理异步的方法和层次,我不知道我在这里是否正确。

Basically, I have a controller method, that calls a service method. The service method is to call the database layer twice, in an async fashion. But I feel that I am changing every single method and layer to deal with async and I wasn't sure if what I have here is correct.

其次,在控制器方法我不确定如何异步调用工作提交方法。具有_unitOfWork.CommitAsync();的行。

Secondly, in the controller method I am unsure how to call the unit of work commit method asynchronously. The line that has "_unitOfWork.CommitAsync();". I cannot stick an "await" before it as it is a void method.

任何想法?

编辑1

以下是存储库方法调用EF的完整版本:

Here is the full version of the repository method call to EF:

public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> 
                                               predicate, params 
                                               Expression<Func<TEntity, object>>[]
                                               includeProperties)
{
    IQueryable<TEntity> query = EntitySet;
    if (includeProperties != null && includeProperties.Any())
    {
        query = IncludeProperties(query, includeProperties);
    }
    return await query.FirstOrDefaultAsync(predicate);
}


推荐答案

我看到一个重现的模式你的代码:

I see a reoccurring pattern in your code:

private async Task<TestObject> privateMethod2Async()
{
    return await _testRepository.FirstOrDefaultAsync();
}

当您有一个单行方式,只需查询您的数据库一个 Task< T> ,您可以避免等待导致的状态机分配,只需将热任务返回给调用者(因为他可能会等待更高的呼叫链):

When you have a single-liner which simply queries your DB for a Task<T>, you can avoid the state-machine allocation which await causes, and simply return the hot task to the caller (as he'll probably await on it anyway higher up the call-chain):

private Task<TestObject> privateMethod2Async()
{
    return _testRepository.FirstOrDefaultAsync();
}

请注意, async-await 将让你走异步一路,这是异步的本质。确保您可以使用 Task.WhenAll (如果可能)并发运行任务,例如(不确定这可能是最好的示例):

Note that async-await will make you go "async all the way", that's the nature of async. Make sure that you group tasks that can run concurrently using Task.WhenAll if possible, for example (not sure this might be the best example):

public async Task<TestObject> TestMethod1()
{
    var testObject1 = await privateMethod1Async();
    if (testObject1 != null) return testObject1;

    testObject1 = await privateMethod2Async();

    return testObject1;
}

可能会变成:

return Task.WhenAny(privateMethod1Async(), privateMethod2Async());

鉴于其中一种方法适用于返回类型。

given that one of the methods is applicable as a return type.

编辑:


添加异步是一般规则的经验法则/等待?是
它为一个方法做其他处理吗?哪一个,当你点
出来,这个方法不是?

What is the general rule rule of thumb for adding the async/await? is it for a method that does other processing in it? Which, as you point out, this method doesn't?

你想使用等待,当您希望对返回的任务进行更多处理时。如果您想要的是返回实际的任务,则无需等待,您只需返回热任务即可。这是我使用的一般规则。另请注意,当您使用返回await vs简单返回

You would want to use await when you'd want to be doing more processing on the returned Task. If all you want is to return the actual Task, there is no need to await it, you can simply return the hot task. That's the general rule i use. Also note that exception handling is different when you use return await vs simply return.

您可以在在异步方法结束时,我应该返回还是等待?等待任务.Run();返回;"和return Task.Run()?

这篇关于这是在服务/存储库层的MVC中正确使用async / await吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆