Summary#
.Update(…) ends a query chain the way .Delete() does — but instead of deleting the matching
rows it writes them: the body is a list of assignments to the row, applied set-based in one statement, at the
call site. The answer is how many rows were written. It is the same verb as C#'s ExecuteUpdate, under the natural
name and with the natural body — assignments, not a SetProperty chain.
Signature#
<Entity>.Where(o => …).Update(o => { o.Status = "Closed"; }) → int
<Entity>.Where(o => …).Update(o => { o.Total = o.Total + o.Fee; }) → int // the RHS reads the row
<Entity>.Where(o => …).OrderBy(k).Take(n).Update(o => { … }) → int // bounded — the chunked passDescription#
Which rows does it write?#
Exactly the rows the chain would have returned, narrowed further by the entity's allow update rules — per
assigned property: a row is updatable only if every property you assign is granted for it, and a caller with no
grant at all for one of the assigned properties is refused naming it. Rows outside the set are untouched, never an
error; the count says how many were written.
entity Order {
[Required] string Status;
decimal Total;
decimal Fee;
}
int CloseStale() {
return Order.Where(o => o.Status == "Stale").Update(o => { o.Status = "Closed"; });
}A value can read the row#
An assignment's value may reference the row's own properties. It becomes part of the SQL, so each row computes with its own values, and concurrent increments compose instead of losing writes:
int ApplyFees() {
return Order.Where(o => o.Status == "Closed").Update(o => { o.Total = o.Total + o.Fee; });
}A value may also be a captured local or parameter — it binds like a query predicate's would. It may read through the row's references, and it may embed a correlated scalar read — an aggregate over the row's own collection, or an entity-rooted one:
entity Region { [Required] string Name; decimal TaxRate; }
entity Account {
[Required] string Status;
Region? Region;
decimal TaxRate;
decimal Total;
[ForeignKey(Account)] Entry[] Entries;
}
entity Entry { [Required] Account Account; decimal Amount; }
int Restamp() =>
Account.Where(a => a.Status == "Open").Update(a => {
a.TaxRate = a.Region.TaxRate ?? 0m; // a hop — null when the reference is absent, so answer for it
a.Total = a.Entries.Sum(e => e.Amount); // ITS OWN entries, correlated per row
});A hop through a reference that can be absent is null for rows without one — assigning that to a non-nullable
member refuses at compile until you answer for absence (?? <fallback>) or declare the member nullable, the same
standard an empty-set Max(…) holds. What a value may NOT be is a row-returning query: a set statement
assigns one scalar per row — aggregate it, or compute it into a local first.
When does it run?#
Immediately — at the call, not at UnitOfWork.Commit(), exactly like .Delete(). It writes the
stored rows, so it refuses (naming the remedy) while your unit of work holds uncommitted changes of the same type.
What about the entity's rules?#
They hold. An [Immutable] property, a workflow-owned state field or a platform-stamped field is refused at
compile time, naming the reason. Value rules ([Min], [Max], [Pattern], [MinLength], [Required]) and the
entity's invariants are re-checked over the written rows inside the same transaction — one violating row
rolls the whole statement back, with the rule's own message:
entity Meter {
[Required] string Zone;
[Max(100)] int Load;
}
int Shed(int by) {
return Meter.Where(m => m.Zone == "North").Update(m => { m.Load = m.Load + by; });
}A list in memory?#
.Update(…) writes database rows. Elements of a local list change with a plain loop —
foreach (var x in xs) { x.Prop = value; } — and the compiler says so if you reach for the wrong verb.
Examples#
int ArchiveOldest() {
return Order.Where(o => o.Status == "Closed").OrderBy(o => o.Total).Take(100)
.Update(o => { o.Status = "Archived"; });
}See also#
- Delete — the delete terminal, same shape and same security story
- Where / Single / Count — saying which rows
- security { } — the
allow updaterules that narrow the set, per assigned property