ExecutionResult <Address> IManager.SearchAddress(string address) { try { using (var db = this.CreateUnitOfWork()) { var DadataClient = GetDadataClient(); DaData.Entities.AddressData result = null; if (result == null) { try { var found = db.Repo2.Where(x => x.NameAddressSearch.Equals(address, StringComparison.InvariantCultureIgnoreCase) && x.ServiceFound == "DaData").OrderByDescending(x => x.DateSearch).FirstOrDefault(); if (found != null) { if (found.IsSuccess) { result = Newtonsoft.Json.JsonConvert.DeserializeObject <DaData.Entities.AddressData>(found.ServiceAnswer); } else { var timeoutForNewSearch = TimeSpan.FromDays(5); //Время, в течение которого мы используем старый неудачный результат поиска, чтобы не тратить деньги ЛК DaData. if (DateTime.Now - found.DateSearch < timeoutForNewSearch) { return(new ExecutionResult <Address>(false, "Указанный адрес не найден.")); } } } } catch (Exception ex) { this.RegisterEvent(Journaling.EventType.Error, "Ошибка во время поиска кешированного результата.", $"Адрес: {address}", null, ex); } } if (result == null) { var results = DadataClient.Clean <DaData.Entities.AddressData>(new string[] { address }); if (results.IsSuccess) { if (results.Data != null && results.Data.Count > 0) { var resultPre = results.Data.First(); var history = new AddressSearchHistory() { NameAddressSearch = address, DateSearch = DateTime.Now, IsSuccess = false, AddressType = AddressType.Country, ServiceFound = "DaData", ServiceAnswer = Newtonsoft.Json.JsonConvert.SerializeObject(resultPre) }; var allowed = resultPre.qc == DaData.Constants.QC.QC_OK;//Разрешаем только точные совпадения. if (!allowed && resultPre.qc == DaData.Constants.QC.QC_UNSURE) { int fias_level; if (int.TryParse(resultPre.fias_level, out fias_level)) { if (fias_level >= 7) { allowed = true; //Если точность совпадения - улица, тоже разрешаем. } if (fias_level == 6 && string.IsNullOrEmpty(resultPre.city_kladr_id) && !string.IsNullOrEmpty(resultPre.settlement_kladr_id)) { allowed = true; //Если точность совпадения - некрупный населенный пункт, тоже разрешаем. } } } if (allowed) { result = resultPre; history.IsSuccess = true; history.KodAddress = result.kladr_id; history.ServiceAnswer = Newtonsoft.Json.JsonConvert.SerializeObject(result); } db.Repo2.Add(history); db.SaveChanges(); } } else { if (results.Code == 402) { _cachedEvents.GetOrAddWithExpiration("account_balance_empty", (k) => { this.RegisterServiceState(ServiceStatus.CannotRunBecouseOfErrors, "Пополните баланс на счете Дадаты - не работают стандартизация и подсказки."); return(DateTime.Now); }, TimeSpan.FromMinutes(5)); return(new ExecutionResult <Address>(false, "Поиск недоступен - недостаточно средств на счете Дадаты.")); } else { this.RegisterServiceState(ServiceStatus.CannotRunBecouseOfErrors, "Необработанная ошибка в ответе сервиса.", new Exception($"Код ответа {results.Code}, текст: {results.Detail}")); return(new ExecutionResult <Address>(false, "Необработанная ошибка в ответе сервиса.")); } } } var prepareResult = PrepareAddressDataIntoDB(address, result, db); return(new ExecutionResult <Address>(prepareResult != null, null, prepareResult)); } } catch (Exception ex) { this.RegisterEvent(Journaling.EventType.Error, "Ошибка во время обработки результата поиска.", $"SearchAddress: {address}", null, ex); return(new ExecutionResult <Address>(false, "Ошибка во время обработки результата поиска.")); } }
private ExecutionResult <Address> GetAddressByQuery(string addressString, Func <string, DaData.Entities.Suggestions.Suggestion <DaData.Entities.AddressData> > suggectionProvider) { try { using (var db = this.CreateUnitOfWork()) { DaData.Entities.AddressData result = null; if (result == null) { try { var found = db.Repo2.Where(x => x.NameAddressSearch.Equals(addressString, StringComparison.InvariantCultureIgnoreCase) && x.ServiceFound == "DaData" && x.AddressType == AddressType.IP_Address).OrderByDescending(x => x.DateSearch).FirstOrDefault(); if (found != null) { if (found.IsSuccess) { result = Newtonsoft.Json.JsonConvert.DeserializeObject <DaData.Entities.AddressData>(found.ServiceAnswer); } else { var timeoutForNewSearch = TimeSpan.FromMinutes(5); //Время, в течение которого мы используем старый неудачный результат поиска, чтобы не тратить счетчик подсказок DaData. if (DateTime.Now - found.DateSearch < timeoutForNewSearch) { return(new ExecutionResult <Address>(false, "Указанный адрес не найден.")); } } } } catch (Exception ex) { this.RegisterEvent(Journaling.EventType.Error, "Ошибка во время поиска кешированного результата.", $"Адрес: {addressString}", null, ex); } } AddressSearchHistory history = null; if (result == null) { history = new AddressSearchHistory() { NameAddressSearch = addressString, DateSearch = DateTime.Now, IsSuccess = false, AddressType = AddressType.IP_Address, ServiceFound = "DaData" }; var suggestion_result = suggectionProvider(addressString); if (suggestion_result != null) { result = suggestion_result.data; Debug.WriteLineNoLog("GetAddressByQuery: {0}", addressString); Debug.WriteLineNoLog(Newtonsoft.Json.JsonConvert.SerializeObject(result)); history.IsSuccess = true; history.KodAddress = result.kladr_id; history.ServiceFound = "DaData"; history.ServiceAnswer = Newtonsoft.Json.JsonConvert.SerializeObject(result); } db.Repo2.Add(history); db.SaveChanges(); } var prepareResult = PrepareAddressDataIntoDB(addressString, result, db); if (prepareResult != null && history != null) { history.AddressType = prepareResult.AddressType; db.SaveChanges(); throw new NotImplementedException("Здесь надо проверить корректность заполнения AddressType в базе после повторного вызова SaveChanges."); } return(new ExecutionResult <Address>(prepareResult != null, null, prepareResult)); } } catch (NotImplementedException) { throw; } catch (Exception ex) { this.RegisterEvent(Journaling.EventType.Error, "Ошибка во время обработки результата поиска.", $"GetAddressByQuery: {addressString}", null, ex); return(new ExecutionResult <Address>(false, "Ошибка во время обработки результата поиска.")); } }