【问题标题】:ASP.NET MVC 5 Async Context ManagementASP.NET MVC 5 异步上下文管理
【发布时间】:2014-07-10 17:48:27
【问题描述】:

我有一个相当标准的 MVC 5 应用程序,它由存储库层、服务层和控制器层组成。为了保持每一层的解耦和可测试性,我使用 Ninject 进行依赖注入。

为了重温新技能,我决定使用新的 Task 控制器动作和异步 / 等待服务和控制器方法的 IO 绑定操作。

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

kernel.Bind<IDbContext>().To<BlogContext>().InRequestScope();

总的来说,现在这工作正常,但是如果我选择调试我的应用程序,或者将多个跟踪的实体框架对象连接在一起并保存,我会发现上下文已被处理或者我遇到了跟​​踪问题。我明白为什么会发生这种情况,这是完全合乎逻辑的,因为操作不再发生在 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);
    }

服务方式

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

存储库方法

    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));
    }

【问题讨论】:

  • 你使用 DbContextFactory 吗?我倾向于使用 TransientScope 而不是 Request,我从来没有遇到任何问题
  • 我实际上希望我可以以类似于使用 InRequestScope 的 DbContextFactory 的方式使用 Ninject。如果我沿着使用 DBContextFacotry 的路线前进,那么我如何知道异步线程属于哪个请求的问题仍然很明显,我该如何否定这一点?至于使用瞬态范围,它将为每个存储库创建一个新的上下文,这对于使用一个的服务很好,但是当我使用多个(外观模式)将对象拼接在一起并且保存将不起作用,因为来自不同存储库的对象将在不同的跟踪下上下文。
  • 这就是我使用ninject的方式,通过DbContextFactory,它允许我将上下文注入到TransientScope中的存储库中。 :)
  • 对不起,你的这个“postService”字段每个请求依赖使用 Niject 或默认 MVC 的实际情况?
  • 如果您不密集编译到 IOC,请尝试使用 Autofac 轻松构建上下文,并使用此 action 进行简单构建

标签: c# asp.net-mvc asp.net-mvc-5 async-await c#-5.0


【解决方案1】:

在您的帖子和相关的 cmets 中有一些很好的例子来说明如何做到这一点。

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

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

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

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

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

  • 您的商品是否短缺?
  • 如果没有,您的项目是否受 CPU 限制?

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

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

【讨论】:

    猜你喜欢
    • 2016-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    相关资源
    最近更新 更多