2017-07-01 196 views
0

我'试图以异步方式运行我的控制器操作运行。 如何使用异步任务?或如何在异步方式运行如何使用异步任务<IActionResult>?或如何以异步方式在我的Asp.Net核心网络API

// Db context 
public class DeptContext : DbContext 
{ 
    public LagerContext(DbContextOptions<LagerContext> options) 
     : base(options) 
    { 

     Database.Migrate(); 
    } 

    public DbSet<Department> Departments { get; set; } 
    public DbSet<Product> Products { get; set; } 


} 

//这是我的接口IDepRepository

Task<Department> GetDepartmentWithOrWithoutProducts(int deptId, bool includeProducts); 

//我的仓储类DepRepository

public class DepRepository : IDepRepository 
{ 
    private DeptContext db; 
    public DepRepository(DeptContext context) 
    { 
     db = context; 
    } 

    // I'am geting Department name with products or Without products 

    public async Task<Department> GetDepartmentWithOrWithoutProducts(int deptId, bool includeProducts) 
    { 
     if(includeProductss) 
     { 
      return await db.Departments.Include(c => c.Products).Where(s => s.deptId == deptId).SingleAsync(); 
     } 
       return await db.Departments.Where(s => s.deptId == deptId).SingleAsync(); 
    } 
} 

所以我应该如何现在做我的控制器这样做的异步方式:我尝试如下,但我不知道这是否是正确的做这样的下面: 我没有得到任何错误,但我不知道如果这是正确的方式...

using System.Threading.Tasks; 
using System.Net; 
using Microsoft.Data.Entity; 
using Microsoft.EntityFrameworkCore; 

[Route("api/departments")] 
public class DepartmentsController : Controller 
{ 
    private IDeptRepository _deptInfoRepository; 

    public DepartmentsController(IDeptRepository deptInfoRepository) 
    { 
     _deptInfoRepository = deptInfoRepository; 
    } 

    [HttpGet("{id}")] 
    public async Task<IActionResult> GetDepatment(int id, bool includeProducts = false) 
    { 
     var dept = _deptInfoRepository.GetDepartmentWithOrWithoutProducts(id, includeComputers); 
     if(dept == null) 
     { 
      return BadRequest(); 
     } 

     if(includeProducts) 
     { 
      var depResult = new DepartmentDto() { deptId = dept.deptId, deptName = dept.deptName }; 
      foreach(var department in dept.Products) 
      { 
       depResult.Products.Add(new ProductDto() { productId = department.productId, deptId = department.deptId, ProductName =      department.ProductName }); 
      } 

      return Ok(depResult); 
     } 

     var departmentWithoutProductResult = new DepartmentsWithoutProductsDto() { DeptId = dept.deptId, DeptName = dept.DeptName}; 
     return Ok(departmentWithoutProductResult); 


    } 

我该如何做到异步的方式我的控制器..我不知道在哪里把这些await和ToListAsync()。先谢谢你!

+0

'ToListAsync'作为'IQueryable'扩展名而不是'IEnumerable'扩展名存在。 List不实现'IQueryable'。你有'GetDepartments'的异步版本吗?如果是这样,你可以等待那个电话。 –

+0

@ R.Richards感谢您的回复。你的意思是,如果我在我的GetDepartments中有异步并等待,那就足够了? –

+0

不是。你需要的是GetDepartments的异步版本。这里的答案暗示了这一点。 GetDepartmentsAsync会返回任何GetDepartments返回的任务<>。这是必需的,因为如果没有基于任务的函数,就不能有效地使用async/await。 [看到这个](https://stackoverflow.com/questions/14455293/how-and-when-to-use-async-and-await)。 –

回答

0

的接口应该被重新命名为更好地展示意图。

public interface IDepRepository { 
    Task<Department> GetDepartmentWithOrWithoutProductsAsync(int deptId, bool includeProducts); 
    //... 
} 

哪一个会相应地更新实施。由于该方法实际上并没有在异步调用之后使用任何东西,因此没有任何理由将该方法标记为异步。只需返回任务。

public Task<Department> GetDepartmentWithOrWithoutProductsAsync(int deptId, bool includeProducts) { 
    if(includeProductss) { 
     return db.Departments.Include(c => c.Products).Where(s => s.deptId == deptId).SingleAsync(); 
    } 
    return db.Departments.Where(s => s.deptId == deptId).SingleAsync(); 
} 

控制器动作但是需要等待的任务,然后继续后,任务完成等于是该方法将被标记为异步。

[HttpGet("{id}")] 
public async Task<IActionResult> GetDepatment(int id, bool includeProducts = false) { 
    var dept = await _deptInfoRepository.GetDepartmentWithOrWithoutProductsAsync(id, includeComputers); 
    if (dept == null) { 
     return BadRequest(); 
    } 
    if (includeProducts) { 
     var depResult = new DepartmentDto() { deptId = dept.deptId, deptName = dept.deptName }; 
     foreach (var department in dept.Products) { 
      depResult.Products.Add(new ProductDto() { 
       productId = department.productId, 
       deptId = department.deptId, 
       ProductName = department.ProductName 
      }); 
     } 
     return Ok(depResult); 
    } 
    var departmentWithoutProductResult = new DepartmentsWithoutProductsDto() { DeptId = dept.deptId, DeptName = dept.DeptName}; 
    return Ok(departmentWithoutProductResult); 
} 
0

你不应该做任何await已经准备results名单上。它已经包含了所需的数据 - 你想等待什么?

你应该让新的异步版本的GetDepartments()方法和等待,同时从资源库中获取数据:

var depEntities = await _depRepository.GetDepartmentsAsync(); 
+0

谢谢你的回应。现在我已经更新了相似的详细代码,请您检查我的代码代码吗? –

+1

现在你应该等待'var dept = await _deptInfoRepository.GetDepartmentWithOrWithout ...',否则你的代码将无法编译/工作('dept'是'Task',而不是'Department')。并且为方法名添加'Async'后缀(如果可能的话)以澄清它是异步的。 – Dmitry

0

我无法从你的代码告诉是什么GetDepartments返回的数据类型。我的猜测是你正在使用EF Core并且GetDepartments返回一个DbSet或者一个针对DbSet的LINQ查询。如果是这样的话,那么在您depEntities变量设置,行之后变量指向一个延迟对象(尚未evaulated又一个表达式树)。换句话说,实际的查询还没有被发送到数据库。当循环遍历depEntities(使用foreach循环)时,会导致发生实际可能长期运行的工作(数据库访问)。这就是你想要等待的。所以,是的,你可以把GetDepartments的异步版本,或者你也很可能改变你的代码:

var depEntities = await _depRepository.GetDepartments().ToListAsync(); 

到ToListAsync呼叫将枚举递延对象,并进行数据库访问。你的return语句只会返回结果。在幕后,该方法实际上会在您的await语句中返回,并在您等待完成的工作后继续。最后

一注..任何数据库异常将发生在那里的递延对象被列举的点。

+0

谢谢你的回应。现在我已经更新了相似的详细代码,请您检查我的代码代码吗? –