Skip to content
Client v5: BLE, BLE Hosting, HTTP, Jobs - Linux, MacOS, & Blazor Support! Full AOT, RX on BLE only & MANY other features! Check It Out

FAQ & Decision Trees

Common questions about how DocumentDb is designed and which API to reach for. If you’re coming from Entity Framework, start with the write-model questions — the mental model is deliberately a little different.

DocumentDb gives you three ways to write, in increasing order of grouping. Pick the smallest one that fits.

Are you writing more than one document?
├─ No ── one document, write it now
│ └─► Insert / Update / Upsert / Remove (auto-commit, one round trip)
└─ Yes
├─ All the same type, and you just want them in fast?
│ └─► BatchInsert(documents) (single transaction, command reuse)
└─ Mixed operations / mixed types that must all
succeed or all fail together?
└─► CreateUnitOfWork() → Add/Update/Remove → SaveChanges()
You want to…UseAtomic?Notes
Write a single documentInsert / Update / Upsert / Removen/a (one op)Auto-commits. No setup.
Insert many documents of one type, fastBatchInsertYes — the whole batchAuto-generates IDs; rolls the batch back on any failure.
Group several writes (any mix) atomicallyUnitOfWork + SaveChangesYes — the whole unitBuffers Add/Update/Upsert/Remove, commits once.
// Single writes — just do them
await store.Insert(user);
await store.Update(order);
// Bulk insert of one type — fastest path for "load these in"
var count = await store.BatchInsert(users);
// Several writes, all-or-nothing
var uow = store.CreateUnitOfWork();
uow.Add(order)
.Add(orderLine1)
.Add(orderLine2)
.Remove<Cart>(cartId);
await uow.SaveChanges(); // one transaction; rolls back entirely on failure

Why is UnitOfWork a separate object and not IDocumentStore itself?

Section titled “Why is UnitOfWork a separate object and not IDocumentStore itself?”

If you come from EF, the natural question is “why isn’t the store itself the unit of work, like DbContext?” We looked hard at this and chose a separate, store-created handle on purpose.

DbContext can be the unit of work because EF registers it scoped — one short-lived context per operation, never shared. The expensive parts (the model, internal services, connection pooling) live in singletons that the context borrows from.

IDocumentStore is the opposite: it’s long-lived, shared infrastructure. It owns the connection(s), the change-notification broadcaster and its subscribers, and the type/ID caches. On mobile it’s effectively a singleton. Putting a mutable “pending writes” buffer on that shared object would mean:

  • Concurrency hazards. Two callers buffering writes would land in the same buffer; whoever calls save first would flush the other’s half-built work.
  • Forgotten-flush footguns. A long-lived object accumulates pending writes; a later, unrelated save could flush stale ones.

A UnitOfWork is per-operation, short-lived state — so it lives in its own object whose lifetime is bounded by your use of it. Abandon it and the buffer is simply collected.

Can I read my own uncommitted writes from a UnitOfWork?

Section titled “Can I read my own uncommitted writes from a UnitOfWork?”

No. A UnitOfWork is a write buffer, not a tracking context with an identity map. Reads (Get, Query, Count) always go live against the store and won’t see writes that are still buffered in a unit. Call SaveChanges first if a later read needs to see them.

This is a deliberate difference from EF’s DbContext, which serves buffered changes back from its change tracker.

How do I run several operations in one transaction?

Section titled “How do I run several operations in one transaction?”

Use a UnitOfWork. Everything you Add/Update/Upsert/Remove is applied inside a single transaction when you call SaveChanges, and rolled back as a whole if anything fails. There is no separate “begin transaction” call on the store — the unit of work is the transaction boundary, and it’s the only place one opens.

No. It holds no connection or transaction of its own until SaveChanges runs (which opens, commits, and closes its transaction internally). An un-saved unit is just an in-memory list of pending operations.