Over a million developers have joined DZone.

Working with Transactions in Entity Framework 6

Jalpesh Vadgama provides a summary of using transactions with Entity Framework 6 and how, when used properly, you can keep your database clean.

· Database Zone

Build fast, scale big with MongoDB Atlas, a hosted service for the leading NoSQL database. Try it now! Brought to you in partnership with MongoDB.

In any relational database, maintaining integrity of the database is very important and a Transaction is one way of maintaining database integrity. When you have a situation where you need to insert data into multiple tables and if inserting data in one of the table fails, you should always rollback other insert transactions. The same scenario exists for update or delete operations. If transactions are not there you will end up with lots of junk data in tables. Entity Framework is one of most popular ORMs in the .NET World. So in this post we are going to learn how we can use transactions with Entity Framework 6. 

Transaction and Entity Framework 6

Entity Framework internally maintains a transaction when you call the SaveChanges() method. So all Inserts, update operations under a single save changes method call will be in a single transaction. But when you want to wrap multiple SaveChanges() methods under a single transaction there is not any built-in functionality in earlier versions of Entity Framework. 

Now, with Entity Framework 6.0, we have two built-in APIs for transactions:

DbContext.Database.BeginTransaction

This API call will allow us to begin a transaction for multiple save changes.  You can combine as many operations as you want under a single transaction and hence either all will be performed successfully then the transaction will be committed.  If any exception occurs then the transaction will be rolled back.

DbContext.Database.UseTransaction

Some times we need to use a transaction which is started outside of the entity framework. In this case this API call allows us to also use that transaction with Entity Framework. 

In this blog post, we are going to use Begin Transaction. In the future, I plan to write a separate blog post about how to use existing transaction with entity framework.

So enough theory, let's create a console application to understand it better.

ef6-with-transactions-console-application We need Entity Framework. So I have added it via nuget package.

entity-framework-transaction-nuget-package

In this application, we are going to use two model classes called category and product. We will save them both in single transaction and try to understand how transaction works with Entity Framework.

The category model is listed below:

namespace EFWithTransactions
{
    public class Category
    {
        public int CategoryId { get; set; }
        public string CategoryName { get; set; }
    }
}

Here is the product model:

using System.ComponentModel.DataAnnotations.Schema;

namespace EFWithTransactions
{
    public class Product
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
        [ForeignKey("Category")]
        public int CategoryId { get; set; }
        public virtual Category Category { get; set; }
    }
}

Here you can see I have the category ID in Product an Product belongs to Category.  I have created my dbcontext class as shown below:

using System.Data.Entity;

namespace EFWithTransactions
{
    public class ProductDbContext : DbContext
    {
        public ProductDbContext()
            : base("ProductConnectionString")
        {

        }
        public DbSet<Category> Categories { get; set; }
        public DbSet<Product> Products { get; set; }
    }
}

The Main method of console application is displayed below, which illustrates a real scenario where an exception might occurs during multiple save changes().

using System;

namespace EFWithTransactions
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ProductDbContext productDbContext = new ProductDbContext())
            {
                using (var transaction = productDbContext.Database.BeginTransaction())
                {
                    try
                    {
                        //saving category
                        Category category = new Category
                        {
                            CategoryName = "Clothes"
                        };
                        productDbContext.Categories.Add(category);
                        productDbContext.SaveChanges();

                        // Throw some error to check transaction
                        // Comment this to make transactions sucessfull
                        // throw new Exception("Custom Exception");

                        //saving product
                        Product product = new Product
                        {
                            ProductName = "Blue Denim Shirt",
                            CategoryId = category.CategoryId
                        };
                        productDbContext.Products.Add(product);
                        productDbContext.SaveChanges();
                        Console.Write("Cateogry and Product both saved");
                        transaction.Commit();
                    }
                    catch (Exception exception)
                    {
                        transaction.Rollback();
                        Console.WriteLine("Transaction Roll backed due to some exception");
                    }
                }

            }
            Console.ReadKey();
        }
    }
}

If you review the above code carefully, you can see I have two save changes methods: one for Category and another for Product. I have also used a BeginTransaction method to initiate a new transaction.

I have added one custom exception to illustrate something is wrong with that transaction. Also a try/catch block exists to handle any exceptions and will rollback the transaction. If all goes well it will commit the transaction.

Now let's run this application and the follow is the expected output, since we have thrown an exception.

Transaction-roll-back-entity-framework

As a result, no data has been inserted into the database.

sql-server-database-with-no-data

Now let's comment the new part that throws an exception.

//throw new Exception("Custom Exception");

When we run our application again, the expected output is returned.

transaction-committed-sql-server

Now we have data in the database.

sql-server-database-with-data-transaction-commited

As a result, we have a really good way to use Transaction in Entity Framework. Hope you like it.

Stay tuned for more!

Now it's easier than ever to get started with MongoDB, the database that allows startups and enterprises alike to rapidly build planet-scale apps. Introducing MongoDB Atlas, the official hosted service for the database on AWS. Try it now! Brought to you in partnership with MongoDB.

Topics:
.net ,entity framework ,orm ,transaction management

Published at DZone with permission of Jalpesh Vadgama, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}