Skip to the content.

Transactions

Auto-Commit (Default)

Each executeAsync / executeWriteAsync call auto-commits:

let! count = mutation |> Cypher.executeWriteAsync driver
// Committed immediately

Explicit Transactions

Use Cypher.inTransaction for multi-statement atomicity:

task {
    let! result = Cypher.inTransaction driver (fun tx -> task {
        let! _ = cypher { for _p in node<Person> do; create { Name = "A"; Age = 1 } }
                 |> Cypher.executeWriteAsync tx
        let! _ = cypher { for _p in node<Person> do; create { Name = "B"; Age = 2 } }
                 |> Cypher.executeWriteAsync tx
        return 2
    })
    // Both committed atomically
}

If an exception occurs inside the function, the transaction is automatically rolled back:

try
    let! _ = Cypher.inTransaction driver (fun tx -> task {
        let! _ = q1 |> Cypher.executeWriteAsync tx
        failwith "something went wrong"
        return 1
    })
    ()
with _ ->
    // Transaction rolled back — q1 changes are discarded
    ()

Manual Transaction Control

For advanced cases, use IGraphTransaction directly:

task {
    let! tx = driver.BeginTransactionAsync()
    try
        let! _ = tx.ExecuteWriteAsync(cypher, params)
        do! tx.CommitAsync()
    with _ ->
        do! tx.RollbackAsync()
    finally
        do! tx.DisposeAsync()
}

See Also