Saturday, August 17, 2013

Transaction Support in Entity Framework 6





The Entity Framework team has announced the new version of Entity Framework 6 beta pro. I describe in this article series new features introduced in Entity Framework 6.
My last article was Code First Stored Procedure in Entity Framework 6. You can see this from:

Code First Insert Update and Delete Stored Procedure in Entity Framework 6 Pre

Now, through this article, I provide another new specification of Entity Framework 6. The new APIs make the developer easy to worki with transactions in Entity Framework.

Transaction: Transaction is used to ensure that everything in the unit of work is either successful or failed. A transaction is a series of operations performed as a single unit of work. Entity Framework transactions are a part of its internal architecture. The "SaveChanges()" method operates within a transaction and saves results of the work. It is designed to ensure data integrity.First we need to install the Entity Framework 6 Pre in Visual Studio 2012,
How to Install the Entity Framework 6 Beta version in .NET Framework 4.5
From the Tools menu, select "Library Package Manager" and then click "Package Manager Console".

package-manager-console-in-vs2012.jpg

To install Entity Framework, run the following command in the Package Manager Console.
PM> Install-Package Entity Framework -Pre

install-entity-framework-in-vs-2012.jpg

In Entity Framework 6 we can now add the two new APIs to DbContext.Database that makes working with transactions easier.
"UseTransaction" and "BeginTransaction"

In this article however I will only consider how to use "BeginTransaction()" to work with the transactions in Entity Framework 6.

BeginTransaction():  This method returns a "DbContextTransaction" object and will open the underlying database connection if necessary. This method has two overriden constructors. Both the overrides takes the "IsolationLevel" for the transaction.

1.  The first one is the default constructor that takes no arguments, which means it uses the default for the transaction.
2.  The second takes an explicit "IsolationLevel" for the transaction.

DbContextTransaction: It provides the two methods "Commit()" and "Rollback()" that perform Rollback and Commit on the transaction.

Now, let's start code to see how to use Transaction in Entity Framework 6.

Here, I'll use a console application in VS2012 using C#.

I am using Code First to use the Transaction. When using Code First development you usually begin by writing .NET Framework classes that define your conceptual (domain) model.

The code below defines a set of model classes. Open the Program.cs file and paste the following class definitions.



public class PostInformation
{
        [Key]
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
}

public class PostAdditionalInformation
{
        [Key]
        public int PostId { get; set; }
        [Required]
        public string PostName { get; set; }
}

To use the appropriate annotations, include the Namespaces in the file.
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;


Define the DbContext Derived Type

In addition to defining entities, you need to define a class that derives from DbContext and exposes DbSet<TEntity> properties. The DbSet<TEntity> properties.

An instance of the DbContext derived type manages the entity objects during run time, that includes populating objects with data from a database, change tracking, and persisting data to the database.

In the Program.cs add the context definition.
public partial class PostEntityContainer : DbContext
{
        public PostEntityContainer() : base("name=EntitieConnectionString")
        {
        } 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
        }
        public DbSet<PostInformation> Post_Details { get; set; }
        public DbSet<PostAdditionalInformation> PostAddtional_Details { get; set; }}


Here, I will call the base constructor of the "DbContext" class by passing the Connection String key name that is defined in my "Web.Config" file.

Now, after creating the basics Entity Framework, it's time to use the following declaration in the Main method with a transaction.
Open the Program.cs file where the Main method is defined. Add the following code into the Main function.
static void Main(string[] args)
        {
            using (var context = new PostEntityContainer())
            {
                using (var dbcxtransaction = context.Database.BeginTransaction())
                {
                    try
                    {
                        PostInformation NewPost = new PostInformation()
                        {
                            PostId = 101,
                            Content = "This is my first Post related to Entity Model",
                            Title = "Transaction in EF 6 beta"
                        };
                        context.Post_Details.Add(NewPost);
                        context.SaveChanges();
                        PostAdditionalInformation PostInformation = new PostAdditionalInformation()
                        {
                            PostId = (101),
                            PostName = "Working With Transaction in Entity Model 6 Beta Version"

                        };
                        context.PostAddtional_Details.Add(PostInformation);
                        context.SaveChanges();
                        dbcxtransaction.Commit();
                        Console.WriteLine("Data Saved Successfully. Transaction Commited");
                    }
                    catch
                    {
                        dbcxtransaction.Rollback();
                        Console.WriteLine("Error Occured during data saved. Transaction Rolled Back");
                    }
                }
            }
        }

The code above will call the "SaveChanges()" method on the context two times on the different "DbSet" underlying the same transaction. If both the entities are saved successfully then the transaction will be successfully committed, otherwise it wil be rolled back.Note: Beginning a transaction requires that the underlying store connection is open. So calling BeginTransaction() will open the connection if necessary. If "DbContextTransaction" opened the connection then it will close it when "Dispose()" is called. 

Now, run the application and see what happens with it.

When you run the application, you get the following message on the screen.


transaction Commited in Entity Framework.jpg

When you open your database with a respective connection string, you will notice that the will be inserted in both of the tables.

Sql-Table-in-Sql-Server.jpg


Now, I will change some code during the second insertion of the entity to the set, so that it will go through the catch block and transaction when it is being rolled back.
static void Main(string[] args)
        {
            using (var context = new PostEntityContainer())
            {
                using (var dbcxtransaction = context.Database.BeginTransaction())
                {
                    try
                    {
                        PostInformation NewPost = new PostInformation()
                        {
                            PostId = 101,
                            Content = "This is my first Post related to Entity Model",
                            Title = "Transaction in EF 6 beta"
                        };
                        context.Post_Details.Add(NewPost);
                        context.SaveChanges();
                        PostAdditionalInformation PostInformation = new PostAdditionalInformation()
                        {
                            PostId = 101,
                        //    PostName = "Working With Transaction in Entity Model 6 Beta Version" Comment the Line, which is mark as required.
                        };
                        context.PostAddtional_Details.Add(PostInformation);
                        context.SaveChanges();
                        dbcxtransaction.Commit();
                        Console.WriteLine("Data Saved Successfully. Transaction Commited");
                    }
                    catch
                    {
                        dbcxtransaction.Rollback();
                        Console.WriteLine("Error Occured during data saved. Transaction Rolled Back");
                    }
                }
            }
        }
The code above will prompt the message that the transaction is being rolled back due to some error. This is because the "PostAdditionalInformation" class has a required element that we do not passed when saving the entity to the set. See the Comment line. This time it goes through the catch block and the transaction will be completely rolled back, even the first "SaveChanges" will succeed.

Transaction Rolled Back in Entity Framwork.jpg


Here is the result of the database tables. No entry will be made in both the tables due to the transaction being rolled back.

Blank-table-in-sqlserver.jpg

No comments:

Post a Comment