Есть вот такой класс из слоя бизнес-логики:
public class ProductService
{
private readonly IGenericRepository<Product> _productRepository;
public ProductService(IGenericRepository<Product> productRepository)
{
_productRepository = productRepository;
}
public Task Update(int id, ProductModel model)
{
return Task.Run(() =>
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
var product = _productRepository.GetById(id);
if (product == null)
{
throw new ArgumentException(nameof(id));
}
// еще код... //
_productRepository.Update(product);
});
}
}
Я поймал себя на том, что у меня все методы, обращающиеся к базе данных (даже если они обращаются через репозитории), возвращают Task, так как знаю, что выше у меня Web API контроллер, action которого я хочу вызывать асинхронно.
Я думаю, что я делаю неправильно, потому что, проектируя класс ProductService я не должен заботиться о клиентском коде. Сейчас да, у меня клиентом является самый верхний слой (Web API), но так ведь может быть не всегда и для другого клиента возможно тип Task метода Update может быть излишним. Я прав?
Согласно своим рассуждениям я переписал методProductService.Update() и класс-клиент:
public void Update(int id, ProductModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
var product = _productRepository.GetById(id);
if (product == null)
{
throw new ArgumentException(nameof(id));
}
// еще код... //
_productRepository.Update(product);
}
[RoutePrefix("api/products")]
public class ProductsController : ApiController
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[HttpPut]
[Route("{id:int}")]
public async Task<IHttpActionResult> Put([FromBody] productModel)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var productId = (int)RequestContext.RouteData.Values["id"];
await Task.Run(() =>
{
_productService.Update(productId, productModel);
});
return Ok();
}
ProductsControlers.Put()автоматически создается отдельная нитьProductsControlers.Put() -> ProductService.Update() -> GenericRepoisoty<Product>.Update()? – Adam Shakhabov Jul 25 '17 at 12:44await Task.Run. Сейчас у вас используются две разные нити для той же цели. – Pavel Mayorov Jul 25 '17 at 12:47ProductService.Update(), убираюasync/await/Task.Run()изProductsController.Put()и каждый запрос клиента на обновление сущностиProductбудет выполняться асинхронно, так? – Adam Shakhabov Jul 25 '17 at 12:53