ASP.NET MVC 5异步上下文管理

jps*_*jps 10 c# asp.net-mvc async-await c#-5.0 asp.net-mvc-5

我有一个相当标准的MVC 5应用程序,包括存储库层,服务层和控制器层.为了保持每个层分离和可测试,我使用Ninject进行依赖注入.

为了了解新技能,我决定在服务和控制器方法的IO绑定操作上使用async/await的新的新任务控制器操作.

通常我只是像这样使用InRequestScope绑定

kernel.Bind<IDbContext>().To<BlogContext>().InRequestScope();
Run Code Online (Sandbox Code Playgroud)

一般情况下这现在工作正常,但是如果我选择调试我的应用程序,或者将多个跟踪的实体框架对象连接在一起并保存,我发现上下文已被处理或我正在跟踪问题.我明白为什么会发生这种情况,这是完全合乎逻辑的,因为IIS线程上不再进行操作,所以Ninject如何知道它应该使用相同的上下文.

为了解决这个问题,我可以将我的上下文从我的服务层传递到每个存储库调用,如果需要,甚至可以从控制器层传递.但是我觉得这看起来很混乱,如果可能的话,我宁愿Ninject管理这个对象的上下文.

在保持我的代码类似于下面给出的示例的同时,以优雅/简约的方式处理此问题的最佳策略是什么?

这是我的一个控制器方法的示例

    public virtual async Task<ActionResult> Edit(int id)
    {
        var editViewModel = await BuildDefaultCreateEditViewModel();

        var post = await postService.GetNonDeletedPost(id);
        ...
        ...
        return View(MVC.Admin.Post.Views.CreateEdit, editViewModel);
    }
Run Code Online (Sandbox Code Playgroud)

服务方式

    public async Task<PostDTO> GetNonDeletedPost(int postId)
    {
        return (await PostRepostiory.GetPost(postId)).ConvertToDTO();
    }
Run Code Online (Sandbox Code Playgroud)

存储库方法

    public Task<Post> GetPost(int postId)
    {
        return QueryableExtensions.SingleOrDefaultAsync(
                DbSet.Where(post => post.PostId == postId)
                .Include(post => post.PostVersions)
                .Include(post => post.Categories)
                .Include(post => post.Files));
    }
Run Code Online (Sandbox Code Playgroud)

Gre*_*reg 1

在您的帖子和相关评论中,有一些关于如何执行此操作的很好的示例。

然而,对于其他一些可能会在这里绊倒的读者,我想提出一个诚实的问题:你真的需要异步控制器吗?

异步控制器操作释放了处理请求所需的线程数量;但是,如果您没有用完线程并且不太可能用完线程,那么您在尝试解决您既没有也不希望出现的问题时就会造成复杂性。或者:“Async 真的免费并且总是更好吗?”

实际上,我试图展示一种非常可行的解决方案(也许不是您正在寻找的解决方案),那就是根本不使用异步控制器 - 如果确实不需要(这取决于您的具体情况。)

通过消除问题来解决问题的古老而古怪的解决方案。特别是,我提出它是因为消除复杂性似乎是目标之一。

如何选择使用哪个? 有一个更长的列表,但最好的两个问题是:

  • 您的商品缺货吗?
  • 如果不是,您的项目是否受 CPU 限制?

http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4

来自上面的链接“对 CPU 密集型操作使用异步操作方法没有任何好处,并且会导致更多开销。”