Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Query

Delete

<query>.Delete() → int // delete every matching row, immediately; answers how many

Ends a query chain with a set-based DELETE: every row the chain selects is deleted in the database, immediately, in one statement — and the call answers how many went. Zero is an answer, not an error. A row the caller cannot read, or that the entity's delete rules refuse, is simply not in the set.

stable5 examples compiled by CIquerydatamutation

Summary#

.Delete() ends a query chain the way .Count() does — but instead of counting the matching rows it deletes them, set-based, in the database, at the call site. The answer is how many rows were deleted. It is the same verb as C#'s ExecuteDelete, under the natural name.

Signature#

<Entity>.Where(o => …).Delete()                    →   int   // every matching row, one statement
<Entity>.Where(o => …).OrderBy(k).Take(n).Delete() →   int   // at most n rows — the chunked purge
<Entity>.Delete()                                  →   int   // the WHOLE set — deliberate, like C#'s ExecuteDelete
<a Query<T> binding or parameter>.Delete()         →   int   // a deferred chain composes into the terminal

Description#

Which rows does it delete?#

Exactly the rows the chain would have returned to you, narrowed further by the entity's allow delete rules. A row your read security hides is not in the set; a row the delete rules refuse stays untouched. Neither is an error — the statement deletes fewer rows, and the count says how many it was.

entity Order {
  [Required] string Status;
  decimal Total;
}

int PurgeStale() {
  return Order.Where(o => o.Status == "Stale").Delete();
}

Zero is a normal answer: a predicate that matches nothing deletes nothing and answers 0. A bare Order.Delete() is the whole set, on purpose — the receiver names the set as plainly as Order.Count() does, and the declared security still bounds it. And a Query<T> built elsewhere — a binding, or a parameter crossing a function boundary — ends in the terminal exactly like an inline chain.

When does it run?#

Immediately — at the call, not at UnitOfWork.Commit(). It is a statement against the stored rows, so it does not see rows you have created or edited in the current unit of work. If you hold uncommitted changes of the same entity type, the call refuses and tells you to Commit() or Discard() them first — silently deleting around your pending edits would be worse.

What happens to related rows?#

The same thing a per-row delete does: a required child ([Required] Order Order; on the child) is deleted with its parent, an optional reference is set to null, and a relation declared to restrict blocks the delete. The answered count is the target rows — cascaded children are not counted.

entity Invoice {
  [Required] string State;
  [ForeignKey(Invoice)] InvoiceLine[] Lines;
}
entity InvoiceLine {
  [Required] Invoice Invoice;   // required → deleted with its invoice
  int Qty;
}

int DropDrafts() {
  return Invoice.Where(i => i.State == "Draft").Delete();   // lines cascade; count = invoices
}

How do I delete a lot without one huge statement?#

OrderBy and Take compose like on any chain, which gives the chunked-purge idiom — delete a bounded slice per call and stop when the answer is zero:

int PurgeOldest() {
  return Order.Where(o => o.Status == "Stale").OrderBy(o => o.Total).Take(100).Delete();
}

One row I already hold?#

The receiver decides which verb you get. A loaded entity deletes that row through the unit of work, at commit, like any other staged write; a query chain deletes set-based, immediately:

void DropOne(Order o) {
  o.Delete();                                       // this row — staged, lands at commit
}
int DropMatching(string status) {
  return Order.Where(x => x.Status == status).Delete();   // the set — immediate, counted
}

A list in memory?#

.Delete() deletes database rows. A local list already has its verb — list.RemoveAll(x => …) — and the compiler says so if you reach for the wrong one.

Examples#

entity Session2 {
  [Required] string Token;
  DateTime ExpiresAt;
}

int ReapExpired() {
  return Session2.Where(s => s.ExpiresAt < DateTime.UtcNow).Delete();
}

See also#

Related

Where / Single / Count

Query an entity by writing a predicate over it. The query runs in the database — not a filter over rows you already…

Skip / Take (paging)

Page a query with Skip(n) (OFFSET) and Take(m) (LIMIT). The count can be a compile-time constant OR a runtime integer —…

Array literals

An array literal [a, b, c] is a value: a list you can return, assign, pass as an argument, or supply as a UI prop. Its…

security { }

The rules that decide who may read and write an entity's rows. A where clause filters by the row (the owner sees their…