Your model, described once
The client learns entity types, keys, relationships and validation from the Entity Framework Core or NHibernate mapping you already have.
Describe your model to the client, run the queries it composes, and save its whole change-set in one transaction - on .NET 8, 9 and 10, with Entity Framework Core or NHibernate.
This site documents the .NET server-side packages of Breeze, a library from IdeaBlade that helps you manage data in rich client applications. It covers version 8.0.0, which targets .NET 8, 9 and 10 on ASP.NET Core.
TIP
Looking for the client? The Breeze client documentation - guides and the TypeScript API reference - is at breeze.github.io/breeze-client-v3. Start with Using a Breeze .NET server for how a client talks to the server documented here.
A Breeze client holds a cache of entities. It composes queries against them, tracks what the user changes, and saves everything in one go. None of that works against an ordinary REST API, because an ordinary REST API answers only the questions its author thought of in advance, and accepts only the shapes its author declared.
The server packages close that gap. They add three things to an ASP.NET Core application:
PersistenceManager.Metadata() reads your Entity Framework Core or NHibernate mapping and returns it as JSON: entity types, their properties and data types, keys, relationships, which properties are required, how long a string may be, and which column is the concurrency token.
The client builds its own model from that document. It is what lets the client create a valid entity, follow customer.orders[0].orderDetails, know that a change is a change, and reject a too-long CompanyName before a request is ever sent. You write no schema twice: the mapping you already have is the description.
The client builds a query — filter, sort, page, project, include related types — and sends it as JSON in the URL. [BreezeQueryFilter] applies it to the IQueryable your action returned, before it is serialized. So it reaches the database as SQL, with the filter in the WHERE clause rather than in memory afterwards.
The practical effect is on how many endpoints you write:
| without Breeze | with Breeze | |
|---|---|---|
| query endpoints | one per question - GetCustomers, GetCustomersByCity, GetCustomersByCityPaged … | one per entity set, returning IQueryable<T> |
| a new filter the UI needs | a new endpoint, deployed | nothing; the client already can |
That is also why Querying spends most of its length on MaxDepth and MaxTake. A query that arrives from a browser is user input, and the point of the feature is that you did not enumerate what it may ask for.
SaveChanges receives one document containing every pending change — added, modified and deleted entities, of as many types as the user touched, each carrying its state and its original values. The PersistenceManager turns that back into real entities attached in the right states, saves them in one transaction, and reports back the keys the database generated in place of the temporary ones the client invented.
So a screen that adds an order, edits two of its lines and deletes a third is one request that succeeds or fails as a unit — not four, in an order you had to choose, with partial failure to unpick.
A failed save comes back as an RFC 9457 problem details document carrying which entity failed and why, so the client can attach the message to the offending record rather than showing one dialog for the batch. Optimistic concurrency conflicts arrive with a stable problem type, identical whether Entity Framework Core or NHibernate raised them. See Error handling.
It is a library, not a framework, and it is deliberately small:
DbContext or your mappings. It reads them. Your entities, configuration and migrations are unchanged.This site has two halves: a hand-written Guide, and an API reference generated from the XML doc comments in breeze-server-v3. The API link above reaches the whole of it; the table below starts at each package.
| Getting started | from an empty project to a working Breeze endpoint |
| The PersistenceManager | the server side of Breeze, and its lifetime |
| Querying | the query filter, and limiting what clients may ask for |
| Saving | interceptors, transactions and key mappings |
| Security | the query and the change-set both come from the browser |
| Metadata | what the client is told about your model |
| Error handling | returning errors a client can act on |
| Package | Namespace | Purpose |
|---|---|---|
| Breeze.AspNetCore.NetCore | Breeze.AspNetCore | ASP.NET Core integration - [BreezeQueryFilter] and friends |
| Breeze.Persistence.EFCore | Breeze.Persistence.EFCore | Entity Framework Core support - start at EFPersistenceManager<T> |
| Breeze.Persistence.NH | Breeze.Persistence.NH | NHibernate support |
| Breeze.Persistence | Breeze.Persistence | Shared persistence layer - PersistenceManager |
| Breeze.Core | Breeze.Core | Query parsing and JSON serialization |
A typical EF Core application installs the first two; the last two are pulled in automatically.
The reference is built from the net10.0 target. The public API is the same on net8.0 and net9.0, except that each target references the matching major version of Entity Framework Core.