我正在将一个正在运行的linq管道升级到异步,我正在使用synthaxe / logic(在task.run,async / await,Tolist ......)进行一些努力。 目前它不会编译,因为最后一个方法返回IEnumerable的Task产品而不是IEnumerable产品
这是电话:
public async Task<IEnumerable<ProductDto>> GetProducts(bool isLogged)
{
return await _mapper.GetStripeProductsDto(isLogged, false);
}
其中一个回购:
public async Task<IEnumerable<StripeProduct>> GetAllStripeProductsAsync()
{
return (await _productService.ListAsync())
.Where(x => x.Type == "good" && x.Active == true);
}
我在哪里建立我的dto并且正在努力:
public async Task<IEnumerable<ProductDto>> GetStripeProductsDto(bool isLogged, bool isSubscriber)
{
var productList = (await _productRepo.GetAllStripeProductsAsync()).ToList();
return await Task.Run(async () =>
GetSkuOffers(productList)
.Concat(await GetSubsciptionOffers(productList))
.GroupBy(product => product.Name)
.Select(productGroup => new ProductDto
{
Name = productGroup.Key,
Id = productGroup.Select(product => product.Id).First(),
Description = productGroup.Select(product => product.Description).First(),
Image = productGroup.Select(product => product.Image).First(),
CurrentUserProfile = isSubscriber
? OfferTypeEnum.Pro.ToString()
: isLogged
? OfferTypeEnum.Registered.ToString()
: OfferTypeEnum.Basic.ToString(),
Prices = productGroup.Select(product => new
{
Offer = product.OfferType.ToString(),
Price = product.Price.ToString()
})
.ToDictionary(p => p.Offer, p => p.Price)
})
.ToList())
.ConfigureAwait(false);
}
private IEnumerable<Product> GetSkuOffers(IEnumerable<StripeProduct> productList)
{
return productList
.SelectMany(sku => sku.Skus.Data, (product, sku) => new Product
{
Name = product.Name,
Id = product.Id,
Image = new Uri(product.Images.First()),
Description = product.Description,
OfferType = sku.Id.Contains("Basic") ? OfferTypeEnum.Basic : OfferTypeEnum.Registered,
Price = sku.Price
});
}
private IEnumerable<Product> GetSubsciptionOffers(IEnumerable<StripeProduct> productList)
{
return
productList
.Select(async product => new Product
{
Name = product.Name,
Id = product.Id,
Image = new Uri(product.Images.First()),
Description = product.Description,
OfferType = OfferTypeEnum.Pro,
Price = (await _planRepo.GetPlanByIdAsync(product.Metadata.First().Value)).Amount.GetValueOrDefault()
});
}
编辑:编译版本,ToListAsync似乎只适用于DB,我的repo调用api,所以我放弃了;我删除了Task.Run(...),并以可能令人讨厌的方式摆脱了IEnumerable的任务产品
public async Task<IEnumerable<ProductDto>> GetStripeProductsDto(bool isLogged, bool isSubscriber)
{
var productList = (await _productRepo.GetAllStripeProductsAsync()).ToList();
var skuOffers = GetSkuOffers(productList);
var subsciptionOffers = GetSubsciptionOffers(productList);
return skuOffers
.Concat(subsciptionOffers)
.GroupBy(product => product.Name)
.Select(productGroup => new ProductDto
{
Name = productGroup.Key,
Id = productGroup.Select(product => product.Id).First(),
Description = productGroup.Select(product => product.Description).First(),
Image = productGroup.Select(product => product.Image).First(),
CurrentUserProfile = isSubscriber
? OfferTypeEnum.Pro.ToString()
: isLogged
? OfferTypeEnum.Registered.ToString()
: OfferTypeEnum.Basic.ToString(),
Prices = productGroup.Select(product => new
{
Offer = product.OfferType.ToString(),
Price = product.Price.ToString()
})
.ToDictionary(p => p.Offer, p => p.Price)
})
.ToList();
}
private IEnumerable<Product> GetSkuOffers(IEnumerable<StripeProduct> productList)
{
return productList
.SelectMany(sku => sku.Skus.Data, (product, sku) => new Product
{
Name = product.Name,
Id = product.Id,
Image = new Uri(product.Images.First()),
Description = product.Description,
OfferType = sku.Id.Contains("Basic") ? OfferTypeEnum.Basic : OfferTypeEnum.Registered,
Price = sku.Price
});
}
private IEnumerable<Product> GetSubsciptionOffers(IEnumerable<StripeProduct> productList)
{
return productList
.Select(product => new Product
{
Name = product.Name,
Id = product.Id,
Image = new Uri(product.Images.First()),
Description = product.Description,
OfferType = OfferTypeEnum.Pro,
//Price = _planRepo.GetPlanById(product.Metadata.First().Value).Amount.GetValueOrDefault()
Price = GetSubscriptionPrice(product.Metadata.First().Value)
}).ToList();
}
private int GetSubscriptionPrice(string str)
{
var plan = Task.Run(() => _planRepo.GetPlanByIdAsync(str)).GetAwaiter().GetResult();
return plan.Amount.GetValueOrDefault();
}
答案 0 :(得分:0)
我会做这样的事情:
public async Task<IEnumerable<ProductDto>> GetProductsAsync(bool isLogged)
{
return await _mapper.GetStripeProductsDto(isLogged, false);
}
public async Task<IEnumerable<StripeProduct>> GetAllStripeProductsAsync()
{
var list = await _productService.ListAsync();
return await list.Where(x => x.Type == "good" && x.Active == true).ToListAsync();
}
public async Task<IEnumerable<ProductDto>> GetStripeProductsDtoAsync(bool isLogged, bool isSubscriber)
{
// here you're making async call and when task is done, you are making .ToList() on results
var productList = await _productRepo.GetAllStripeProductsAsync();
// this will be executed when productList has results from database (task).
// Because GetSkuOffers() method is sync you can execute this like below.
var skuOffersResult = GetSkuOffers(productList);
// get asynchronously subscription offers
var getSubscriptionOffers = await GetSubsciptionOffers(productList);
// this is done also synchronously so you don't need to use async/await statements
skuOffersResult.Concat(getSubscriptionOffers)
.GroupBy(product => product.Name)
.Select(productGroup => new ProductDto
{
Name = productGroup.Key,
Id = productGroup.Select(product => product.Id).First(),
Description = productGroup.Select(product => product.Description).First(),
Image = productGroup.Select(product => product.Image).First(),
CurrentUserProfile = isSubscriber
? OfferTypeEnum.Pro.ToString()
: isLogged
? OfferTypeEnum.Registered.ToString()
: OfferTypeEnum.Basic.ToString(),
Prices = productGroup.Select(product => new
{
Offer = product.OfferType.ToString(),
Price = product.Price.ToString()
})
.ToDictionary(p => p.Offer, p => p.Price)
})
.ToList());
}
private IEnumerable<Product> GetSkuOffers(IEnumerable<StripeProduct> productList)
{
return productList
.SelectMany(sku => sku.Skus.Data, (product, sku) => new Product
{
Name = product.Name,
Id = product.Id,
Image = new Uri(product.Images.First()),
Description = product.Description,
OfferType = sku.Id.Contains("Basic") ? OfferTypeEnum.Basic : OfferTypeEnum.Registered,
Price = sku.Price
});
}
private async Task<IEnumerable<Product>> GetSubsciptionOffers(IEnumerable<StripeProduct> productList)
{
return
productList
.Select(async product => new Product
{
Name = product.Name,
Id = product.Id,
Image = new Uri(product.Images.First()),
Description = product.Description,
OfferType = OfferTypeEnum.Pro,
Price = (await _planRepo.GetPlanByIdAsync(product.Metadata.First().Value)).Amount.GetValueOrDefault()
});
}
如何使用async / await的简单示例: 假设您有使用存储库获取产品列表的服务 - 所有这些服务现在都是同步的:
public class Repository : IRepository
{
public List<Product> GetProducts()
{
return _dbContext.Products.ToList();
}
}
public class Service : IService
{
private readonly IRepository _repository;
public Service(IRepository repository)
{
_repository = repository;
}
public List<Product> GetProductsFromDb()
{
return _repository.GetProducts();
}
}
现在您要更改此代码以使其异步工作:
public class Repository : IRepository
{
public async Task<List<Product>> GetProductsAsync()
{
return await _dbContext.Products.ToListAsync();
}
}
public class Service : IService
{
private readonly IRepository _repository;
public Service(IRepository repository)
{
_repository = repository;
}
public async Task<List<Product>> GetProductsFromDbAsync()
{
return await _repository.GetProductsAsync();
}
}