2017-02-20 39 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

我完全理解,它不是一个异步方法,只需查看签名即可。谢谢你的时间。 –