Summary#
ui-chart-over-unbounded-rows is a SHOULD finding: a Chart (or a map) is drawn from a read of every row of an
entity. A page query is sent about 2 MB of rows an answer (How many rows a page is sent), so the chart of a growing table
quietly leaves rows out — and before then it ships every row to draw a few bars.
Let the database do the summing, so the answer is one row per mark:
entity Sale {
[Required, MaxLength(10)] string Day;
decimal Amount;
security { allow read, create when IsAnonymous || IsAuthenticated; }
}
class DayTotal { public string Day; public decimal Total; }
[Route("/sales")] [Render(CSR)] [AllowAnonymous]
component SalesPage() {
live var perDay = Sale.GroupBy(s => s.Day)
.Select(g => new DayTotal { Day = g.Key, Total = g.Sum(s => s.Amount) }).ToList();
render {
Stack(gap: 2, p: 6) {
foreach (var d in perDay) { Text($"{d.Day}: {d.Total}"); }
}
}
}Signature#
Entity.GroupBy(x => key).Select(g => new Row { Key = g.Key, Value = g.Sum(x => …) }).ToList() // one row per mark
Entity.Where(x => x.At >= from).OrderBy(x => x.At).Take(n).ToList() // or a narrowed rangeDescription#
When does it fire?#
On a component field read from an entity with no Take that a chart or map is drawn from — a Chart, a Pie, a
Sparkline, or any control whose name holds Chart or Map — through its arguments or anything written inside it.
It takes precedence over the list and dropdown rules for the same read.
When is it silent?#
When the read is an aggregate — a GroupBy (one row per key), a Count, a Sum — or bounded by a Take, a one-row
read or a child collection pinned to one parent.
What can it not tell?#
How many distinct keys a GroupBy has. A group per customer can be large; a group per day of a month is not. A
grouped read is trusted as bounded.
See also#
- How many rows a page is sent — what a page is sent, and why an aggregate is never windowed
- The chart kit — line, column, bar, scatter and candle, with no JavaScript — the chart kit