A .NET library for generating time-series trend data from Entity Framework Core queries with support for different database providers.
$ dotnet add package DotTrendA .NET library for generating time-series trend data from Entity Framework Core queries with support for different database providers. DotTrend makes it easy to create trend reports by date intervals (minute, hour, day, week, month, year) with zero-filling for missing periods.
Install the package via NuGet:
dotnet add package DotTrend
using DotTrend;
using System;
using System.Linq;
// Get daily order counts for January 2025
var dailyOrderCounts = Trend<Order>
.Query(dbContext.Orders)
.Between(new DateTime(2025, 1, 1), new DateTime(2025, 1, 31))
.PerDay()
.Count();
// Generate monthly sales report for 2025
var monthlySales = Trend<Order>
.Query(dbContext.Orders)
.Between(new DateTime(2025, 1, 1), new DateTime(2025, 12, 31))
.PerMonth()
.Sum(o => o.Amount);
// Display the results
foreach (var point in monthlySales)
{
Console.WriteLine($"{point.Date:yyyy-MM}: ${point.Aggregate}");
}
DotTrend supports multiple usage patterns to fit your coding style:
var result = Trend<Order>
.Query(dbContext.Orders)
.Between(startDate, endDate)
.PerDay()
.Count();
var result = dbContext.Orders
.Trend()
.Between(startDate, endDate)
.PerDay()
.Count();
First, register your DbContext:
// In your application startup
dbContext.UseTrend();
Then use the static approach:
var result = Trend<Order>
.Between(startDate, endDate)
.PerDay()
.Count();
// Per minute (e.g., for real-time dashboards)
var minuteData = Trend<Event>.Query(dbContext.Events)
.Between(startDate, endDate)
.PerMinute()
.Count();
// Per hour
var hourlyData = Trend<Event>.Query(dbContext.Events)
.Between(startDate, endDate)
.PerHour()
.Count();
// Per day (default)
var dailyData = Trend<Event>.Query(dbContext.Events)
.Between(startDate, endDate)
.PerDay()
.Count();
// Per week
var weeklyData = Trend<Event>.Query(dbContext.Events)
.Between(startDate, endDate)
.PerWeek()
.Count();
// Per month
var monthlyData = Trend<Event>.Query(dbContext.Events)
.Between(startDate, endDate)
.PerMonth()
.Count();
// Per year
var yearlyData = Trend<Event>.Query(dbContext.Events)
.Between(startDate, endDate)
.PerYear()
.Count();
// Count (default)
var orderCount = Trend<Order>.Query(dbContext.Orders)
.Between(startDate, endDate)
.PerDay()
.Count();
// Sum
var totalSales = Trend<Order>.Query(dbContext.Orders)
.Between(startDate, endDate)
.PerDay()
.Sum(o => o.Amount);
// Average
var averageOrderValue = Trend<Order>.Query(dbContext.Orders)
.Between(startDate, endDate)
.PerDay()
.Average(o => o.Amount);
// Minimum
var minOrderValue = Trend<Order>.Query(dbContext.Orders)
.Between(startDate, endDate)
.PerDay()
.Min(o => o.Amount);
// Maximum
var maxOrderValue = Trend<Order>.Query(dbContext.Orders)
.Between(startDate, endDate)
.PerDay()
.Max(o => o.Amount);
// SQL Server (default)
var sqlServerTrend = Trend<Order>.Query(
dbContext.Orders,
new SqlServerAdapter()
);
// MySQL
var mysqlTrend = Trend<Order>.Query(
dbContext.Orders,
new MySqlAdapter()
);
// PostgreSQL
var postgresTrend = Trend<Order>.Query(
dbContext.Orders,
new PostgresAdapter()
);
// SQLite
var sqliteTrend = Trend<Order>.Query(
dbContext.Orders,
new SqliteAdapter()
);
// Auto-detect database type from context
var autoAdapter = dbContext.GetTrendAdapter();
var autoTrend = Trend<Order>.Query(dbContext.Orders, autoAdapter);
// Use a different date column instead of the default "CreatedAt"
var ordersByProcessedDate = Trend<Order>.Query(dbContext.Orders)
.Between(startDate, endDate)
.DateColumn("ProcessedAt")
.PerDay()
.Count();
The result of any trend calculation is a list of TrendValue objects, which have these properties:
Date: The DateTime representing the periodAggregate: The decimal value of the aggregation for that periodpublic class TrendValue
{
public DateTime Date { get; set; }
public decimal Aggregate { get; set; }
}
This project is licensed under the MIT License - see the LICENSE file for details.