En .NET las transacciones son representadas por la clase Transaction que implementa la interfaz IDbTransaction definida dentro del ensamblado System.Data
esta interfaz proporciona los métodos:
Esta interfaz se utiliza para crear clases Transaction asociadas con un proveedor especifico, así para SQL Server tenemos SqlTransaction, para Oracle OracleTransaction y para PostgreSQL NpgsqlTransaction.
La ventaja de crear transacciones en .NET y no en la bases de datos es proporcionar  a la aplicaciones la capacidad de las transacciones en caso de utilizar una base de datos que no proporcione o soporte esa característica.
Como ejemplo escribimos un programa en MonoDevelop que utiliza las tablas: Invoices e InvoiceDetails que se utilizaron en esta entrada  este programa utiliza una transaction y 4 comandos SQL con los que guarda una factura (invoice) con dos detalles (invoice details), actualizando el total de la factura conforme a la cantidad de productos y su precio.
using System;
using System.Collections.Generic;
using System.Text;
using Npgsql;
using NpgsqlTypes;
using System.Data;
using System.Globalization;
namespace MonoTransExamples
 {
  class Program
  {
  static string connString = "Server=127.0.0.1;Port=5432;Database=myinvoices;
User ID=postgres;Password=Pa$$W0rd";
  static string commandText1 = "INSERT INTO invoices(invoice_number,invoice_date,
invoice_total)" + "VALUES(:number,:date,:total)";
  static string commandText2 = "SELECT MAX(invoice_id) FROM invoices";
  static string commandText3 = "INSERT INTO invoicedetails
(invoice_id,invoiced_description,invoiced_quantity,invoiced_amount)" +
"VALUES(:id,:description,:quantity,:amount)";
static string commandText4 = "UPDATE invoices SET invoice_total =
 :total WHERE invoice_id = :id";
static void Main(string[] args)
{
    bool success = false;
    int recordsAffected = 0;
    Invoice invoice = new Invoice { 
        Invoice_number = 2099,
        Invoice_date = new DateTime(2013,01,29,6,6,6,100,Calendar.CurrentEra)
    };
    Invoicedetails[] details = { 
    new Invoicedetails{
        Invoice = invoice,
        Invoiced_description = "walkie-talkie 22-Channel",
        Invoiced_quantity = 3,
        Invoiced_amount = 19.99M
    },
    new Invoicedetails{
        Invoice = invoice,
        Invoiced_description = "2 GB SD Memory Card",
        Invoiced_quantity = 4,
        Invoiced_amount = 6.99M
    }
    };
    NpgsqlTransaction transaction = null;
    NpgsqlConnection conn = null;
    try
    {
    conn = new NpgsqlConnection(connString);
    conn.Open();
    transaction = conn.BeginTransaction();
using (NpgsqlCommand cmd1 = new NpgsqlCommand(commandText1, conn, transaction))
{
cmd1.CommandType = CommandType.Text;
cmd1.Parameters.Add("number", NpgsqlDbType.Integer, 4).Value = invoice.Invoice_number;
cmd1.Parameters.Add("date", NpgsqlDbType.Timestamp).Value = invoice.Invoice_date;
cmd1.Parameters.Add("total", NpgsqlDbType.Money).Value = invoice.Invoice_total;
      recordsAffected = cmd1.ExecuteNonQuery();
        }
        Console.WriteLine("{0} invoiced inserted",recordsAffected);
        if (recordsAffected > 0)
        {
 using (NpgsqlCommand cmd2 = new NpgsqlCommand(commandText2, conn, transaction))
            {
       cmd2.CommandType = CommandType.Text;
       invoice.Invoice_id = Convert.ToInt32(cmd2.ExecuteScalar());
            }
        Console.WriteLine("Invoice Id {0} ",invoice.Invoice_id);
        }
        if (invoice.Invoice_id > 0)
        {
        recordsAffected = 0;
        foreach (Invoicedetails invd in details)
        {
        invd.Invoice.Invoice_id = invoice.Invoice_id;
         using (NpgsqlCommand cmd3 = new NpgsqlCommand(commandText3, conn, transaction))
         {
 cmd3.CommandType = CommandType.Text;
 cmd3.Parameters.Add("id", NpgsqlDbType.Integer, 4).Value = invd.Invoice.Invoice_id;
 cmd3.Parameters.Add("description", NpgsqlDbType.Varchar, 512).Value = invd.Invoiced_description;
 cmd3.Parameters.Add("quantity", NpgsqlDbType.Smallint).Value = invd.Invoiced_quantity;
 cmd3.Parameters.Add("amount", NpgsqlDbType.Money).Value = invd.Invoiced_amount;
        recordsAffected += cmd3.ExecuteNonQuery();
                }
        invoice.Invoice_total += invd.Invoiced_amount * invd.Invoiced_quantity;
            }
Console.WriteLine("Total: {0} ,{1} records affected ",invoice.Invoice_total,recordsAffected);
        }
        if (recordsAffected == details.Length)
        {
      using (NpgsqlCommand cmd4 = new NpgsqlCommand(commandText4, conn, transaction)) {
 cmd4.CommandType = CommandType.Text;
 cmd4.Parameters.Add("total",NpgsqlDbType.Money).Value = invoice.Invoice_total;
 cmd4.Parameters.Add("id",NpgsqlDbType.Integer).Value = invoice.Invoice_id;
      recordsAffected = cmd4.ExecuteNonQuery();
            }
Console.WriteLine("Updated invoice {0} with total {1} ",
invoice.Invoice_id,invoice.Invoice_total);
        }
        if(recordsAffected > 0)
                success = true;
    }catch(NpgsqlException ex){
        Console.WriteLine("Error {0} ", ex.Message);
    }finally{
        if (success)
            transaction.Commit();
        else
            transaction.Rollback();
        if (conn != null)
            if (conn.State == ConnectionState.Open)
                conn.Close();
    }
    Console.WriteLine("Done");
    Console.ReadLine();
}
}
    class Invoice {
    public int Invoice_id { set; get; }
    public int Invoice_number { set; get; }
    public DateTime Invoice_date { set; get; }
    public Decimal Invoice_total { set; get; }
    }
    class Invoicedetails {
    public int Invoiced_id { set; get; }
    public Invoice Invoice { set; get; }
    public string Invoiced_description { set; get; }
    public int Invoiced_quantity { set; get; }
    public Decimal Invoiced_amount { set; get; }
    }
}
Este programa asocia una transacción con una conexión abierta.
conn = new NpgsqlConnection(connString); conn.Open(); transaction = conn.BeginTransaction();Se crea cada uno de los comandos SQL dentro del alcance de la transacción
using (NpgsqlCommand cmd1 = new NpgsqlCommand(commandText1, conn, transaction)) using (NpgsqlCommand cmd2 = new NpgsqlCommand(commandText2, conn, transaction)) using (NpgsqlCommand cmd3 = new NpgsqlCommand(commandText3, conn, transaction)) using (NpgsqlCommand cmd4 = new NpgsqlCommand(commandText4, conn, transaction))Si todos los comandos se ejecutan correctamente se llama al método Commit() de lo contrario se llama al método Rollback y se cierra la conexión.
  if (success)
            transaction.Commit();
        else
            transaction.Rollback();
        if (conn != null)
            if (conn.State == ConnectionState.Open)
                conn.Close();
Es importante recordar que la transacción queda pendiente hasta que no se confirme (commit) o se cancele (rollback), si se cierra la conexión mediante el método Close se ejecuta un rollback en todas las transacciones pendientes.