2017-02-20 3 views
0

Надеюсь, я могу четко объяснить себя, поскольку я довольно новичок в async/await и Task.Асинхронное программирование с пользовательской структурой DTO и Entity Framework

В основном я иду по пути обучения асинхронному программированию, в то время как в принципе я полностью понимаю концепцию и когда это лучше всего применять.

Хотя в моем проекте я, возможно, немного поехал за борт. Поэтому мне всегда нравилось создавать свои собственные DTO, и мне не очень нравится использовать сторонний инструмент (AutoMapper), чтобы сделать это, но потенциально с большим сожалением, потому что я не уверен, как вернуть Task<DTO> из ручного сопоставления.

Если я могу уточнить:

Client Repo

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

    } 
} 

Mapping

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 - позволяет мне чтобы скрыть сложность.

С вышеуказанным я попытался вернуть Task<Client> в методе сопоставления static, но я уверен, что, как вы знаете, это вызывает проблемы с типом.

Каков наилучший подход для возврата асинхронного Task<Client>?

действительно надеюсь, что кто-то может дать мне понять, как и почему?

Очень ценивший,

ответ

2

Обратите внимание на том, что FirstOrDefaultAsync возвращения: Task<Client>. Затем вы пытаетесь передать эту задачу методу, который принимает объект 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

Я полностью понимаю, что это не асинхронный метод, просто глядя на подпись. Спасибо за ваше время. –

Смежные вопросы