public override AppBusinessProcessResult StartBusinessProcess() { AppBusinessProcessResult result = new AppBusinessProcessResult() { OutputData = null, NumberSuccessfullyProcessed = 0, NumberOfExceptions = 0 }; faceClient = new FaceClient( new ApiKeyServiceClientCredentials(subscriptionKey), new System.Net.Http.DelegatingHandler[] { }) { Endpoint = faceEndpoint }; using (SqlConnection conn = RequestContext.OpenAppDBConnection()) { List <Task> tasks = new List <Task>(); Guid idSetRegisterID = Guid.Empty; SPWrapConstituentPhotoAnalysis.USR_USP_CONSTITUENTPHOTOANALYSISPROCESS_GETPARAMETERS.ResultRow parameterRow = SPWrapConstituentPhotoAnalysis.USR_USP_CONSTITUENTPHOTOANALYSISPROCESS_GETPARAMETERS.WrapperRoutines.ExecuteRow(conn, ProcessContext.ParameterSetID); if (parameterRow != null && (parameterRow.IDSETREGISTERID != Guid.Empty)) { idSetRegisterID = parameterRow.IDSETREGISTERID; } else { throw new ServiceException("Could not retrieve parameters."); } SPWrapConstituentPhotoAnalysis.USR_USP_CONSTITUENT_GETPHOTOS.SPResultCollection rows = SPWrapConstituentPhotoAnalysis.USR_USP_CONSTITUENT_GETPHOTOS.WrapperRoutines.ExecuteSP(conn, idSetRegisterID); if (rows != null) { foreach (SPWrapConstituentPhotoAnalysis.USR_USP_CONSTITUENT_GETPHOTOS.ResultRow row in rows.ResultSet) { tasks.Add(AnalyzePhoto(row, result)); } } // Use the business process timeout. If it times out before all tasks complete, errors will occur. Task.WhenAll(tasks).Wait(ProcessCommandTimeout * 1000); } return(result); }
public override AppBusinessProcessResult StartBusinessProcess() { AppBusinessProcessResult result = new AppBusinessProcessResult() { NumberSuccessfullyProcessed = 0, NumberOfExceptions = 0 }; using (SqlConnection conn = this.RequestContext.OpenAppDBConnection(RequestContext.ConnectionContext.BusinessProcess)) { this.UpdateProcessStatus("Retrieving list of active currencies..."); Dictionary<string, Currency> currencies = (Dictionary<string, Currency>)LoadActiveCurrencies(conn); // There are no active currencies in CRM, therefore there is nothing to do if (currencies.Count == 0) { return result; } // The Free Edition of Fixer only supports the Euro as the base currency. If the Euro is not present, there is nothing to do. if (!currencies.ContainsKey(EUR_SYMBOL)) { return result; } this.UpdateProcessStatus("Retrieving process properties..."); LoadProperties(conn); // Initialize third party service _service = new Fixer.Service(_accessKey); this.UpdateProcessStatus("Retrieving list of currencies supported by the rate provider..."); Dictionary<string, string> supportedCurrencies = (Dictionary<string, string>)_service.GetSupportedCurrencies().Symbols; // Remove currencies not supported by the rate provider foreach (var r in currencies.Where(c => !supportedCurrencies.ContainsKey(c.Key)).ToList()) { currencies.Remove(r.Key); } // There are no supported currencies in CRM, therefore there is nothing to do if (currencies.Count == 0) { return result; } // Get exchange rates ExchangeRates rateResponse; this.UpdateProcessStatus("Retrieving currency exchange rates from the rate provider..."); switch (_dateCode) { case Common.DateCode.Latest: rateResponse = _service.GetLatestRates(currencies.Keys.ToList<string>()); break; case Common.DateCode.Historical: rateResponse = _service.GetHistoricalRates(_date, currencies.Keys.ToList<string>()); break; default: throw new ServiceException("Invalid process date code encountered."); } // Prepare to add the rates Guid baseCurrencyId = currencies[rateResponse.Base].Id; DateTime date = rateResponse.Date.AddTicks(rateResponse.Timestamp); Guid timeZoneId = GetTimeZoneId(conn); // Add rates, except the one that goes from base to base. Fixer includes this in the output. foreach(var r in rateResponse.Rates.Where(r => currencies[r.Key].Id != baseCurrencyId)) { // Create request DataFormSaveRequest request = new DataFormSaveRequest() { FormID = new Guid("9b16843e-c20a-4ddf-b31b-1d179380476e"), // CurrencyExchangeRate.Add.xml SecurityContext = new RequestSecurityContext() { SecurityFeatureID = new Guid("37e7492f-9a86-4029-b125-d133f330bf90"), // ExchangeRateRefresh.BusinessProcess.xml SecurityFeatureType = SecurityFeatureType.BusinessProcess }, DataFormItem = new AppFx.XmlTypes.DataForms.DataFormItem() }; // Fill out form request.DataFormItem.SetValue("FROMCURRENCYID", baseCurrencyId); request.DataFormItem.SetValue("TOCURRENCYID", currencies[r.Key].Id); request.DataFormItem.SetValue("TYPECODE", 1); // Daily request.DataFormItem.SetValue("RATE", r.Value); request.DataFormItem.SetValue("ASOFDATETIME", date); request.DataFormItem.SetValue("TIMEZONEENTRYID", timeZoneId); // Save the form try { ServiceMethods.DataFormSave(request, this.RequestContext); result.NumberSuccessfullyProcessed++; } catch { result.NumberOfExceptions++; } } } return result; }
// Detect faces in a local image private async Task AnalyzePhoto(SPWrapConstituentPhotoAnalysis.USR_USP_CONSTITUENT_GETPHOTOS.ResultRow row, AppBusinessProcessResult result) { if (row.PICTURE == null || row.PICTURE.Length == 0) { result.NumberOfExceptions++; return; } try { using (Stream imageStream = new MemoryStream(row.PICTURE)) { IList <DetectedFace> faceList = await faceClient.Face.DetectWithStreamAsync( imageStream, true, false, faceAttributes); try { SaveConstituentPhotoAnalysis(faceList, row.ID); result.NumberSuccessfullyProcessed++; } catch { result.NumberOfExceptions++; } } } catch (APIErrorException e) { throw new Exception(e.Message); } }