2017-07-01 155 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

謝謝你的迴應。現在我已經更新了相似的詳細代碼,請您檢查我的代碼代碼嗎? –