Search Results for

    Show / Hide Table of Contents

    ACID compliant transactions

    multi-document transactions are performed like the following:

    var book1 = new Book { Title = "book one" };
    var book2 = new Book { Title = "book two" };
    
    await DB.SaveAsync(new[] { book1, book2 });
    
    using (var TN = DB.Transaction())
    {
          var author1 = new Author { Name = "one" };
          var author2 = new Author { Name = "two" };
    
          await TN.SaveAsync(new[] { author1, author2 });
    
          await TN.DeleteAsync<Book>(new[] { book1.ID, book2.ID });
    
          await TN.CommitAsync();
    }
    

    in the above code, book1 and book2 are saved before the transaction begins. author1 and author2 are created within the transaction and book1 and book2 are deleted within the transaction.

    a transaction is started when you instantiate a Transaction object either via the factory method DB.Transaction() or new Transaction(). you then perform all transaction logic using the methods supplied by that class such as .SaveAsync(), .DeleteAsync(), .Update(), .Find() instead of the methods supplied by the DB static class like you'd normally do.

    the methods of the DB class also supports transactions but you would have to supply a session to each method call, which would be less convenient than using the Transaction class.

    whatever transactional operations you do are only saved to the database once you call the .CommitAsync() method. if you do not call .CommitAsync(), then nothing changes in the database.

    if an exception occurs before the .CommitAsync() line is reached, all changes are rolled back and the transaction is implicitly terminated.

    it is best to always wrap the transaction in a using statement because reaching the end of the using statement will automatically end the transaction and dispose the underlying session. if no using statement is used, you will have to manually dispose the transaction object you created in order to finalize things.

    you can also call .AbortAsync() to abort a transaction prematurely if needed at which point all changes will be rolled back.

    Relationship Manipulation

    relationships within a transaction requires passing down the session to the .Add() and .Remove() methods as shown below.

    using (var TN = DB.Transaction())
    {
        var author = new Author { Name = "author one" };
        await TN.SaveAsync(author);
    
        var book = new Book { Title = "book one" };
        await TN.SaveAsync(book);
    
        await author.Books.AddAsync(book, TN.Session);
        await author.Books.RemoveAsync(book, TN.Session);
    
        await TN.CommitAsync();
    }
    

    File Storage

    file storage within a transaction also requires passing down the session like so:

    using (var TN = DB.Transaction())
    {
        var picture = new Picture { Title = "my picture" };
        await TN.SaveAsync(picture);
    
        var streamTask = new HttpClient()
                          .GetStreamAsync("https://placekitten.com/g/4000/4000");
    
        using (var stream = await streamTask)
        {
            await picture.Data.UploadAsync(stream, session: TN.Session);
        }
    
        await TN.CommitAsync();
    }
    

    Transactions with DBContext instances

    Transactions can be performed using DBContext instances like so:

    var db = new DBContext();
    
    using (var session = db.Transaction())
    {
        await db.SaveAsync(new Book { Title = "test" });
        await db.CommitAsync();
    }
    

    Note: only one active transaction is allowed per DBContext instance. if you need to start another transaction for the same instance, make sure to first commit your changes -> dispose the session object (if not wrapped in a using statement) -> assign a null to the session before you call db.Transaction() again.

    In this article
    Back to top Developed by Đĵ ΝιΓΞΗΛψΚ and contributors / Licensed under MIT / Website generated by DocFX