Archive for the Category ◊ .Net ◊

Tuesday, November 18th, 2014

In my previous blog post, we saw what ngen is all about and how it helps improve application start up performance. In this blog post, we will see how to use Ngen in Entity Framework based applications. Lets get started.

PS: Prior to Entity Framework 6.0, Core libraries of Entity Framework runtime were part of .NET Framework, which means native images were generated automatically. From EF 6.0, Whole runtime is part of nuget package (comprising of EntityFramework.dll & EntityFramework.SqlServer.dll)

I defined StudentContext in Main.cs as below , lets keep model simple as our focus is on ngen)

        public class StudentContext : DbContext
        {
            public DbSet<Student> Students;
        }

        public class Student
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }

To Evaluate application startup, lets use Windows Performance Recorder , that ships with Windows ADK, For this phase of demo, i have not ngen’d EF at all.,As you see below, clrjit.dll starts doing JIT Compilation.
With clrjit.dll

With ngen:

  • Open VS Developer Command Prompt in Admin mode
  • Navigate to location where EntityFramework.dll resides
  • Run Command “ngen install EntityFramework.dll” as below

ngen_issue_command

Running WPA again, yield below results and its clear that there is no clrjit.dll
Without_JIT

As you see, its very clear, there is no clrjit.dll, which infact means that clr is using native image cache of EntityFramework.dll instead of JITting again. Inorder to see where is the cache located, we need to issue command as

ngen display EntityFramework.dll

after_using_ngen_display

Summary:

Ngen.exe is very effective in saving performance during application startup and in some cases it can even reduce memory usage. B/w multiple applications can use the same assembly which is already ngen’ed., so that they can get benefits of low memory footprint and fast app startup.

Category: .Net | Tags: ,  | Leave a Comment
Monday, November 17th, 2014

For all new bees who have not heard of ngen, ngen means Native Image Generator (Ngen.exe) is a tool provided by Microsoft to improve the performance of application during application start up. Ngen comes with .NET Framework itself and is used to Compile IL code to processor-specific machine code, and installs them into native image cache on local computer.

With out ngen: Once the application starts up, CLR’s JIT compiler(clrjit.dll) will be invoked ON DEMAND to convert IL code(usually byte code) to native instruction set, which at times take significant amount of time., delaying application startup. This is one situation where ngen comes handy.

How it works ?
Once you invoke ngen.exe on executable(.exe) or dll, exe or dll have their IL gets compiled to native code. A new assembly file containing only native code is created by Ngen.exe., and will be located in a directory %SystemRoot%\Assembly\NativeImages_v4.0.XXXXX_64. The directory name include version of CLR and information header denoting whether native code is compiler for 32 bit or 64 bit. The good part about this is if we use ngen for one of our dll, all its dependencies will be automatically ngen’d. This is the significant change from .NET 4 framework, Having said this, once we run execute application, CLR will do a check whether the application is ngen’d or not by checking corresponding native image file in the said directory(above)., If its not found, CLR JIT compiler compiles the IL code. Otherwise CLR uses the native image code generated by ngen, and CLR does not have to compile the methods in the native image file during runtime. Thats it, this is how ngen works. In my next article i will demonstrate how to use ngen through commandline and interpret the results of the application performance.

Category: .Net | Tags:  | Leave a Comment
Sunday, November 09th, 2014

Few days ago I was looking at some cool new features that would be introduced in C# 6.0. Although mentioning about all the features in a single blog would be difficult, I would like to share the improvisations made to the most commonly used functionalities that we as developers use very frequently.

Initializing Auto Properties:

C# 6.0 allows developers to declare and initialize auto properties just like fields.

public class Employee

{

public string Id { get; } = “PROXXX”;

public string Name  { get; set; } = “XXXXXX”;

}

 

Primary Constructors

This is a very useful feature for developers since it helps us overcome the difficulty of assigning values of constructor parameters to fields in a class. The primary constructors makes the initialization process much simpler. The below code snippet explains how to declare primary constructors.

 

public class Employee(int id, string name)    // Primary Constructor declaration

{

public int Id { get; } = id;

public string Name  { get; set; } = name;

}

 

Accessing static methods:

The general way of accessing a static method is <StaticClassName>.<MethodName>. This is made even simpler in C# 6.0. All we need to do is declare the type in a using statement and all the static members of that type will be accessible.

 

using System.Console;

namespace ExploreCSharpSix

{

class Program

{

static void Main(string[] args)

{

WriteLine(“Welcome to Prowareness”);

}

}

}

 

Declaration Expressions:

This feature allows to declare local variables in the middle of an expression

 

Before C# 6.0:

public void ConvertStringToDatetime(string strDate)

{

strDate = “09/11/2014″;

DateTime result;

bool isParsed = DateTime.TryParse(strDate, out result);

}

 

C# 6.0:

 

public void ConvertStringToDatetime(string strDate)

{

strDate = “09/11/2014″;

bool isParsed = DateTime.TryParse(strDate, out Datetime result);

}

 

Category: .Net, General  | 4 Comments
Monday, November 03rd, 2014

This is a follow up to Microsoft Release Management from scratch – Part 1. In this post, we will look at the following things.

  1. Setup Users for Release Management
  2. Download installers for Release Management
  3. Install Release Management Server
  4. Verify Release Management Server was configured properly.
  5. Install Release Management Client
  6. Install Release Management Deployment Agent
  7. Verify Release Management Deployment was configured properly.

Release Management is a three step install – Release Mangement Server, Client and Deployment Agent.

1) Setup Users for Release Management

image

Create 3 users for Release management.

  1. RMServerDude – This user will be used to run the Release Management Server which will be installed.
  2. RMIntegrationDude – This user will be used to integrate Team Foundation Server and Release Management
  3. RMDeploymentAgentDude – This user will be used to run the Deployment agent.

2) Download installers for Release Management

Download the Release Management installers from here. Once download is completed, follow these steps.

3) Install Release Management Server

Click on rm_Server.exe.image

Agree to the terms and conditions and click on install.

image

On completion of installation, click on Launch.image

Once the installation is complete, the following screen pops up. For Release Management Services, use the user account RmServerDude which we created earlier. Give the port and the database details and click on Apply settings.image

On click of apply settings, we get this error. It is pretty straight forward. Release Management Server expects the user running its services to be an administrator.

image

image image

image

Now click on apply settings in the Release Management Server console.

image Now, the Release Management Server configuration succeeds.

4) Verify Release Management Server was configured properly.

Open IIS and click on Application pools. Verify ReleaseManagementAppPool is created.

image

Verify Release Management Website is created.

image

Verify ReleaseManagement database is created.image

5)Install Release Management Client

Click on rm_Client.exe

image

Agree to the terms and conditions and click on Install.image

image

image

Once the setup is complete, click on Launch.image

Configure the Release Management Client to the Release Management Server which was created. Give the Web Server Name and click on Ok. The Release Management client opens.

image

6)Install Release Management Deployment Agent

Click on the installer for Release Management Deployment Agent.image

Agree to the terms and conditions and click on Launch.

image

Configure the Deployment Agent. It is the agent who actually deploys software to the target machine. use the RMDeploymentAgentDude user to run the Deployment Agent. Also enter the Release Management Server URL.

image

This successfully configures the Release Management server.

image

 

7)Verify Release Management Deployment was configured properly.

fire up services.msc from the command prompt. Verify if Release Management Monitor is running as RmServerDude.

image

Verify if Microsoft Deployment Agent is running as RMDeploymentAgentDude.image 

This completes the Microsoft Release Management from scratch – Part 2. Watch out for this space for more updates.

Wednesday, October 29th, 2014

Definition

Wiki says “Chain of responsibility is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain”. A mechanism also exists for adding new processing objects to the end of this chain and avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

 Participants

The classes and objects participating in this pattern are:

Handler  (Handler):

Defines an interface for handling the requests

ConcreteHandler  (EmployeeHandler, ChainTerminationHandler):

Handles requests it is responsible for. It can access its successor

If the ConcreteHandler can handle the request, it does so; otherwise it forwards the request to its successor

Client (Program.cs):

Initiates the request to a ConcreteHandler object on the chain

e1.SetNextHandler(e2);

e2.SetNextHandler(e3);

e3.SetNextHandler(e4);

 

Below sample code snippet explains chain of responsibility design pattern for approval of employee reimbursement application. An employee [ who can be an HR, Admin, CEO, etc] will have an approval limit. Once a reimbursement application is received, each of these employee would check if reimbursement amount is within the approval limit for which they are authorized to. If yes, they would approve else would pass it to the next employee in the chain for approval.

 

namespace COR.Emp.Reimbursement.Lib

{

public interface IReimbursementApprovar

{

Response ApproveReimbursement(IReimbursementReport reimbursementReport);

}

}

 

namespace COR.Emp.Reimbursement.Lib

{

public class Employee : IReimbursementApprovar

{

private string _name;

private readonly double _approvalLimit;

 

public Employee(string name, double approvalLimit)

{

_name = name;

_approvalLimit = approvalLimit;

}

 

public Response ApproveReimbursement(IReimbursementReport reimbursementReport)

{

return reimbursementReport.Total < _approvalLimit ? Response.Approve : Response.LimitExceeded;

}

}

}

 

namespace COR.Emp.Reimbursement.Lib

{

public enum Response

{

Approve,

Reject,

LimitExceeded

}

}

 

namespace COR.Emp.Reimbursement.Lib

{

public interface IReimbursementReport

{

double Total { get; set; }

}

}

 

namespace COR.Emp.Reimbursement.Lib

{

public class ReimbursementReport:IReimbursementReport

{

public ReimbursementReport(double value)

{

Total = value;

}

public double Total { get; set; }

}

}

 

 

namespace COR.Emp.Reimbursement.Lib

{

public abstract class Handler

{

// ReSharper disable once InconsistentNaming

protected Handler NextHandler;

protected IReimbursementApprovar Approvar { get; set; }

 

protected Handler(IReimbursementApprovar approvar)

{

Approvar = approvar;

NextHandler = ChainTerminationHandler.Instance;

}

public void SetNextHandler(Handler handler)

{

this.NextHandler = handler;

}

public abstract Response ApproveReimbursement(IReimbursementReport reimbursementReport);

}

}

 

// ConcreteHandlerHandles requests it is responsible for.

namespace COR.Emp.Reimbursement.Lib

{

public class EmployeeHandler: Handler

{

public EmployeeHandler(IReimbursementApprovar approvar) : base(approvar)

{

}

 

public override Response ApproveReimbursement(IReimbursementReport reimbursementReport)

{

var response = Approvar.ApproveReimbursement(reimbursementReport);

if (response == Response.LimitExceeded)

{

return NextHandler.ApproveReimbursement(reimbursementReport);

}

return response;

}

}

}

// ConcreteHandler : Handles requests it is responsible for.

namespace COR.Emp.Reimbursement.Lib

{

public class ChainTerminationHandler: Handler

{

private static readonly ChainTerminationHandler_instance = new ChainTerminationHandler (new Employee(string.Empty, 0));

 

public static ChainTerminationHandler Instance

{

get { return _instance; }

}

public ChainTerminationHandler(IReimbursementApprovar approvar) : base(approvar)

{

}

 

public override Response ApproveReimbursement(IReimbursementReport reimbursementReport)

{

return ApprovalResponse.Reject;

}

}

}

 

 

private static void Main(string[] args)

{

var e1 = new EmployeeHandler(new Employee(“Barikh”, 0));

var e2 = new EmployeeHandler(new Employee(“Amarnath”, 2000));

var e3 = new EmployeeHandler(new Employee(“Shanti”, 5000));

var e4 = new EmployeeHandler(new Employee(“Rahul”, 20000));

double inputValue;

 

// Construct chain to handle responsibility

e1.SetNextHandler(e2);

e2.SetNextHandler(e3);

e3.SetNextHandler(e4);

 

if (Double.TryParse(Console.ReadLine(), out inputValue))

{

var reimbursementReport= new ReimbursementReport(inputValue);

var response = e1.ApproveReimbursement(reimbursementReport);

Console.WriteLine(“The request was {0}”, response);

Console.ReadKey();

}

}

Tuesday, October 21st, 2014

This is a follow up post of Microsoft Release Management from scratch. In this section, we will look at following steps:-

  1. Spawning a new VM in Azure
  2. Installing Team Foundation Server with basic configuration.
  3. Configuration of the TFS Build Server

Creation a new VM in Azure. Select the option as shown below.

image

 

From the Gallery, we want to choose a server which has Visual Studio 2013 already installed. Click on next icon.

image

Configure the Virtual machine with it’s name and credentials. For this particular tutorial on Release Management, it is recommended to have minimum memory of 7 GB. Click on Next.

image

 

Let us leave the default as it is. Click on next.

image

Ensure “Install the VM Agent” is selected. Once this is done, Click on the tick icon to complete the creation of VM.

image

The next step is to download the installers for Team Foundation Server. The installers can be found here.

Once the installers are downloaded, we will proceed with the Team Foundation Server installation. Click on the tfs_server.exe. Accept the license terms and click on “Install Now”.

image

 

Select the basic installation of TFS. For our purpose, only basic installation of TFS is necessary. Click on “Start Wizard” to start the TFS installation wizard.

image

 

Click on Next.image

 

Install SQL Express since it is not available by default. Click on Next.image

 

Readiness check tells us that all is well. Click on “Configure” to proceed.

image

 

Team Foundation Server related setup succeeds.image

Click on “Close” to finish the setup of Team foundation Server.

image

 

Since the setup is complete, it is time to configure Team Foundation Server build. Open the Team Foundation Server Administration Console. Select Build Configuration and click on “Configure Installed features”.

image

Select “Configure Team Foundation Build Service”.  Click on “Start Wizard”

image

This opens up the Build Service Configuration wizard. Click on “Next”

image

 

Select the DefaultCollection and click on “Next”.

image 

 

Select “Use the default setting” and click on “Next”

image

 

Let TFS Build Service run as a System Account. By default it is configured to run as

NT AUTHORITY\LOCAL SERVICE. Click on Next.image

 

Click on Next for Readiness Checks.image

Build Configuration takes some time. Once it succeeds the following messages are shown. Click on Next.image

Click on Close.

image

 

Click on Build Configuration to see the Build Controller and Agent.

image

This completes the part 1 of the series Microsoft Release Management from scratch.

Tuesday, October 21st, 2014

I have been exploring Microsoft Release Management and I thought I will document the pain points which i went through while learning them it.

I will be starting from scratch here. Yes, absolutely from scratch! Right from spawning a new VM in Azure to the complete installation of Release Management.

These are the steps which we will follow to install Release Management

  1. Spawn a new VM in Azure.
  2. Install TFS with basic configuration
  3. Setup Build Controller
  4. Setup User Accounts for Release Management
  5. Install Release Management
    • Install Release Management Server
    • Install Release Management Client
    • Install Release Management Deployment Agent
  6. Configure Release Management Client
  7. Setup a Build Pipeline
  8. Trigger a release

Since, this is quite a long adventure I am documenting it in different parts.

Friday, October 17th, 2014

Transaction Commit Failure is another ground breaking feature that is available from EF 6.0.1 and above. While Connection Resilency handles the way to acquire connections !, Connection Resilency has no control on what happened with the connection, i.e the transaction succeeded with the connection or not. Here comes Transaction Commit Failure Feature to rescue.When an exception is raised during a transaction commit there are two possible causes:

  • The transaction commit failed on the server
  • The transaction commit succeeded on the server but a connectivity issue prevented the success notification from reaching the client

When the first situation happens the application or the user can retry the operation, but when the second situation occurs retries should be avoided and the application could recover automatically. The challenge is that without the ability to detect what was the actual reason an exception was reported during commit, the application cannot choose the right course of action. The new feature allows EF to double-check with the database if the transaction succeeded and take the right course of action transparently.So its very clear that, to put Second situation into practice, We would need to disable Connection Resilency temporarily.

To enable this feature, include the call to SetTransactionHandler(..) in the constructor of DbConfiguration., like below.

public class CustomConfiguration : DbConfiguration
    {
        public CustomConfiguration()
        {
            this.SetExecutionStrategy(SqlProviderServices.ProviderInvariantName, () => (IDbExecutionStrategy)new DefaultExecutionStrategy());

            this.SetTransactionHandler(SqlProviderServices.ProviderInvariantName, () => new CommitFailureHandler(c => new CustomTransactionContext(c)));
        }
    }

CommitFailureHandler is provided by EF out of the box, However other interesting class to note is CustomTransactionContext, inheriting from TransactionContext, provided by EF out of the box. Here is the definition of CustomTransactionContext

using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;

namespace ConsoleApplication1
{
    public class CustomTransactionContext : TransactionContext
    {
        public CustomTransactionContext(DbConnection existingConnection)
            : base(existingConnection)
        {
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<TransactionRow>().ToTable("TransactionHistory");
        }
    }
}

When the feature is enabled, EF will automatically add a new table to the database called “__Transactions”, which we renamed as “TransactionHistory”. A new row is inserted in this table every time a transaction is created by EF and that row is checked for existence if a transaction failure occurs during commit. If the row exists the exception will be ignored and the application will continue normally. If it does not then the exception is rethrown, triggering the retry logic for the failed operation.

using (var ctx = new StudentContext())
            {
                ctx.Database.Initialize(false);
                var commitHandler = CommitFailureHandler.FromContext(ctx);

                if (commitHandler != null)
                {
                    commitHandler.ClearTransactionHistory();
                }
                
                using (var transaction = ctx.Database.BeginTransaction(IsolationLevel.ReadCommitted))
                {
                    ctx.Students.Add(new Student()
                    {
                        Name = "Shashank",
                        Address = new Address() { AddressId = 121, AddressLine1 = "Bannerghatta Road", AddressLine2 = "JP Nagar Phase 4", AddressLine3 = "Near IIMB" },
                        DateOfBirth = new DateTime(1980, 1, 1)
                    });

                    ctx.Students.Add(new Student()
                    {
                        Name = "Meera",
                        Address = new Address() { AddressId = 131, AddressLine1 = "Behind Carlton Towers", AddressLine2 = "Old Airport Road", AddressLine3 = "Domlur" },
                        DateOfBirth = new DateTime(1982, 1, 1)
                    });

                    ctx.Students.Add(new Student()
                    {
                        Name = "Mohit",
                        Address = new Address() { AddressId = 141, AddressLine1 = "Inner Ring Road", AddressLine2 = "Near Sony Signal", AddressLine3 = "Eijapura" },
                        DateOfBirth = new DateTime(1986, 1, 1)
                    });

                    ctx.Students.Add(new Student()
                    {
                        Name = "Krishna",
                        Address = new Address() { AddressId = 181, AddressLine1 = "Old Airport Road", AddressLine2 = "Near Rajeswari Theatre", AddressLine3 = "Murghesh Palya" },
                        DateOfBirth = new DateTime(1984, 1, 1)
                    });

                    ctx.Students.Add(new Student()
                    {
                        Name = "Sai C",
                        Address = new Address() { AddressId = 191, AddressLine1 = "Behind KR Pural Railway Station", AddressLine2 = "Vijinapura", AddressLine3 = "Tin Factory" },
                        DateOfBirth = new DateTime(1986, 1, 1)
                    });

                    ctx.SaveChanges();

                    transaction.Commit();
                    
                }
            }

Once the above transaction is complete, EF inserts record in TransactionHistory table as below.
TransactionHistory

Category: .Net | Tags:  | Leave a Comment
Thursday, October 16th, 2014

In my previous blog posts on Connection Resilency, we went in to deep dive understanding what Connection Resilency is all about and possible work arounds for user initiated transactions. In this blog post,I am trying to address how to handle deadlocks and other timeout failures. When connection to sql server goes to deadlock, we need to provide mechanism of retrying to acquire a connection., Or when connection to sql server times out, we want to provide the mechanism of retrying. Inherit from DbExecutionStrategy and override methods to handle Retries as below. Since I am working with SqlServer, I know what error code sqlserver emits for Deadlock scenarios as below. Btw,These error codes may vary from one provider to another provider.

    public class SqlServerExecutionStrategy : DbExecutionStrategy
    {
        private readonly DateTime _establishTime;
        private readonly TimeSpan _maxDelay;
        public SqlServerExecutionStrategy()
        { }

        public SqlServerExecutionStrategy(int maxRetryCount, TimeSpan maxDelay)
        {
            this._establishTime = DateTime.UtcNow;
            this._maxDelay = maxDelay;
        }

        protected override bool ShouldRetryOn(Exception ex)
        {
            var sqlException = ex as SqlException;
            if (sqlException == null)
                return false; // donot retry

            foreach (var error in sqlException.Errors.Cast<SqlError>())
            {
                switch (error.Number)
                {
                    // Deadlock Error Code
                    case 1205:
                    // Timeout Error Code
                    case -1:
                    // Timeout Error Code
                    case -2:
                        return true; // retry
                }
            }

            return false;
        }

        protected override TimeSpan? GetNextDelay(Exception lastException)
        {
            return DateTime.UtcNow.Subtract(_establishTime.Add(this._maxDelay));
        }
    }

Now hook our SqlServerExecutionStrategy into our CustomConfiguration as below

public class CustomConfiguration : DbConfiguration
    {
        public CustomConfiguration()
        {
            this.SetExecutionStrategy("System.Data.SqlClient",()=>new SqlServerExecutionStrategy(1,TimeSpan.FromSeconds(30)));
        }

    }

You are done! Now if your application encounters any deadlock issues with sqlserver Or timeout issues, SqlServerExecutionStrategy will automatically hook into the pipeline to start retrying

Category: .Net | Tags:  | Leave a Comment
Wednesday, October 15th, 2014

In my previous blog post, we had a deep dive into Connection Resilency, In this post, I will be solving a problem – where we can control temporarily disable Connection Resilency for the cases where Retries does not make sense!. By default Entity Framework pushes all changes to database by using Transaction. If user initiates transaction, Entity Framework does not know, what are all subsequent deltas it needs to process post connection failure where retries come into action. In cases like this, where user initiates transaction, Suspend Execution Strategy would be handy.

using (var ctx = new StudentContext())
            {
                // Batch 1
                ctx.Students.Add(new Student()
                {
                    Name = "Shashank",
                    Address = new Address() { AddressId = 121, AddressLine1 = "Bannerghatta Road",AddressLine2 = "JP Nagar Phase 4", AddressLine3 = "Near IIMB"},
                    DateOfBirth = new DateTime(1980,1,1)
                });

                ctx.Students.Add(new Student()
                {
                    Name = "Meera",
                    Address = new Address() { AddressId = 131, AddressLine1 = "Behind Carlton Towers", AddressLine2 = "Old Airport Road", AddressLine3 = "Domlur" },
                    DateOfBirth = new DateTime(1982, 1, 1)
                });

                ctx.Students.Add(new Student()
                {
                    Name = "Mohit",
                    Address = new Address() { AddressId = 141, AddressLine1 = "Inner Ring Road", AddressLine2 = "Near Sony Signal", AddressLine3 = "Eijapura" },
                    DateOfBirth = new DateTime(1986, 1, 1)
                });

                ctx.SaveChanges();

                // Batch 2
                ctx.Students.Add(new Student()
                {
                    Name = "Krishna",
                    Address = new Address() { AddressId = 181, AddressLine1 = "Old Airport Road", AddressLine2 = "Near Rajeswari Theatre", AddressLine3 = "Murghesh Palya" },
                    DateOfBirth = new DateTime(1984, 1, 1)
                });

                ctx.Students.Add(new Student()
                {
                    Name = "Sai C",
                    Address = new Address() { AddressId = 191, AddressLine1 = "Behind KR Pural Railway Station", AddressLine2 = "Vijinapura", AddressLine3 = "Tin Factory" },
                    DateOfBirth = new DateTime(1986, 1, 1)
                });

                ctx.SaveChanges();
            }

In the above example, we are sending two batches to database, If it happens that first batch succeded and second batch failed, Entity Framework will be in no position to know where it has to start sending the batches to db i.e batch1 or batch2., In the cases like this, Suspend Execution Strategy will be useful, Remember: Suspend Execution is just a workaround, not a bullet proof solution.

public class SqlServerExecutionStrategy : DbExecutionStrategy
    {
        public SqlServerExecutionStrategy()
        { }

        public SqlServerExecutionStrategy(int maxRetryCount, TimeSpan maxDelay)
            : base(maxRetryCount, maxDelay)
        { }

        protected override bool ShouldRetryOn(Exception ex)
        {
            //TODO: Handle retries
        }
    }

Once I have SqlServerStrategy defined, all need to be done is hook this strategy in your code as below.

public class CustomConfiguration : DbConfiguration
    {
        public CustomConfiguration()
        {
            this.SetExecutionStrategy("System.Data.SqlClient", () => SuspendExecutionStrategy
              ? (IDbExecutionStrategy)new DefaultExecutionStrategy()
              : new SqlServerExecutionStrategy(1,TimeSpan.FromSeconds(30)));
        }

        public static bool SuspendExecutionStrategy
        {
            get
            {
                return (bool?)CallContext.LogicalGetData("SuspendExecutionStrategy") ?? false;
            }
            set
            {
                CallContext.LogicalSetData("SuspendExecutionStrategy", value);
            }
        }
    }

using (var ctx = new StudentContext())
            {
                CustomConfiguration.SuspendExecutionStrategy = true;

                // Batch 1
                // Insert 1
                // Insert 2
                // Insert 3

                ctx.SaveChanges();

                // Batch 2
                // Insert 4.......
                // Insert 5
                ctx.SaveChanges();

                CustomConfiguration.SuspendExecutionStrategy = false;
            }

With SuspendExecutionStrategy, we dont have to worry about transient failures!

Category: .Net | Tags:  | Leave a Comment