/// <summary> /// Get an entity. /// </summary> /// <typeparam name="TEntity">Type of entity to load, must have an mapper registered in <see cref="EntityMappingProvider"/>.</typeparam> /// <param name="unitOfWork">UnitOfWork to invoke <c>ExecuteReaderAsync()</c> on (through a created <c>DbCommand</c>).</param> /// <param name="query">Query or short query (<c><![CDATA["projectId = @id AND dateCreated < @minDate"]]></c>)</param> /// <param name="parameters">Anonymous object (<c>new { id = dto.ProjectId, @minDate = dto.MinDate }</c>), a dictionary or a value array</param> /// <returns>Found entity</returns> /// <remarks> /// <para>Uses <see cref="EntityMappingProvider"/> to find the correct <c><![CDATA[ICrudEntityMapper<TEntity>]]></c></para> /// </remarks> /// <example> /// <code> /// <![CDATA[ /// public async Task<User> GetUser(int userId) /// { /// return await _connection.FirstAsync<User>("WHERE id = @id", new { id = UserId }); /// } /// ]]> /// </code> /// <para> /// Which will translate into: /// </para> /// <code> /// command.CommandText = "SELECT * FROM Users WHERE id = @id"; /// var p = command.CreateParameter(); /// p.Name = "id"; /// p.Value = userId; /// command.Parameters.Add(p); /// </code> /// </example> /// <exception cref="EntityNotFoundException">Failed to find an entity mathing the query</exception> public static Task <TEntity> FirstAsync <TEntity>(this IAdoNetUnitOfWork unitOfWork, string query, object parameters) { if (unitOfWork == null) { throw new ArgumentNullException("unitOfWork"); } if (query == null) { throw new ArgumentNullException("query"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } var mapping = EntityMappingProvider.GetMapper <TEntity>(); using (var cmd = unitOfWork.CreateDbCommand()) { cmd.ApplyQuerySql(mapping, query, parameters); return(cmd.FirstAsync(mapping)); } }
/// <summary> /// Return an enumerable which uses lazy loading of each row. /// </summary> /// <typeparam name="TEntity">Type of entity to map</typeparam> /// <param name="unitOfWork">Connection to invoke <c>ExecuteReader()</c> on (through a created <c>DbCommand</c>).</param> /// <param name="ownsConnection"> /// <c>true</c> if the connection should be disposed together with the command/datareader. See /// remarks. /// </param> /// <param name="query">Query or short query (<c>"id = @1"</c>)</param> /// <param name="parameters"></param> /// <returns>Lazy loaded enumerator</returns> /// <remarks> /// <para> /// For more information about the "query" and "parameters" arguments, see <see cref="CommandExtensions.ApplyQuerySql{TEntity}"/>. /// </para> /// <para> /// The returned enumerator will not map each row until it's requested. To be able to do that the /// connection/command/datareader is /// kept open until the enumerator is disposed. Hence it's important that you make sure that the enumerator is /// disposed when you are /// done with it. /// </para> /// <para>Uses <see cref="EntityMappingProvider" /> to find the correct <c><![CDATA[IEntityMapper<TEntity>]]></c>.</para> /// </remarks> /// <example> /// <code> /// // All these examples are valid: /// <![CDATA[ /// var users = unitOfWork.ToEnumerable<User>(true, "Age < 10"); /// var users = unitOfWork.ToEnumerable<User>(true, "SELECT * FROM Users WHERE Age = 37"); /// var users = unitOfWork.ToEnumerable<User>(true, "FirstName = @name", new { name = user.FirstName }); /// var users = unitOfWork.ToEnumerable<User>(true, "FirstName = @1 AND Age < @2", 'A%', 35); /// var users = unitOfWork.ToEnumerable<User>(true, "SELECT * FROM Users WHERE Age = @age LIMIT 1, 10", new { age = submittedAge }); /// var users = unitOfWork.ToEnumerable<User>(true, "SELECT * FROM Users WHERE Age = @1 LIMIT 1, 10", user.FirstName); /// ]]> /// </code> /// </example> public static IEnumerable <TEntity> ToEnumerable <TEntity>(this IAdoNetUnitOfWork unitOfWork, bool ownsConnection, string query, params object[] parameters) { if (unitOfWork == null) { throw new ArgumentNullException("unitOfWork"); } var mapping = EntityMappingProvider.GetMapper <TEntity>(); var cmd = unitOfWork.CreateDbCommand(); try { cmd.ApplyQuerySql(mapping, query, parameters); var reader = cmd.ExecuteReader(); return(new AdoNetEntityEnumerable <TEntity>(cmd, reader, mapping, ownsConnection)); } catch (Exception e) { throw cmd.CreateDataException(e); } }
public async Task <GetSimilaritiesResult> ExecuteAsync(GetSimilarities query) { using (var cmd = _unitOfWork.CreateDbCommand()) { cmd.CommandText = @"select Name, Properties from IncidentContextCollections where IncidentId = @incidentId"; cmd.AddParameter("incidentId", query.IncidentId); var collections = new List <GetSimilaritiesCollection>(); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { var json = (string)reader["Properties"]; var properties = OneTrueSerializer.Deserialize <ContextCollectionPropertyDbEntity[]>(json); var col = new GetSimilaritiesCollection { Name = reader.GetString(0) }; col.Similarities = (from prop in properties let values = prop.Values.Select(x => new GetSimilaritiesValue(x.Value, x.Percentage, x.Count)) select new GetSimilaritiesSimilarity(prop.Name) { Values = values.ToArray() } ).ToArray(); collections.Add(col); } } return(new GetSimilaritiesResult { Collections = collections.ToArray() }); } }
public async Task <GetApplicationVersionsResult> HandleAsync(IMessageContext context, GetApplicationVersions query) { var sql = @"SELECT version, sum(incidentcount) incidentcount, sum(reportcount) reportcount, min(FirstReportDate) as FirstReportDate, max(LastReportDate)as LastReportDate FROM ApplicationVersions join [codeRR].[dbo].ApplicationVersionMonths on (versionid=applicationversions.id) where applicationid=@appId group by version order by version "; using (var cmd = _uow.CreateDbCommand()) { cmd.CommandText = sql; cmd.AddParameter("appId", query.ApplicationId); using (var reader = await cmd.ExecuteReaderAsync()) { var items = new List <GetApplicationVersionsResultItem>(); while (await reader.ReadAsync()) { var item = new GetApplicationVersionsResultItem { Version = reader[0].ToString(), FirstReportReceivedAtUtc = (DateTime)reader[3], LastReportReceivedAtUtc = (DateTime)reader[4], IncidentCount = (int)reader[1], ReportCount = (int)reader[2] }; items.Add(item); } return(new GetApplicationVersionsResult { Items = items.ToArray() }); } } }
public async Task <IReadOnlyList <string> > GetEmailAddressesAsync(int incidentId) { var emailAddresses = new List <string>(); using (var cmd = _unitOfWork.CreateDbCommand()) { cmd.CommandText = "SELECT distinct EmailAddress FROM IncidentFeedback WHERE IncidentId = @id AND EmailAddress IS NOT NULL"; cmd.AddParameter("id", incidentId); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { var email = reader.GetString(0); if (!emailAddresses.Any(x => x.Equals(email, StringComparison.OrdinalIgnoreCase))) { emailAddresses.Add(email); } } } } return(emailAddresses); }
/// <summary> /// Generate a complete list before returning. /// </summary> /// <typeparam name="TEntity">Type of entity to map</typeparam> /// <param name="unitOfWork">Unit of work to invoke <c>ExecuteReaderAsync()</c> on (through a created <c>DbCommand</c>).</param> /// <param name="mapping">Mapping used to translate from db table rows to .NET object</param> /// <param name="query">Query or short query (<c><![CDATA["projectId = @id AND dateCreated < @minDate"]]></c>)</param> /// <param name="parameters">Anonymous object (<c>new { id = dto.ProjectId, @minDate = dto.MinDate }</c>), a dictionary or a value array</param> /// <returns>A list which is generated asynchronously.</returns> /// <remarks> /// <para> /// For more information about the "query" and "parameters" arguments, see <see cref="CommandExtensions.ApplyQuerySql{TEntity}"/>. /// </para> /// <para> /// The returned enumerator will not map each row until it's requested. To be able to do that the /// connection/command/datareader is /// kept open until the enumerator is disposed. Hence it's important that you make sure that the enumerator is /// disposed when you are /// done with it. /// </para> /// <para>Uses <see cref="EntityMappingProvider" /> to find the correct <c><![CDATA[IEntityMapper<TEntity>]]></c>.</para> /// </remarks> /// <example> /// <code> /// // All these examples are valid: /// <![CDATA[ /// var users = await unitOfWork.ToListAsync<User>("Age < 10"); /// var users = await unitOfWork.ToListAsync<User>("SELECT * FROM Users WHERE Age = 37"); /// var users = await unitOfWork.ToListAsync<User>("FirstName = @name", new { name = user.FirstName }); /// var users = await unitOfWork.ToListAsync<User>("FirstName = @1 AND Age < @2", 'A%', 35); /// var users = await unitOfWork.ToListAsync<User>("SELECT * FROM Users WHERE Age = @age LIMIT 1, 10", new { age = submittedAge }); /// var users = await unitOfWork.ToListAsync<User>("SELECT * FROM Users WHERE Age = @1 LIMIT 1, 10", user.FirstName); /// ]]> /// </code> /// </example> public static async Task <List <TEntity> > ToListAsync <TEntity>(this IAdoNetUnitOfWork unitOfWork, ICrudEntityMapper <TEntity> mapping, string query, params object[] parameters) { if (unitOfWork == null) { throw new ArgumentNullException("unitOfWork"); } if (mapping == null) { throw new ArgumentNullException("mapping"); } if (query == null) { throw new ArgumentNullException("query"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } var cmd = unitOfWork.CreateDbCommand(); cmd.ApplyQuerySql(mapping, query, parameters); var items = new List <TEntity>(); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { var entity = mapping.Create(reader); mapping.Map(reader, entity); items.Add((TEntity)entity); } } return(items); }
public async Task <GetOverviewResult> ExecuteAsync(GetOverview query) { if (query.NumberOfDays == 0) { query.NumberOfDays = 30; } if (query.NumberOfDays == 1) { return(await GetTodaysOverviewAsync(query)); } var apps = new Dictionary <int, GetOverviewApplicationResult>(); var labels = new string[query.NumberOfDays + 1]; //+1 for today var startDate = DateTime.Today.AddDays(-query.NumberOfDays); for (var i = 0; i <= query.NumberOfDays; i++) { labels[i] = startDate.AddDays(i).ToShortDateString(); } var result = new GetOverviewResult(); using (var cmd = _unitOfWork.CreateDbCommand()) { cmd.CommandText = @"select Applications.Id, Applications.Name, cte.Date, cte.Count FROM ( select Incidents.ApplicationId , cast(Incidents.CreatedAtUtc as date) as Date, count(Incidents.Id) as Count from Incidents where Incidents.CreatedAtUtc >= @minDate group by Incidents.ApplicationId, cast(Incidents.CreatedAtUtc as date) ) cte right join applications on (applicationid=applications.id) ;"; cmd.AddParameter("minDate", startDate); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { var appId = reader.GetInt32(0); GetOverviewApplicationResult app; if (!apps.TryGetValue(appId, out app)) { app = new GetOverviewApplicationResult(reader.GetString(1), startDate, query.NumberOfDays + 1); //+1 for today apps[appId] = app; } //no stats at all for this app if (reader[2] is DBNull) { var startDate2 = DateTime.Today.AddDays(-query.NumberOfDays + 1); for (var i = 0; i < query.NumberOfDays; i++) { app.AddValue(startDate2.AddDays(i), 0); } } else { app.AddValue(reader.GetDateTime(2), reader.GetInt32(3)); } } result.TimeAxisLabels = labels; result.IncidentsPerApplication = apps.Values.ToArray(); } } await GetStatSummary(query, result); return(result); }
public async Task <GetCollectionResult> HandleAsync(IMessageContext context, GetCollection query) { if (query.MaxNumberOfCollections == 0) { query.MaxNumberOfCollections = 1; } var sql = @"WITH ReportsWithCollection (ErrorReportId) AS ( select distinct TOP(10) ErrorReports.Id FROM ErrorReports JOIN ErrorReportCollectionProperties ep ON (ep.ReportId = ErrorReports.Id) WHERE ep.Name = @collectionName AND ErrorReports.IncidentId=@incidentId ) select erp.PropertyName, erp.Value, ErrorReports.CreatedAtUtc, ErrorReports.Id ReportId from ErrorReportCollectionProperties erp join ReportsWithCollection rc on (erp.ReportId = rc.ErrorReportId) join ErrorReports on (ErrorReports.ID = rc.ErrorReportId) WHERE erp.Name = @collectionName"; var items = new List <GetCollectionResultItem>(); using (var cmd = _unitOfWork.CreateDbCommand()) { cmd.CommandText = sql; cmd.AddParameter("incidentId", query.IncidentId); cmd.AddParameter("collectionName", query.CollectionName); using (var reader = await cmd.ExecuteReaderAsync()) { GetCollectionResultItem item = null; var lastReportId = 0; while (reader.Read()) { var reportId = (int)reader["ReportId"]; if (reportId != lastReportId || item == null) { item = new GetCollectionResultItem { ReportId = (int)reader["ReportId"], ReportDate = (DateTime)reader["CreatedAtUtc"], Properties = new Dictionary <string, string>() }; items.Add(item); } lastReportId = reportId; var key = (string)reader["PropertyName"]; var value = (string)reader["Value"]; if (item.Properties.ContainsKey(key)) { _logger.Info( $"Report {reportId} have value for key {key} current: {item.Properties[key]} new: {value}."); } else { item.Properties.Add(key, value); } } } } return(new GetCollectionResult { Items = items.ToArray() }); }
public async Task <GetApplicationOverviewResult> ExecuteAsync(GetApplicationOverview query) { if (query.NumberOfDays == 0) { query.NumberOfDays = 30; } if (query.NumberOfDays == 1) { return(await GetTodaysOverviewAsync(query)); } var curDate = DateTime.Today.AddDays(-query.NumberOfDays); var errorReports = new Dictionary <DateTime, int>(); var incidents = new Dictionary <DateTime, int>(); while (curDate <= DateTime.Today) { errorReports[curDate] = 0; incidents[curDate] = 0; curDate = curDate.AddDays(1); } var result = new GetApplicationOverviewResult(); using (var cmd = _unitOfWork.CreateDbCommand()) { var sql = @"select cast(Incidents.CreatedAtUtc as date), count(Id) from Incidents where Incidents.CreatedAtUtc >= @minDate AND Incidents.CreatedAtUtc <= GetUtcDate() {0} group by cast(Incidents.CreatedAtUtc as date); select cast(ErrorReports.CreatedAtUtc as date), count(Id) from ErrorReports where ErrorReports.CreatedAtUtc >= @minDate AND ErrorReports.CreatedAtUtc <= GetUtcDate() {1} group by cast(ErrorReports.CreatedAtUtc as date);"; if (query.ApplicationId > 0) { cmd.CommandText = string.Format(sql, " AND Incidents.ApplicationId = @appId", " AND ErrorReports.ApplicationId = @appId"); cmd.AddParameter("appId", query.ApplicationId); } else { cmd.CommandText = string.Format(sql, "", ""); } cmd.AddParameter("minDate", DateTime.Today.AddDays(-query.NumberOfDays)); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { incidents[(DateTime)reader[0]] = (int)reader[1]; } await reader.NextResultAsync(); while (await reader.ReadAsync()) { errorReports[(DateTime)reader[0]] = (int)reader[1]; } result.ErrorReports = errorReports.Select(x => x.Value).ToArray(); result.Incidents = incidents.Select(x => x.Value).ToArray(); result.TimeAxisLabels = incidents.Select(x => x.Key.ToShortDateString()).ToArray(); } } await GetStatSummary(query, result); return(result); }
public async Task <GetOverviewResult> HandleAsync(IMessageContext context, GetOverview query) { if (query.NumberOfDays == 0) { query.NumberOfDays = 30; } var labels = CreateTimeLabels(query); var isSysAdmin = context.Principal.IsSysAdmin(); var gotApps = context.Principal.FindAll(x => x.Type == CoderrClaims.Application).Any(); if (!isSysAdmin && !gotApps) { return(new GetOverviewResult() { StatSummary = new OverviewStatSummary(), IncidentsPerApplication = new GetOverviewApplicationResult[0], TimeAxisLabels = labels }); } if (isSysAdmin) { var appIds = new List <int>(); using (var cmd = _unitOfWork.CreateCommand()) { cmd.CommandText = "SELECT id FROM Applications"; using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { appIds.Add(reader.GetInt32(0)); } } } ApplicationIds = string.Join(",", appIds); } else { var appIds = context.Principal .FindAll(x => x.Type == CoderrClaims.Application) .Select(x => int.Parse(x.Value).ToString()) .ToList(); ApplicationIds = string.Join(",", appIds); } if (query.NumberOfDays == 1) { return(await GetTodaysOverviewAsync(query)); } var apps = new Dictionary <int, GetOverviewApplicationResult>(); var startDate = DateTime.Today.AddDays(-query.NumberOfDays); var result = new GetOverviewResult(); result.Days = query.NumberOfDays; using (var cmd = _unitOfWork.CreateDbCommand()) { cmd.CommandText = $@"select Applications.Id, Applications.Name, cte.Date, cte.Count FROM ( select Incidents.ApplicationId , cast(Incidents.CreatedAtUtc as date) as Date, count(Incidents.Id) as Count from Incidents where Incidents.CreatedAtUtc >= @minDate AND Incidents.CreatedAtUtc <= GetUtcDate() AND Incidents.ApplicationId in ({ApplicationIds}) group by Incidents.ApplicationId, cast(Incidents.CreatedAtUtc as date) ) cte right join applications on (applicationid=applications.id) ;"; cmd.AddParameter("minDate", startDate); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { var appId = reader.GetInt32(0); GetOverviewApplicationResult app; if (!apps.TryGetValue(appId, out app)) { app = new GetOverviewApplicationResult(reader.GetString(1), startDate, query.NumberOfDays + 1); //+1 for today apps[appId] = app; } //no stats at all for this app if (reader[2] is DBNull) { var startDate2 = DateTime.Today.AddDays(-query.NumberOfDays + 1); for (var i = 0; i < query.NumberOfDays; i++) { app.AddValue(startDate2.AddDays(i), 0); } } else { app.AddValue(reader.GetDateTime(2), reader.GetInt32(3)); } } result.TimeAxisLabels = labels; result.IncidentsPerApplication = apps.Values.ToArray(); } } await GetStatSummary(query, result); return(result); }
public async Task <GetVersionHistoryResult> HandleAsync(IMessageContext context, GetVersionHistory query) { var sql = @"select avm.YearMonth, avm.IncidentCount, avm.ReportCount, LastUpdateAtUtc, av.Version from [ApplicationVersionMonths] avm JOIN ApplicationVersions av ON (av.Id=avm.VersionId) WHERE av.ApplicationId = @appId ORDER BY YearMonth, ApplicationId, av.Version"; var first = DateTime.MinValue; var last = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1); using (var cmd = _unitOfWork.CreateDbCommand()) { cmd.AddParameter("appId", query.ApplicationId); if (query.FromDate != null) { sql += " AND YearMonth >= @from"; cmd.AddParameter("from", query.FromDate.Value); first = query.FromDate.Value; } if (query.ToDate != null) { sql += " AND YearMonth <= @to"; cmd.AddParameter("to", query.ToDate.Value); last = query.ToDate.Value; } cmd.CommandText = sql; var versions = new Versions(); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { var month = (DateTime)reader["YearMonth"]; if (first == DateTime.MinValue) { first = month; } var incindentCount = (int)reader["IncidentCount"]; var reportCount = (int)reader["ReportCount"]; var version = (string)reader["Version"]; versions.AddCounts(version, month, incindentCount, reportCount); } } if (versions.IsEmpty) { return new GetVersionHistoryResult { Dates = new string[0], IncidentCounts = new GetVersionHistoryResultSet[0], ReportCounts = new GetVersionHistoryResultSet[0] } } ; versions.PadMonths(first, last); var result = new GetVersionHistoryResult { Dates = versions.GetDates(), IncidentCounts = versions.BuildIncidentSeries(), ReportCounts = versions.BuildReportSeries() }; return(result); } } }
public async Task <GetWhitelistEntriesResult> HandleAsync(IMessageContext context, GetWhitelistEntries message) { var items = new List <GetWhitelistEntriesResultItem>(); using (var cmd = _unitOfWork.CreateDbCommand()) { CreateSqlStatement(message, cmd); var appMap = new Dictionary <int, List <GetWhitelistEntriesResultItemApp> >(); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { MapRow(reader, items, appMap); } foreach (var map in appMap) { items.First(x => x.Id == map.Key).Applications = map.Value.ToArray(); } } } if (!items.Any()) { return new GetWhitelistEntriesResult { Entries = new GetWhitelistEntriesResultItem[0] } } ; using (var cmd = _unitOfWork.CreateDbCommand()) { var entryIds = items.Select(x => x.Id).ToArray(); cmd.CommandText = $"SELECT * FROM WhitelistedDomainIps WHERE DomainId IN ({string.Join(", ", entryIds)})"; using (var reader = await cmd.ExecuteReaderAsync()) { var map = new Dictionary <int, List <GetWhitelistEntriesResultItemIp> >(); while (await reader.ReadAsync()) { var domainId = (int)reader["DomainId"]; if (!map.TryGetValue(domainId, out var ipItems)) { ipItems = new List <GetWhitelistEntriesResultItemIp>(); map[domainId] = ipItems; } ipItems.Add(new GetWhitelistEntriesResultItemIp { Address = (string)reader["IpAddress"], Type = (ResultItemIpType)(int)reader["IpType"], UpdatedAtUtc = (DateTime)reader["StoredAtUtc"] }); } foreach (var kvp in map) { items.First(x => x.Id == kvp.Key).IpAddresses = kvp.Value.ToArray(); } } } return(new GetWhitelistEntriesResult { Entries = items.ToArray() }); }
public async Task <GetApplicationOverviewResult> HandleAsync(IMessageContext context, GetApplicationOverview query) { if (query.NumberOfDays == 0) { query.NumberOfDays = 30; } if (query.NumberOfDays == 1) { return(await GetTodaysOverviewAsync(query)); } var curDate = DateTime.Today.AddDays(-query.NumberOfDays); var errorReports = new Dictionary <DateTime, int>(); var incidents = new Dictionary <DateTime, int>(); while (curDate <= DateTime.Today) { errorReports[curDate] = 0; incidents[curDate] = 0; curDate = curDate.AddDays(1); } var result = new GetApplicationOverviewResult(); using (var cmd = _unitOfWork.CreateDbCommand()) { string filter1; string filter2; if (query.Version != null) { var id = _unitOfWork.ExecuteScalar("SELECT Id FROM ApplicationVersions WHERE Version = @version", new { version = query.Version }); filter1 = @"JOIN IncidentVersions On (Incidents.Id = IncidentVersions.IncidentId) WHERE IncidentVersions.VersionId = @versionId AND "; filter2 = @"JOIN IncidentVersions On (ErrorReports.IncidentId = IncidentVersions.IncidentId) WHERE IncidentVersions.VersionId = @versionId AND "; cmd.AddParameter("versionId", id); } else { filter1 = "WHERE "; filter2 = "WHERE "; } var sql = @"select cast(Incidents.CreatedAtUtc as date), count(Id) from Incidents {2} Incidents.CreatedAtUtc >= @minDate AND Incidents.CreatedAtUtc <= GetUtcDate() {0} group by cast(Incidents.CreatedAtUtc as date); select cast(ErrorReports.CreatedAtUtc as date), count(Id) from ErrorReports {3} ErrorReports.CreatedAtUtc >= @minDate AND ErrorReports.CreatedAtUtc <= GetUtcDate() {1} group by cast(ErrorReports.CreatedAtUtc as date);"; if (query.ApplicationId > 0) { cmd.CommandText = string.Format(sql, " AND Incidents.ApplicationId = @appId", " AND ErrorReports.ApplicationId = @appId", filter1, filter2); cmd.AddParameter("appId", query.ApplicationId); } else { cmd.CommandText = string.Format(sql, "", "", filter1, filter2); } cmd.AddParameter("minDate", DateTime.Today.AddDays(-query.NumberOfDays)); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { incidents[(DateTime)reader[0]] = (int)reader[1]; } await reader.NextResultAsync(); while (await reader.ReadAsync()) { errorReports[(DateTime)reader[0]] = (int)reader[1]; } result.ErrorReports = errorReports.Select(x => x.Value).ToArray(); result.Incidents = incidents.Select(x => x.Value).ToArray(); result.TimeAxisLabels = incidents.Select(x => x.Key.ToString("yyyy-MM-dd")).ToArray(); } } await GetStatSummary(query, result); return(result); }