2017-02-20 46 views
0

希望我能夠清楚地解釋我自己,因爲我對async/awaitTask的新手很熟悉。使用自定義DTO和實體框架進行異步編程

基本上我正在走自學異步編程的道路,儘管從根本上說,我完全理解了這個概念,以及何時最適用。

雖然在我的項目中,我可能已經有點過度。所以我一直都很喜歡製作自己的DTO,而且我並不喜歡使用第三方工具(AutoMapper)來做到這一點,但可能會帶來很大的遺憾,因爲我不確定如何從手動映射返回Task<DTO>

如果我可以詳細說明:

客戶回購

public sealed class ClientRepository : IClientRepository 
{ 
    private ClientConfigEntities _context; 

    public ClientRepository(ClientConfigEntities context) 
    { 
     _context = context; 
    } 
    public async Task<Client> AuthenticateAsync(string apiKey, string password) 
    { 
     //Throws error because it cannot return Task<Client> from Client 
     return await MapClient.ToModel(_context.tbl_Client 
        .FirstOrDefaultAsync(c => c.ApiKey == apiKey 
         && c.Password == password)); 

    } 
} 

映射

public static class MapClient 
{ 
    public static Client ToModel(tbl_Client source) 
    { 
     return (source != null) ? new Client 
     { 
      Id = source.Id, 
      ApiKey = source.ApiKey, 
      ApiURL = source.ApiURL, 
      ClientKey = source.ClientKey, 
      Password = source.Password, 
      RetainMeApiKey = source.RetainMeApiKey, 
      Secret = source.Secret 
     } 
     : null; 
    } 
} 

我也有另一個抽象AuthenticationService然後將其稱爲一個Controller - 讓我隱藏複雜性。

以上我已經試過在static映射方法上返回一個Task<Client>,但我相信你知道,它會拋出類型問題。

什麼是返回一個異步Task<Client>?

真希望有人可以給我深入瞭解如何以及爲什麼最好的方法?

大加讚賞,對什麼FirstOrDefaultAsync回報

回答

2

關注:Task<Client>。然後,您嘗試將此任務傳遞給接受客戶端對象而不是Task<Client>的方法。 更改如下:

return MapClient.ToModel(await _context.tbl_Client 
         .FirstOrDefaultAsync(c => c.ApiKey == apiKey 
          && c.Password == password)); 

通過這樣做await _context.tbl_Client.FirstOrDefaultAsync會返回一個客戶對象,一旦任務完成之後,你將模型傳遞到您的配置方法(我也建議你使用extension method代替「正常」靜態方法)。

+0

感謝您的幫助,對於擴展方法提示+1。 –

1

除了Tinwor的回答,OP在使用等待的地方出現了一些混淆。試圖在內聯中執行所需的代碼有助於引起混淆。

重構代碼以使其更易於閱讀和識別應放置等待的代碼的位置,從而顯示代碼的意圖。

public async Task<Client> AuthenticateAsync(string apiKey, string password) { 
    var entity = await _context.tbl_Client.FirstOrDefaultAsync(
     c => c.ApiKey == apiKey && c.Password == password 
    ); 
    var model = MapClient.ToModel(entity); 
    return model; 
} 

轉換的ToModel以擴展方法也可以讓代碼更清潔以及

public static class MapClient { 
    public static Client ToModel(this tbl_Client source) { 
     return (source != null) ? new Client { 
      Id = source.Id, 
      ApiKey = source.ApiKey, 
      ApiURL = source.ApiURL, 
      ClientKey = source.ClientKey, 
      Password = source.Password, 
      RetainMeApiKey = source.RetainMeApiKey, 
      Secret = source.Secret 
     } 
     : null; 
    } 
} 

這將導致最終的代碼看起來像

public async Task<Client> AuthenticateAsync(string apiKey, string password) { 
    var entity = await _context.tbl_Client.FirstOrDefaultAsync(
     c => c.ApiKey == apiKey && c.Password == password 
    ); 
    var model = entity.ToModel();// <-- extension method used here 
    return model; 
} 
+0

真的很感謝你的幫助,與第一個答案一樣......擴展方法肯定有助於保持代碼......感謝你的時間。我可能花更多時間用於異步編程。 –

0

首先,MapClient。 ToModel不是一個異步方法。所以你不能等待這個方法。 其次,您只是映射ToModel方法中的數據。所以沒有必要使它成爲異步。 處理此問題的最佳方法是將「AuthenticateAsync」方法的返回類型僅更改爲客戶端(不是強制性的)。該方法內的代碼可以更改爲 -

return MapClient.ToModel(await _context.tbl_Client.FirstOrDefaultAsync(
     c => c.ApiKey == apiKey && c.Password == password 
    )); 
+0

我完全理解,它不是一個異步方法,只需查看簽名即可。謝謝你的時間。 –