У меня есть следующий вариант использования, FetchDataService
(внедренный как область действия), извлекающий данные из API с использованием httpClient.
Затем служба анализирует данные и запускает await SaveAsync
их в базу данных.
Все до этого момента прекрасно работает.
Затем я добавил еще одну службу: AddressEnrichmentService
(внедренную как область действия), которая на этапе анализа анализирует внешнюю службу асинхронно и приносит больше данных.
Эта служба искажает весьприложение. Я получаю случайные исключения из обработчика базы данных (NHibernate), который указывает на некоторые проблемы с потоками. Я действительно не могу положить на это свой палец. несколько разных случайных исключений ... Эти исключения генерируются при запуске await SaveAsync
. (Я добавлю их в конце).
public async Task Fetch(string url, UserModel userModel ){
string res = null;
using (var httpClient = new HttpClient()){
res = await httpClient.GetStringAsync(url);
}
await databaseLogRepository.SaveAsync(new Log{Message = "The data is here..." + res});
var profile = JsonConvert.DeserializeObject<ProfileModel >(res);
profile.Data.Locations.ForEach(async x =>
{
var address = await addressEnrichmentService.EnrichAsync(x.StreetAddress + " " + x.Locality + " " + x.Country);
userModel.Address = address;
await databaseLogRepository.SaveAsync(new Log{Message = "enriched address"});
});
}
Проблемный сервис:
public class AddressEnrichmentService : IAddressEnrichmentService
{
public async Task<AddressModel> EnrichAsync(string address)
{
string res = null;
using (HttpClient client = new HttpClient())
{
var url = "https://maps.googleapis.com/maps/api/geocode/json?key=__KEY__&address=" + HttpUtility.UrlEncode(address);
res = await client.GetStringAsync(url);// probably the problematic row
}
return JsonConvert.DeserializeObject<AddressModel>(res);
}
}
Использование
UserModel userModel = new UserModel();
await fetchDataService.Fetch(url, userModel);
await userRepo.SaveAsync(userModel);
Снова addressEnrichmentService.EnrichAsync
все портит,Как я узнаю, что EnrichAsync
все испортило?
, если я конвертирую res = await client.GetStringAsync(url);
в res = client.GetStringAsync(url).GetAwaiter().GetResult();
, я не получаю никакой ошибки. 100 раз из 100 попыток я не получаю ошибки. если я возвращаю его к res = await client.GetStringAsync(url);
, я каждый раз получаю сообщение об ошибке.
Об исключениях, опять же, я получаю некоторые признаки того, что ошибка связана с параллелизмом, это метод сохранения:
public async Task<T> SaveAsync(T entity)
{
using (var tr = session.BeginTransaction())
{
//session is injected as scoped
await session.SaveOrUpdateAsync(entity);
tr.Commit();
}
return entity;
}
MySqlException: There is already an open DataReader associated with this Connection which must be closed first.
NHibernate.HibernateException: 'Flush during cascade is dangerous'