Entity Framework Core and LINQ to Entities (9) Performance

[LINQ via C# series]

[Entity Framework Core series]

[Entity Framework series]

EF version of this article: https://weblogs.asp.net/dixin/entity-framework-and-linq-to-entities-10-performance

The previous parts has discussed some aspects that can impact the performance of EF/Core and LINQ to Entities, and here is a summary:

  • Remote LINQ to Entities query can have better performance than local or hybrid query. An intuitive example is Last query for a table data source, which could query the entire table, load data to local, and query the last result locally. It is better to just have a remote query and only load the specific result.
  • Using Select to only query the  data can have better performance than querying full entity.
  • Disabling entity tracking can improve the performance.
  • Disabling automatic change detection can improve the performance.
  • When adding a sequence of entities to repository, DbSet<T>.AddRange/DbSet<T>.RemoveRange call can have better performance than many DbSet<T>.Add/DbSet<T>.Remove calls.

And, in EF, with lazy loading, accessing an entity’s navigation property can cause additional database query round trips (the N + 1 queries problem). Eager loading can improve the performance by read all needed data with 1 single database query.

This part continues the discussion of performance.

Initialization

EF dies a lot of initialization work before the first database query is executed.

The following example simply pulls categories from the repository, with one LINQ to Entities query:’

internal static partial class Performance
{
    internal static void Initialize()
    {
        using (AdventureWorks adventureWorks = new AdventureWorks())
        {
            IQueryable<ProductCategory> categories = adventureWorks.ProductCategories;
            categories.WriteLines(category => category.Name);
            // select cast(serverproperty('EngineEdition') as int)

            // SELECT Count(*)
            // FROM INFORMATION_SCHEMA.TABLES AS t
            // WHERE t.TABLE_SCHEMA + '.' + t.TABLE_NAME IN ('HumanResources.Employee','Person.Person','Production.ProductCategory','Production.ProductSubcategory','Production.Product','Production.ProductProductPhoto','Production.ProductPhoto','Production.TransactionHistory','HumanResources.vEmployee') 
            //    OR t.TABLE_NAME = 'EdmMetadata'
            // exec sp_executesql N'SELECT 
            //    [GroupBy1].[A1] AS [C1]
            //    FROM ( SELECT 
            //        COUNT(1) AS [A1]
            //        FROM [dbo].[__MigrationHistory] AS [Extent1]
            //        WHERE [Extent1].[ContextKey] = @p__linq__0
            //    )  AS [GroupBy1]',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'AdventureWorks'
            // SELECT 
            //    [GroupBy1].[A1] AS [C1]
            //    FROM ( SELECT 
            //        COUNT(1) AS [A1]
            //        FROM [dbo].[__MigrationHistory] AS [Extent1]
            //    )  AS [GroupBy1]
            // SELECT TOP (1) 
            //    [Extent1].[Id] AS [Id], 
            //    [Extent1].[ModelHash] AS [ModelHash]
            //    FROM [dbo].[EdmMetadata] AS [Extent1]
            //    ORDER BY [Extent1].[Id] DESC
            // SELECT 
            //    [Extent1].[ProductCategoryID] AS [ProductCategoryID], 
            //    [Extent1].[Name] AS [Name]
            //    FROM [Production].[ProductCategory] AS [Extent1]
        }
    }
}

Executing above code, a bunch of SQL queries can be traced. And only the last SELECT query is the expected LINQ to Entities query translation. Actually, before a database’s first operation at runtime (e.g., querying Production.ProductCategory table here), EF does a lot of work to initialize its object-relational mapping:

  1. Initialize provider manifest
  2. Initialize the entity data model. EF automatically builds the object models (CLR models, not above entities), conceptual models, storage models, object-conceptual model mappings, conceptual-storage model mappings, etc..
  3. Initialize the database, if needed.
  4. Initialize mapping views, which are the mapping information for entity sets.
  5. Initialize a dynamic assembly "EntityFrameworkDynamicProxies-{OriginalAssemblyName}, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", and define proxy types in it.

The above initialization steps executes only once at runtime, and their performance can be improved from the default behavior.

Provider initialization

As fore mentioned, EF implements the provider model to work with different kinds of data stores, and it need to get the basic information of current data store. For SQL database:

  • The SQL database server’s version is detected by calling DbConnection.ServerVersion
  • The engine edition is queried by above SERVERPROPERTY metadata function, to determine whether it is a on premise database (SQL Server) or cloud database (SQL Azure, aka Azure SQL Database).

For SQL database, the supported provider manifest tokens are:

namespace System.Data.Entity.SqlServer
{
    internal class SqlProviderManifest : DbXmlEnabledProviderManifest
    {
        internal const string TokenSql8 = "2000";

        internal const string TokenSql9 = "2005";

        internal const string TokenSql10 = "2008";

        internal const string TokenSql11 = "2012";

        internal const string TokenAzure11 = "2012.Azure";

        // Other members.
    }
}

For any on premise SQL database later than 11.0, just use “2012”. For cloud SQL database, use “2012.Azure”. In this tutorial, the server version and engine edition is known. So these information can be provided to EF via System.Data.Entity.Infrastructure.IManifestTokenResolver:

public class SqlConfiguration : DbConfiguration
{
    public SqlConfiguration() =>
            this.SetManifestTokenResolver(new SqlManifestTokenResolver());
}

public class SqlManifestTokenResolver : IManifestTokenResolver
{
    public string ResolveManifestToken(DbConnection connection) => "2012.Azure";
}

Then engine edition query is not executed during initialization. Notice EF only support defining a single type derived from DbConfiguration. In the object-relational mapping part, there us already a RetryConfiguration type defined to specify the retry strategy. The logic in both types must be merged intto one type, otherwise EF throws exception during initialization.

Database initialization

The database initialization work is represented by System.Data.Entity.IDatabaseInitializer<TContext> interface:

namespace System.Data.Entity
{
    public interface IDatabaseInitializer<in TContext> where TContext : DbContext
    {
        void InitializeDatabase(TContext context);
    }
}

EF provides several built-in initializers under System.Data.Entity namespace:

  • NullDatabaseInitializer<TContext>: Do nothing for initialization
  • DropCreateDatabaseAlways<TContext>: Always drop the database and create again
  • DropCreateDatabaseIfModelChanges<TContext>: Drop and create database when the code mapping mismatches database schema.
  • MigrateDatabaseToLatestVersion<TContext, TMigrationsConfiguration>: Use the specified code to update the database to the latest version.
  • CreateDatabaseIfNotExists<TContext>: Create database if not exist.

CreateDatabaseIfNotExists<TContext>: is the default initializer, so it is executed here too. As a result, EF attempts to query the existence of the mapped tables and views, database migration history, and entity data model info, etc. Apparently, here AdventureWorks database does not have the migration and entity data model info; recreating database is not needed as well. So the database initialization can be turned off, by setting the initializer to NullDatabaseInitializer<TContext>:

public partial class AdventureWorks
{
    static AdventureWorks()
    {
        Database.SetInitializer(new NullDatabaseInitializer<AdventureWorks>()); // Call once.
        // Equivalent to: Database.SetInitializer<AdventureWorks>(null);
    }
}

where NullDatabaseInitializer<TContext> provide empty operation that does nothing:

namespace System.Data.Entity
{
    public class NullDatabaseInitializer<TContext> : IDatabaseInitializer<TContext> where TContext : DbContext
    {
        public virtual void InitializeDatabase(TContext context)
        {
        }
    }
}

Now all the additional database queries for initialization are turned off.

Mapping views initialization

In EF, mapping views are not the views inside the database. They are System.Data.Entity.Infrastructure.MappingViews.DbMappingView instances, representing the mapping information for entity sets. Instead of generate these instances at runtime, pre-generate them at design time can improve the performance. Microsoft provides a Visual Studio extension, EF Power Tools, to generate these code. It needs to be modified to installed with the latest Visual Studio. After the installation, just right click the code file containing the database mapping (the class derived from DbContext), and in the menu click EF => Generate Views, it generates a file, containing the code to create the DbMappingView instances.

Cache

After the object-relational mapping metadata is initialized, they are cached, so that the initialization only happens once for the AppDomain. EF/Core also implement cache for entities and query translation.

Entity cache

As fore mentioned, by default, the entities queried from repository are cached and tracked. This behavior can be demonstrated by the following example:

internal static void CachedEntity(AdventureWorks adventureWorks)
{
    ProductCategory categoryCopy1 = adventureWorks.ProductCategories
        .Single(entity => entity.ProductCategoryID == 1);
    categoryCopy1.Name = "Cache";

    ProductCategory categoryCopy2 = adventureWorks.ProductCategories
        .Single(entity => entity.Name == "Bikes");
    categoryCopy2.Name.WriteLine(); // Cache
    object.ReferenceEquals(categoryCopy1, categoryCopy2).WriteLine(); // True

    ProductCategory categoryCopy3 = adventureWorks.ProductCategories
#if EF
        .SqlQuery(
#else
        .FromSql(
#endif
            @"SELECT TOP (1) [ProductCategory].[ProductCategoryID], [ProductCategory].[Name]
            FROM [Production].[ProductCategory]
            ORDER BY [ProductCategory].[ProductCategoryID]")
        .Single();
    object.ReferenceEquals(categoryCopy1, categoryCopy3).WriteLine(); // True
}

In this example, the first query reads data from the repository and materialize the data to a category entity, and update its Name. Then the repository is queried again by Name. After reading the data, EF/Core find the primary key is the same as the cached entity, so EF/Core do not materialize the data just read, it reuses the previous category entity. Performance can be improved by skipping the materialization, but tricky result can happen. The second query reads entity with Name “Bikes”, but the query result entity has Name “Cache”. This is not only LINQ to Entities queries’ behavior, When DbSet<T> directly executes SQL query in the repository, EF/Core still uses cached entities.

Entity is not cached when tracking is turned off, or entity is not queried from the repository. Each of the following queries materializes a new entity:

internal static void UncachedEntity(AdventureWorks adventureWorks)
{
    ProductCategory categoryCopy1 = adventureWorks.ProductCategories
        .Single(entity => entity.ProductCategoryID == 1);
    categoryCopy1.Name = "Cache";

    ProductCategory categoryCopy2 = adventureWorks.ProductCategories
        .AsNoTracking().Single(entity => entity.Name == "Bikes");
    categoryCopy2.Name.WriteLine(); // Bikes
    object.ReferenceEquals(categoryCopy1, categoryCopy2).WriteLine(); // False

    ProductCategory categoryCopy3 = adventureWorks.ProductCategories
#if EF
        .SqlQuery(
#else
        .FromSql(
#endif
            @"SELECT TOP (1) [ProductCategory].[ProductCategoryID], [ProductCategory].[Name]
            FROM [Production].[ProductCategory]
            ORDER BY [ProductCategory].[ProductCategoryID]")
        .AsNoTracking()
        .Single();
    object.ReferenceEquals(categoryCopy1, categoryCopy3).WriteLine(); // False

#if EF
    ProductCategory categoryCopy4 = adventureWorks.Database
        .SqlQuery<ProductCategory>(@"
            SELECT TOP (1) [ProductCategory].[ProductCategoryID], [ProductCategory].[Name]
            FROM [Production].[ProductCategory]
            ORDER BY [ProductCategory].[ProductCategoryID]")
        .Single();
    object.ReferenceEquals(categoryCopy1, categoryCopy4).WriteLine(); // False
#endif
}

DbSet.Find accept the primary keys and returns an entity. Calling Find can improve the performance, because it looks up cache before querying the repository:

internal static void Find(AdventureWorks adventureWorks)
{
    Product[] products = adventureWorks.Products
        .Where(entity => entity.Name.StartsWith("Road")).ToArray(); // Execute query.
    Product product = adventureWorks.Products.Find(999); // No database query.
    object.ReferenceEquals(products.Last(), product).WriteLine(); // True
}

Here when Find is called, entity with the specified primary key is already queries, cached and tracked, so Find directly returns the cached entity, without repository query or data materialization.

LINQ query translation cache

As discussed in the query translation part, EF/Core translate a LINQ to Entities query in 2 steps:

  • Compile LINQ expression tree to database expression tree
  • Generate SQL from database expression tree

To improve the performance, EF Core caches the query translations in a Microsoft.Extensions.Caching.Memory.MemoryCache. Before processing a LINQ query, EF Core computes the cache key, and looks up the cache. If the translation is found, then it reuses the translation; if not, it translates the query, and add the translation to cache.. For SQL database queries, the cache key’s hash code is computed with the the hash code of the following values:

  • The LINQ query expression tree. The LINQ query expression tree is scanned recursively, the hash code of the nodes and APIs represented by the expression tree nodes are used to compute the hash code of the entire expression tree.
  • DbContext.Model
  • DbContext.ChangeTracker.QueryTrackingBehavior, which is an enumeration of TrackAll or NoTracking
  • A Boolean value that indicates whether the query is executed asynchronously
  • SqlServerOptionsExtension.UseRelationalNulls, which can be specified with SqlServerDbContextOptionsBuilder.UseRelationalNulls
  • SqlServerOptionsExtension.RowNumberPaging, which can be specified with SqlServerDbContextOptionsBuilder.UseRowNumberForPaging

EF always compiles the LINQ expression tree to database expression tree, then cache the SQL generation in a dictionary. For example:

internal static void TranslationCache(AdventureWorks adventureWorks)
{
    int minLength = 1;
    IQueryable<Product> query = adventureWorks.Products
        .Where(product => product.Name.Length >= minLength)
        .Include(product => product.ProductSubcategory);
    query.Load();
}

EF generates the cache key with the following values:

  • The database expression tree’s string representation. Here it is: [Filter](BV'LQ1'=([Scan](AdventureWorks.Products:Transient.collection[Product(Nullable=True,DefaultValue=)]))([>=](FUNC<Edm.Length(In Edm.String(Nullable=True,DefaultValue=,MaxLength=,Unicode=,FixedLength=))>:ARGS((Var('LQ1')[.]Name)),@p__linq__0:Edm.Int32(Nullable=False,DefaultValue=))))
  • The parameters’ string representation: @@1p__linq__0:System.Int32
  • The path of the Include query. Here it is ProductSubcategory
  • The query’s MergeOption, which is AppendOnly by default.
  • System.Data.Entity.Core.Objects.ObjectContextOptions.UseCSharpNullComparisonBehavior

The following example executes 2 LINQ to Entities queries:

internal static void UnreusedTranslationCache(AdventureWorks adventureWorks)
{
    IQueryable<Product> queryWithConstant1 = adventureWorks.Products
        .Where(product => product.Name.Length >= 1);
    queryWithConstant1.Load();

    IQueryable<Product> queryWithConstant2 = adventureWorks.Products
        .Where(product => product.Name.Length >= 10);
    queryWithConstant2.Load();
}

These first LINQ query builds expression trees with a ConstantExpression node representing int value 1. The second query builds similar expression tree but with a different ConstantExpression node representing int value 10. So these LINQ expression trees are different. In EF Core, the first expression tree’s translation cannot be reused for the second query.

In EF, their compiled database expression trees are different too, with 2 different DbConstantExpression nodes. The 2 database expression trees’ string representations are:

  • [Filter](BV'LQ1'=([Scan](AdventureWorks.ProductCategories:Transient.collection[ProductCategory(Nullable=True,DefaultValue=)]))([>=](FUNC<Edm.Length(In Edm.String(Nullable=True,DefaultValue=,MaxLength=,Unicode=,FixedLength=))>:ARGS((Var('LQ1')[.]Name)),1:Edm.Int32(Nullable=True,DefaultValue=))))
  • [Filter](BV'LQ1'=([Scan](AdventureWorks.ProductCategories:Transient.collection[ProductCategory(Nullable=True,DefaultValue=)]))([>=](FUNC<Edm.Length(In Edm.String(Nullable=True,DefaultValue=,MaxLength=,Unicode=,FixedLength=))>:ARGS((Var('LQ1')[.]Name)),10:Edm.Int32(Nullable=True,DefaultValue=))))

So the first query’s SQL generation cannot be used for the second query either.

To reuse the translation cache, these queries can be parameterized by simply replace the constants with variables:

internal static void ReusedTranslationCache(AdventureWorks adventureWorks)
{
    int minLength = 1;
    IQueryable<Product> queryWithClosure1 = adventureWorks.Products
        .Where(product => product.Name.Length >= minLength);
    queryWithClosure1.Load();

    minLength = 10;
    IQueryable<Product> queryWithClosure2 = adventureWorks.Products
        .Where(product => product.Name.Length >= minLength);
    queryWithClosure2.Load();
}

As discussed in the C# features chapter, the predicate lambda expressions capture variable minLength with the closure syntactic sugar. The above code is compiled to:

internal static void ReusedTranslationCache(AdventureWorks adventureWorks)
{
    int minLength = 1;
    IQueryable<Product> queryWithClosure1 = adventureWorks.Products
        .Where(product => product.Name.Length >= minLength);
    queryWithClosure1.Load();

    minLength = 10;
    IQueryable<Product> queryWithClosure2 = adventureWorks.Products
        .Where(product => product.Name.Length >= minLength);
    queryWithClosure2.Load();
}

In the predicates, the outer variable access is compiled to field access. So in the LINQ queries’ expression trees, there are no longer ConstantExpression nodes representing different int values, but MemberExpression nodes representing the same field. As a result, the 2 query’s LINQ expression trees are identical, and the translation is reused.

In EF, if a query method accepts values instead of lambda expression, this parameterization approach does not work. For example, Skip and Take accept int values as parameters:

internal static void UnresuedSkipTakeTranslationCache(AdventureWorks adventureWorks)
{
    int skip = 1;
    int take = 1;
    IQueryable<Product> skipTakeWithVariable1 = adventureWorks.Products
        .OrderBy(product => product.ProductID).Skip(skip).Take(take);
    skipTakeWithVariable1.Load();

    skip = 10;
    take = 10;
    IQueryable<Product> skipTakeWithVariable2 = adventureWorks.Products
        .OrderBy(product => product.ProductID).Skip(skip).Take(take);
    skipTakeWithVariable2.Load();
}

The above LINQ queries access to variable skip and take, but these variable access are also represented by ConstantExpression nodes. So their expression trees are different, and converted database command trees are different, and their translations cannot be reused for each other. To resolve this problem, EF provides a lambda expression version for these methods:

namespace System.Data.Entity
{
    public static class QueryableExtensions
    {
        public static IQueryable<TSource> Skip<TSource>(this IQueryable<TSource> source, Expression<Func<int>> countAccessor);

        public static IQueryable<TSource> Take<TSource>(this IQueryable<TSource> source, Expression<Func<int>> countAccessor);
    }
}

Now Skip and Take can access variables via closure:

internal static void ResuedSkipTakeTranslationCache(AdventureWorks adventureWorks)
{
    int skip = 1;
    int take = 1;
    IQueryable<Product> skipTakeWithClosure1 = adventureWorks.Products
        .OrderBy(product => product.ProductID).Skip(() => skip).Take(() => take);
    skipTakeWithClosure1.Load();

    skip = 10;
    take = 10;
    IQueryable<Product> skipTakeWithClosure2 = adventureWorks.Products
        .OrderBy(product => product.ProductID).Skip(() => skip).Take(() => take);
    skipTakeWithClosure2.Load();
}

These LINQ queries have MemberExpression nodes again. EF can convert them to identical parameterized database expression trees. Now their translations can be reused for each other.

SQL query plan cache

LINQ queries with different constants are translated to different SQL queries. Above queryWithConstant1 and queryWithConstant2 are translated to:

SELECT [product].[ProductID], [product].[ListPrice], [product].[Name], [product].[ProductSubcategoryID], [product].[RowVersion]
FROM [Production].[Product] AS [product]
WHERE LEN([product].[Name]) >= 1

SELECT [product].[ProductID], [product].[ListPrice], [product].[Name], [product].[ProductSubcategoryID], [product].[RowVersion]
FROM [Production].[Product] AS [product]
WHERE LEN([product].[Name]) >= 10

Apparently they have different query plans in SQL database, which cannot be reused for each other:

image

With parameterization, queryWithClosure1 and queryWithClosure2 are translated to identical SQL queries, with different parameter values:

exec sp_executesql N'SELECT [product].[ProductID], [product].[ListPrice], [product].[Name], [product].[ProductSubcategoryID], [product].[RowVersion]
FROM [Production].[Product] AS [product]
WHERE LEN([product].[Name]) >= @__minLength_0',N'@__minLength_0 int',@__minLength_0=1

exec sp_executesql N'SELECT [product].[ProductID], [product].[ListPrice], [product].[Name], [product].[ProductSubcategoryID], [product].[RowVersion]
FROM [Production].[Product] AS [product]
WHERE LEN([product].[Name]) >= @__minLength_0',N'@__minLength_0 int',@__minLength_0=10

So in SQL database, queryWithClosure1’s query plan is cached and reused for queryWithClosure2:

image

Asynchrony

Generally, for long running I/O bound operation,  asynchrony can improve the application responsiveness and service scalability. EF/Core support asynchrony for database CRUD operations, and these async APIs are very easy to use with C# async/await keywords. Please notice this does not mean all the synchronous API calls must be replaced by asynchronous API calls, the application must be tested to identify which API has better performance.

Asynchronous data queries and data changes

For LINQ to Entities queries, EF/Core start to read the data when values are pulled from IQueryable<T> data source, for example:

  • Pull the values from the query represented by IQueryable<T>.
  • Call a query method to return a single value from the IQueryable<T>, like First, etc..
  • Call a LINQ to Objects query method to return a new collection, like ToArray, etc..

For these operations and APIs, async parities are provided as IQueryable<T> extension methods. In EF Core, these async query APIs are also provided as extension methods in Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions:

  • async iteration method: ForEachAsync asynchronously pulls each value from IQueryable<T> data source and call the specified function.
  • async methods to return a single value:
    • Element: FirstAsync, FirstOrDefaultAsync, LastAsync, LastOrDefaultAsync, SingleAsync, SingleOrDefaultAsync
    • Aggregation: CountAsync, LongCountAsync, MinAsync, MaxAsync, SumAsync, AverageAsync
    • Quantifier: AllAsync, AnyAsync, ContainsAsync
  • async methods to return a new collection: ToArrayAsync, ToDictionaryAsync, ToListAsync

In EF, these methods are provided in System.Data.Entity.QueryableExtensions, and LastAsync, LastOrDefaultAsync are not provided, since EF does not support Last, LastOrDefault.

For data changes, DbContext.SaveChangesAsync is provided as a parity of DbContext.SaveChanges. For example:

internal static async Task Async(AdventureWorks adventureWorks)
{
    IQueryable<ProductCategory> categories = adventureWorks.ProductCategories;
    await categories.ForEachAsync( // Async version of foreach/ForEach.
        category => category.Name.WriteLine());

    ProductSubcategory subcategory = await adventureWorks.ProductSubcategories
        .FirstAsync(entity => entity.Name.Contains("Bike")); // Async version of First.
    subcategory.Name.WriteLine();

    Product[] products = await adventureWorks.Products
        .Where(product => product.ListPrice <= 10)
        .ToArrayAsync(); // Async version of ToArray.

    adventureWorks.Products.RemoveRange(products);
    (await adventureWorks.SaveChangesAsync()).WriteLine(); // Async version of SaveChanges.
}

Transactions and connection resiliency with asynchronous operations

These async APIs work in EF/Core transaction. In this tutorial, connection resiliency is enabled because cloud SQL database is used, so call the retry strategy’s ExecuteAsync method:

internal static async Task DbContextTransactionAsync(AdventureWorks adventureWorks)
{
    await adventureWorks.Database.CreateExecutionStrategy().ExecuteAsync(async () =>
    {
#if EF
        using (IDbContextTransaction transaction = adventureWorks.Database.BeginTransaction(
#else
        using (IDbContextTransaction transaction = await adventureWorks.Database.BeginTransactionAsync(
#endif
            IsolationLevel.ReadUncommitted))
        {
            try
            {
                adventureWorks.CurrentIsolationLevel().WriteLine(); // ReadUncommitted

                ProductCategory category = new ProductCategory() { Name = nameof(ProductCategory) };
#if EF
                adventureWorks.ProductCategories.Add(category);
#else
                await adventureWorks.ProductCategories.AddAsync(category);
#endif
                (await adventureWorks.SaveChangesAsync()).WriteLine(); // 1

                await adventureWorks.Database.ExecuteSqlCommandAsync(
                    sql: "DELETE FROM [Production].[ProductCategory] WHERE [Name] = {0}",
                    parameters: nameof(ProductCategory)).WriteLine(); // 1
                transaction.Commit();
            }
            catch
            {
                transaction.Rollback();
                throw;
            }
        }
    });
}

These async APIs also work in ADO.NET transaction:

internal static async Task DbTransactionAsync()
{
    using (SqlConnection connection = new SqlConnection(ConnectionStrings.AdventureWorks))
    {
        await connection.OpenAsync();
        using (DbTransaction transaction = connection.BeginTransaction(IsolationLevel.Serializable))
        {
            try
            {
                using (AdventureWorks adventureWorks = new AdventureWorks(connection))
                {
                    await adventureWorks.Database.CreateExecutionStrategy().ExecuteAsync(async () =>
                    {
                        adventureWorks.Database.UseTransaction(transaction);
                        adventureWorks.CurrentIsolationLevel().WriteLine(); // Serializable

                        ProductCategory category = new ProductCategory() { Name = nameof(ProductCategory) };
#if EF
                        adventureWorks.ProductCategories.Add(category);
#else
                        await adventureWorks.ProductCategories.AddAsync(category);
#endif
                        (await adventureWorks.SaveChangesAsync()).WriteLine(); // 1.
                    });
                }

                using (DbCommand command = connection.CreateCommand())
                {
                    command.CommandText = "DELETE FROM [Production].[ProductCategory] WHERE [Name] = @p0";
                    DbParameter parameter = command.CreateParameter();
                    parameter.ParameterName = "@p0";
                    parameter.Value = nameof(ProductCategory);
                    command.Parameters.Add(parameter);
                    command.Transaction = transaction;
                    (await command.ExecuteNonQueryAsync()).WriteLine(); // 1
                }
                transaction.Commit();
            }
            catch
            {
                transaction.Rollback();
                throw;
            }
        }
    }
}

TransactionScope by default does not support across thread transaction flow. Using the the async/await syntactic sugar for TransactionScope causes InvalidOperationException: A TransactionScope must be disposed on the same thread that it was created.. To resolved this, Since .NET 4.5.1, a new constructor for TransactionScope is provided to explicitly enable transaction flow across thread continuations:

internal static async Task TransactionScopeAsync()
{
    await new ExecutionStrategy().ExecuteAsync(async () =>
    {
        using (TransactionScope scope = new TransactionScope(
            scopeOption: TransactionScopeOption.Required,
            transactionOptions: new TransactionOptions()
            {
                IsolationLevel = System.Transactions.IsolationLevel.RepeatableRead
            },
            asyncFlowOption: TransactionScopeAsyncFlowOption.Enabled))
        {
            using (DbConnection connection = new SqlConnection(ConnectionStrings.AdventureWorks))
            using (DbCommand command = connection.CreateCommand())
            {
                command.CommandText = DbContextExtensions.CurrentIsolationLevelSql;
                await connection.OpenAsync();
                using (DbDataReader reader = await command.ExecuteReaderAsync())
                {
                    await reader.ReadAsync();
                    reader[0].WriteLine(); // RepeatableRead
                }
            }

            using (AdventureWorks adventureWorks = new AdventureWorks())
            {
                ProductCategory category = new ProductCategory() { Name = nameof(ProductCategory) };
                adventureWorks.ProductCategories.Add(category);
                (await adventureWorks.SaveChangesAsync()).WriteLine(); // 1
            }

            using (AdventureWorks adventureWorks = new AdventureWorks())
            {
                adventureWorks.CurrentIsolationLevel().WriteLine(); // RepeatableRead
            }

            using (DbConnection connection = new SqlConnection(ConnectionStrings.AdventureWorks))
            using (DbCommand command = connection.CreateCommand())
            {
                command.CommandText = "DELETE FROM [Production].[ProductCategory] WHERE [Name] = @p0";
                DbParameter parameter = command.CreateParameter();
                parameter.ParameterName = "@p0";
                parameter.Value = nameof(ProductCategory);
                command.Parameters.Add(parameter);

                await connection.OpenAsync();
                (await command.ExecuteNonQueryAsync()).WriteLine(); // 1
            }

            scope.Complete();
        }
    });
}

Asynchronous concurrent conflicts

EF/Core also provide async APIs for other database operations. In the previous concurrency part, a DbContext.SaveChanges overload is implemented to handle concurrency conflict, refresh entity, and retry saving changes. Here a async version can be implemented easily:

public static partial class DbContextExtensions
{
    public static async Task<int> SaveChangesAsync(
        this DbContext context, Func<IEnumerable<EntityEntry>, Task> resolveConflictsAsync, int retryCount = 3)
    {
        if (retryCount <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(retryCount));
        }

        for (int retry = 1; retry < retryCount; retry++)
        {
            try
            {
                return await context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException exception) when (retry < retryCount)
            {
                await resolveConflictsAsync(exception.Entries);
            }
        }
        return await context.SaveChangesAsync();
    }

    public static async Task<int> SaveChangesAsync(
        this DbContext context, Func<IEnumerable<EntityEntry>, Task> resolveConflictsAsync, RetryStrategy retryStrategy)
    {
        RetryPolicy retryPolicy = new RetryPolicy(
            new TransientDetection<DbUpdateConcurrencyException>(), retryStrategy);
        retryPolicy.Retrying += (sender, e) =>
            resolveConflictsAsync(((DbUpdateConcurrencyException)e.LastException).Entries).Wait();
        return await retryPolicy.ExecuteAsync(async () => await context.SaveChangesAsync());
    }
}

With the async/await syntactic sugar, the implementation looks very similar to the synchronous version. The following are the SaveChangesAsync overloads to accept RefreshConflict enumeration:

public static async Task<int> SaveChangesAsync(
    this DbContext context, RefreshConflict refreshMode, int retryCount = 3)
{
    if (retryCount <= 0)
    {
        throw new ArgumentOutOfRangeException(nameof(retryCount));
    }

    return await context.SaveChangesAsync(
        async conflicts => await Task.WhenAll(conflicts.Select(async tracking =>
            await tracking.RefreshAsync(refreshMode))),
        retryCount);
}

public static async Task<int> SaveChangesAsync(
    this DbContext context, RefreshConflict refreshMode, RetryStrategy retryStrategy) =>
        await context.SaveChangesAsync(
            async conflicts => await Task.WhenAll(conflicts.Select(async tracking =>
                await tracking.RefreshAsync(refreshMode))),
            retryStrategy);

Instead of calling the previously defined Refresh extension method to refresh the DbEntityEntry instance, here a async method RefreshAsync is called to refresh asynchronously:

public static async Task<EntityEntry> RefreshAsync(this EntityEntry tracking, RefreshConflict refreshMode)
{
    switch (refreshMode)
    {
        case RefreshConflict.StoreWins:
        {
            await tracking.ReloadAsync();
            break;
        }
        case RefreshConflict.ClientWins:
        {
            PropertyValues databaseValues = await tracking.GetDatabaseValuesAsync();
            if (databaseValues == null)
            {
                tracking.State = EntityState.Detached;
            }
            else
            {
                tracking.OriginalValues.SetValues(databaseValues);
            }
            break;
        }
        case RefreshConflict.MergeClientAndStore:
        {
            PropertyValues databaseValues = await tracking.GetDatabaseValuesAsync();
            if (databaseValues == null)
            {
                tracking.State = EntityState.Detached;
            }
            else
            {
                PropertyValues originalValues = tracking.OriginalValues.Clone();
                tracking.OriginalValues.SetValues(databaseValues);
#if EF
                databaseValues.PropertyNames
                    .Where(property => !object.Equals(originalValues[property], databaseValues[property]))
                    .ForEach(property => tracking.Property(property).IsModified = false);
#else
                databaseValues.Properties
                    .Where(property => !object.Equals(originalValues[property.Name], databaseValues[property.Name]))
                    .ForEach(property => tracking.Property(property.Name).IsModified = false);
#endif
            }
            break;
        }
    }
    return tracking;
}

Now concurrency conflict can be resolved automatically and asynchronously:

internal static async Task SaveChangesAsync()
{
    using (AdventureWorks adventureWorks1 = new AdventureWorks())
    using (AdventureWorks adventureWorks2 = new AdventureWorks())
    {
        int id = 950;
        Product productCopy1 = await adventureWorks1.Products.FindAsync(id);
        Product productCopy2 = await adventureWorks2.Products.FindAsync(id);

        productCopy1.Name = nameof(productCopy1);
        productCopy1.ListPrice = 100;
        (await adventureWorks1.SaveChangesAsync()).WriteLine(); // 1

        productCopy2.Name = nameof(productCopy2);
        productCopy2.ProductSubcategoryID = 1;
        (await adventureWorks2.SaveChangesAsync(RefreshConflict.MergeClientAndStore)).WriteLine(); // 1
    }
}

15 Comments

  • To create dynamic menus in ASP.NET MVC, the very first step is to generate a database table that can hold all the menu items in a designed hierarchy (if any). The database table can be created with a simple query as mentioned below.

    Create Table Menus(ID int Primary Key Identity(1,1), ParentID int foreign key References Menus(ID), Title varchar(50), Description varchar(250))

  • The site contains a very great blog. the information present in this site will be very useful for us. thank you for sharing the blog with us.

  • There is a typo in Initialization section:
    EF dies a lot of initialization work before the first database query is executed.

    dies should be does

  • Great series. One question, how to enable/disable each cache, for example, is it possible to disable the query translation cache?

  • Please update this article regarding Skip & Take parameterization in EF Core. The proposed solution does not work in EF Core!

  • Nice post.. thank you for useful information

  • I have had so much fun learning with you.

  • I like the helpful info you provide in your articles. I’ll bookmark your weblog and check again here regularly. I am quite sure I will learn much new stuff right here! Good luck for the next!

  • I have had so much fun learning with you.

  • I really learnt alot, thanks for sharing

  • Thanks for the insightful explanation.

  • I am eternally grateful for everything you’ve taught me.

  • <a href="http://glimonlinetrainings.com/abinitio-online-training/">Ab Initio Online Training</a>
    <a href="http://glimonlinetrainings.com/advance-sas-online-training/">Advance SAS Online Training</a>
    <a href="http://glimonlinetrainings.com/ajax-online-training/">Ajax Online Training</a>
    <a href="http://glimonlinetrainings.com/alteryx-online-training/">Alteryx Online Training</a>
    <a href="http://glimonlinetrainings.com/android-online-training/">Android Online Training</a>
    <a href="http://glimonlinetrainings.com/angular-js-online-training/">AngularJS Online Training</a>
    <a href="http://glimonlinetrainings.com/ansible-online-training/">Ansible Online Training</a>
    <a href="http://glimonlinetrainings.com/ansys-online-training/">Ansys Online Training</a>
    <a href="http://glimonlinetrainings.com/appium-online-training/">Appium Online Training</a>
    <a href="http://glimonlinetrainings.com/artificial-intelligence-online-training/">Artificial Intelligence Online Training</a>
    <a href="http://glimonlinetrainings.com/autocad-online-training/">Autocad Online Training</a>
    <a href="http://glimonlinetrainings.com/aws-online-training/">AWS Online Training</a>
    <a href="http://glimonlinetrainings.com/big-data-online-training/">Big Data Online Training</a>
    <a href="http://glimonlinetrainings.com/blockchain-online-training/">BlockChain Online Training</a>
    <a href="http://glimonlinetrainings.com/building-estimation-and-costing-online-training/">Building Estimation and Costing Online Training</a>
    <a href="http://glimonlinetrainings.com/business-analyst-online-training/">Business Analyst Online Training</a>
    <a href="http://glimonlinetrainings.com/c-c-plus-plus-online-training/">C C++ Online Training</a>
    <a href="http://glimonlinetrainings.com/ccna-online-training/">CCNA Online Training</a>
    <a href="http://glimonlinetrainings.com/ccnp-online-training/">CCNP Online Training</a>
    <a href="http://glimonlinetrainings.com/cisco-ucce-online-training/">Cisco UCCE Online Training</a>
    <a href="http://glimonlinetrainings.com/citrix-online-training/">Citrix Online Training</a>
    <a href="http://glimonlinetrainings.com/clinical-sas-online-training/">Clinical SAS Online Training</a>
    <a href="http://glimonlinetrainings.com/cloud-computing-online-training/">Cloud Computing Online Training</a>
    <a href="http://glimonlinetrainings.com/ssrs-online-training/">SSRS Online Training</a>
    <a href="http://glimonlinetrainings.com/cognos-tm1-online-training/">Cognos TM1 Online Training</a>
    <a href="http://glimonlinetrainings.com/creo-online-training/">Creo Online Training</a>
    <a href="http://glimonlinetrainings.com/data-science-online-training/">Data Science Online Training</a>
    <a href="http://glimonlinetrainings.com/datastage-online-training/">DataStage Online Training</a>
    <a href="http://glimonlinetrainings.com/dell-boomi-online-training/">Dell Boomi Online Training</a>
    <a href="http://glimonlinetrainings.com/dell-emc-online-training/">Dell EMC Online Training</a>
    <a href="http://glimonlinetrainings.com/devops-online-training/">DevOps Online Training</a>
    <a href="http://glimonlinetrainings.com/digital-marketing-online-training/">Digital Marketing Online Training</a>
    <a href="http://glimonlinetrainings.com/dotnet-online-training/">DotNet Online Training</a>
    <a href="http://glimonlinetrainings.com/embedded-systems-online-training/">Embedded Systems Online Training</a>
    <a href="http://glimonlinetrainings.com/ethical-hacking-online-training/">Ethical Hacking Online Training</a>
    <a href="http://glimonlinetrainings.com/etl-testing-online-training/">ETL Testing Online Training</a>
    <a href="http://glimonlinetrainings.com/full-stack-developer-online-training/">Fullstack Developer Online Training</a>
    <a href="http://glimonlinetrainings.com/google-cloud-online-training/">Google Cloud Online Training</a>
    <a href="http://glimonlinetrainings.com/google-go-online-training/">Google Go Online Training</a>
    <a href="http://glimonlinetrainings.com/guidewire-online-training/">Guidewire Online Training</a>
    <a href="http://glimonlinetrainings.com/hadoop-online-training/">Hadoop Online Training</a>
    <a href="http://glimonlinetrainings.com/hp-uft-online-training/">HP UFT Online Training</a>
    <a href="http://glimonlinetrainings.com/html-online-training/">HTML Online Training</a>
    <a href="http://glimonlinetrainings.com/informatica-online-training/">Informatica Online Training</a>
    <a href="http://glimonlinetrainings.com/informatica-bdm-online-training/">Informatica BDM Online Training</a>
    <a href="http://glimonlinetrainings.com/informatica-idq-online-training/">Informatica Data Quality Online Training</a>
    <a href="http://glimonlinetrainings.com/informatica-iics-online-training/">Informatica IICS Online Training</a>
    <a href="http://glimonlinetrainings.com/informatica-mdm-online-training/">Informatica MDM Online Training</a>
    <a href="http://glimonlinetrainings.com/informix-online-training/">Informix Online Training</a>
    <a href="http://glimonlinetrainings.com/ios-online-training/">iOS Online Training</a>
    <a href="http://glimonlinetrainings.com/iot-online-training/">IoT Online Training</a>
    <a href="http://glimonlinetrainings.com/itil-online-training/">ITIL Online Training</a>
    <a href="http://glimonlinetrainings.com/java-online-training/">Java Online Training</a>
    <a href="http://glimonlinetrainings.com/jmeter-online-training/">JMeter Online Training</a>
    <a href="http://glimonlinetrainings.com/joomla-online-training/">Joomla Online Training</a>
    <a href="http://glimonlinetrainings.com/kronos-online-training/">Kronos Online Training</a>
    <a href="http://glimonlinetrainings.com/load-runner-online-training/">LoadRunner Online Training</a>
    <a href="http://glimonlinetrainings.com/machine-learning-online-training/">Machine Learning Online Training</a>
    <a href="http://glimonlinetrainings.com/mainframe-online-training/">Mainframe Online Training</a>
    <a href="http://glimonlinetrainings.com/mainframe-admin-online-training/">Mainframe Admin Online Training</a>
    <a href="http://glimonlinetrainings.com/matlab-online-training/">Matlab Online Training</a>
    <a href="http://glimonlinetrainings.com/mcsa-online-training/">MCSA Online Training</a>
    <a href="http://glimonlinetrainings.com/mcse-online-training/">MCSE Online Training</a>
    <a href="http://glimonlinetrainings.com/mean-stack-online-training/">MEAN Stack Online Training</a>
    <a href="http://glimonlinetrainings.com/microsoft-azure-online-training/">Microsoft Azure Online Training</a>
    <a href="http://glimonlinetrainings.com/microsoft-dynamics-crm-online-training/">Microsoft Dynamics CRM Online Training</a>
    <a href="http://glimonlinetrainings.com/microstrategy-online-training/">Microstrategy Online Training</a>
    <a href="http://glimonlinetrainings.com/mobile-application-testing-online-training/">Mobile Application Testing Online Training</a>
    <a href="http://glimonlinetrainings.com/msbi-online-training/">MSBI Online Training</a>
    <a href="http://glimonlinetrainings.com/mulesoft-online-training/">Mulesoft Online Training</a>
    <a href="http://glimonlinetrainings.com/nodejs-online-training/">NodeJS Online Training</a>
    <a href="http://glimonlinetrainings.com/openstack-online-training/">Open stack Online Training</a>
    <a href="http://glimonlinetrainings.com/oracle-online-training/">Oracle Online Training</a>
    <a href="http://glimonlinetrainings.com/odi-online-training/">Oracle Data Integrator Online Training</a>
    <a href="http://glimonlinetrainings.com/oracle-dba-online-training/">Oracle DBA Online Training</a>
    <a href="http://glimonlinetrainings.com/oracle-soa-online-training/">Oracle SOA Online Training</a>
    <a href="http://glimonlinetrainings.com/pega-online-training/">Pega Online Training</a>
    <a href="http://glimonlinetrainings.com/pentaho-online-training/">Pentaho Online Training</a>
    <a href="http://glimonlinetrainings.com/perl-online-training/">Perl Online Training</a>
    <a href="http://glimonlinetrainings.com/phonegap-online-training/">Phonegap Online Training</a>
    <a href="http://glimonlinetrainings.com/php-online-training/">PHP Online Training</a>
    <a href="http://glimonlinetrainings.com/plc-scada-online-training/">PLC SCADA Online Training</a>
    <a href="http://glimonlinetrainings.com/pmp-online-training/">PMP Online Training</a>
    <a href="http://glimonlinetrainings.com/power-bi-online-training/">Power BI Online Training</a>
    <a href="http://glimonlinetrainings.com/primavera-online-training/">Primavera Online Training</a>
    <a href="http://glimonlinetrainings.com/python-online-training/">Python Online Training</a>
    <a href="http://glimonlinetrainings.com/qliksense-online-training/">Qlik Sense Online Training</a>
    <a href="http://glimonlinetrainings.com/qlikview-online-training/">Qlikview Online Training</a>
    <a href="http://glimonlinetrainings.com/qc-online-training/">Quality Control Online Training</a>
    <a href="http://glimonlinetrainings.com/r-programming-online-training/">R Programming Online Training</a>
    <a href="http://glimonlinetrainings.com/react-native-online-training/">React Native Online Training</a>
    <a href="http://glimonlinetrainings.com/reactjs-online-training/">ReactJS Online Training</a>
    <a href="http://glimonlinetrainings.com/revit-architecture-online-training/">Revit Architecture Online Training</a>
    <a href="http://glimonlinetrainings.com/rpa-online-training/">RPA Online Training</a>
    <a href="http://glimonlinetrainings.com/automation-anywhere-online-training/">Automation Anywhere Online Training</a>
    <a href="http://glimonlinetrainings.com/blueprism-online-training/">Blue Prism Online Training</a>
    <a href="http://glimonlinetrainings.com/openspan-online-training/">Openspan Online Training</a>
    <a href="http://glimonlinetrainings.com/uipath-online-training/">UiPath Online Training</a>
    <a href="http://glimonlinetrainings.com/ruby-on-rails-online-training/">Ruby On Rails Online Training</a>
    <a href="http://glimonlinetrainings.com/salesforce-online-training/">Salesforce Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-abap-online-training/">SAP Abap Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-ariba-online-training/">SAP Ariba Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-basis-online-training/">SAP Basis Online Training</a>
    <a href="http://glimonlinetrainings.com/bi-bw-online-training/">SAP BI BW Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-bo-online-training/">SAP BO Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-bods-online-training/">SAP BODS Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-crm-online-training/">SAP CRM Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-erp-online-training/">SAP ERP Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-fico-online-training/">SAP FICO Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-fscm-online-training/">SAP FSCM Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-grc-online-training/">SAP GRC Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-hana-online-training/">SAP HANA Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-hcm-online-training/">SAP HCM Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-hr-online-training/">SAP HR Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-mm-online-training/">SAP MM Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-pp-online-training/">SAP PP Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-ps-online-training/">SAP PS Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-qm-online-training/">SAP QM Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-scm-online-training/">SAP SCM Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-sd-online-training/">SAP SD Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-success-factor-online-training/">SAP Successfactors Online Training</a>
    <a href="http://glimonlinetrainings.com/sap-webdynpro-online-training/">SAP Webdynpro Online Training</a>
    <a href="http://glimonlinetrainings.com/sas-online-training/">SAS Online Training</a>
    <a href="http://glimonlinetrainings.com/base-sas-online-training/">Base SAS Online Training</a>
    <a href="http://glimonlinetrainings.com/sccm-online-training/">SCCM Online Training</a>
    <a href="http://glimonlinetrainings.com/scrum-master-online-training/">Scrum Master Online Training</a>
    <a href="http://glimonlinetrainings.com/selenium-online-training/">Selenium Online Training</a>
    <a href="http://glimonlinetrainings.com/seo-online-training/">SEO Online Training</a>
    <a href="http://glimonlinetrainings.com/servicenow-online-training/">ServiceNow Online Training</a>
    <a href="http://glimonlinetrainings.com/sharepoint-online-training/">SharePoint Online Training</a>
    <a href="http://glimonlinetrainings.com/sharepoint-admin-online-training/">SharePoint Admin Online Training</a>
    <a href="http://glimonlinetrainings.com/snaplogic-online-training/">SnapLogic Online Training</a>
    <a href="http://glimonlinetrainings.com/snowflake-online-training/">Snowflake Online Training</a>
    <a href="http://glimonlinetrainings.com/soapui-testing-online-training/">SoapUI Testing Online Training</a>
    <a href="http://glimonlinetrainings.com/solidworks-online-training/">Solidworks Online Training</a>
    <a href="http://glimonlinetrainings.com/splunk-online-training/">Splunk Online Training</a>
    <a href="http://glimonlinetrainings.com/sql-server-dba-online-training/">SQL Server DBA Online Training</a>
    <a href="http://glimonlinetrainings.com/ssas-online-training/">SSAS Online Training</a>
    <a href="http://glimonlinetrainings.com/cognos-online-training/">Cognos Online Training</a>
    <a href="http://glimonlinetrainings.com/sybase-online-training/">Sybase Online Training</a>
    <a href="http://glimonlinetrainings.com/tableau-online-training/">Tableau Online Training</a>
    <a href="http://glimonlinetrainings.com/talend-online-training/">Talend Online Training</a>
    <a href="http://glimonlinetrainings.com/tally-online-training/">Tally Online Training</a>
    <a href="http://glimonlinetrainings.com/teradata-online-training/">Teradata Online Training</a>
    <a href="http://glimonlinetrainings.com/test-complete-online-training/">Test Complete Online Training</a>
    <a href="http://glimonlinetrainings.com/tibco-amx-bpm-online-training/">Tibco ActiveMatrix BPM Online Training</a>
    <a href="http://glimonlinetrainings.com/tibco-bw-online-training/">Tibco BW Online Training</a>
    <a href="http://glimonlinetrainings.com/jaspersoft-online-training/">Tibco Jaspersoft Online Training</a>
    <a href="http://glimonlinetrainings.com/tibco-spotfire-online-training/">Tibco Spotfire Online Training</a>
    <a href="http://glimonlinetrainings.com/unix-online-training/">Unix Online Training</a>
    <a href="http://glimonlinetrainings.com/vlsi-online-training/">VLSI Online Training</a>
    <a href="http://glimonlinetrainings.com/vmware-online-training/">VMWare Online Training</a>
    <a href="http://glimonlinetrainings.com/web-design-online-training/">Web Designing Online Training</a>
    <a href="http://glimonlinetrainings.com/weblogic-online-training/">Weblogic Online Training</a>
    <a href="http://glimonlinetrainings.com/windows-powershell-online-training/">Windows Powershell Online Training</a>
    <a href="http://glimonlinetrainings.com/workday-online-training/">Workday Online Training</a>
    <a href="http://glimonlinetrainings.com/xamarin-online-training/">Xamarin Online Training</a>


    <a href="http://glimonlinetrainings.com/abinitio-online-training/">Ab Initio Training</a>
    <a href="http://glimonlinetrainings.com/advance-sas-online-training/">Advance SAS Training</a>
    <a href="http://glimonlinetrainings.com/ajax-online-training/">Ajax Training</a>
    <a href="http://glimonlinetrainings.com/alteryx-online-training/">Alteryx Training</a>
    <a href="http://glimonlinetrainings.com/android-online-training/">Android Training</a>
    <a href="http://glimonlinetrainings.com/angular-js-online-training/">AngularJS Training</a>
    <a href="http://glimonlinetrainings.com/ansible-online-training/">Ansible Training</a>
    <a href="http://glimonlinetrainings.com/ansys-online-training/">Ansys Training</a>
    <a href="http://glimonlinetrainings.com/appium-online-training/">Appium Training</a>
    <a href="http://glimonlinetrainings.com/artificial-intelligence-online-training/">Artificial Intelligence Training</a>
    <a href="http://glimonlinetrainings.com/autocad-online-training/">Autocad Training</a>
    <a href="http://glimonlinetrainings.com/aws-online-training/">AWS Training</a>
    <a href="http://glimonlinetrainings.com/big-data-online-training/">Big Data Training</a>
    <a href="http://glimonlinetrainings.com/blockchain-online-training/">BlockChain Training</a>
    <a href="http://glimonlinetrainings.com/building-estimation-and-costing-online-training/">Building Estimation and Costing Training</a>
    <a href="http://glimonlinetrainings.com/business-analyst-online-training/">Business Analyst Training</a>
    <a href="http://glimonlinetrainings.com/c-c-plus-plus-online-training/">C C++ Training</a>
    <a href="http://glimonlinetrainings.com/ccna-online-training/">CCNA Training</a>
    <a href="http://glimonlinetrainings.com/ccnp-online-training/">CCNP Training</a>
    <a href="http://glimonlinetrainings.com/cisco-ucce-online-training/">Cisco UCCE Training</a>
    <a href="http://glimonlinetrainings.com/citrix-online-training/">Citrix Training</a>
    <a href="http://glimonlinetrainings.com/clinical-sas-online-training/">Clinical SAS Training</a>
    <a href="http://glimonlinetrainings.com/cloud-computing-online-training/">Cloud Computing Training</a>
    <a href="http://glimonlinetrainings.com/ssrs-online-training/">SSRS Training</a>
    <a href="http://glimonlinetrainings.com/cognos-tm1-online-training/">Cognos TM1 Training</a>
    <a href="http://glimonlinetrainings.com/creo-online-training/">Creo Training</a>
    <a href="http://glimonlinetrainings.com/data-science-online-training/">Data Science Training</a>
    <a href="http://glimonlinetrainings.com/datastage-online-training/">DataStage Training</a>
    <a href="http://glimonlinetrainings.com/dell-boomi-online-training/">Dell Boomi Training</a>
    <a href="http://glimonlinetrainings.com/dell-emc-online-training/">Dell EMC Training</a>
    <a href="http://glimonlinetrainings.com/devops-online-training/">DevOps Training</a>
    <a href="http://glimonlinetrainings.com/digital-marketing-online-training/">Digital Marketing Training</a>
    <a href="http://glimonlinetrainings.com/dotnet-online-training/">DotNet Training</a>
    <a href="http://glimonlinetrainings.com/embedded-systems-online-training/">Embedded Systems Training</a>
    <a href="http://glimonlinetrainings.com/ethical-hacking-online-training/">Ethical Hacking Training</a>
    <a href="http://glimonlinetrainings.com/etl-testing-online-training/">ETL Testing Training</a>
    <a href="http://glimonlinetrainings.com/full-stack-developer-online-training/">Fullstack Developer Training</a>
    <a href="http://glimonlinetrainings.com/google-cloud-online-training/">Google Cloud Training</a>
    <a href="http://glimonlinetrainings.com/google-go-online-training/">Google Go Training</a>
    <a href="http://glimonlinetrainings.com/guidewire-online-training/">Guidewire Training</a>
    <a href="http://glimonlinetrainings.com/hadoop-online-training/">Hadoop Training</a>
    <a href="http://glimonlinetrainings.com/hp-uft-online-training/">HP UFT Training</a>
    <a href="http://glimonlinetrainings.com/html-online-training/">HTML Training</a>
    <a href="http://glimonlinetrainings.com/informatica-online-training/">Informatica Training</a>
    <a href="http://glimonlinetrainings.com/informatica-bdm-online-training/">Informatica BDM Training</a>
    <a href="http://glimonlinetrainings.com/informatica-idq-online-training/">Informatica Data Quality Training</a>
    <a href="http://glimonlinetrainings.com/informatica-iics-online-training/">Informatica IICS Training</a>
    <a href="http://glimonlinetrainings.com/informatica-mdm-online-training/">Informatica MDM Training</a>
    <a href="http://glimonlinetrainings.com/informix-online-training/">Informix Training</a>
    <a href="http://glimonlinetrainings.com/ios-online-training/">iOS Training</a>
    <a href="http://glimonlinetrainings.com/iot-online-training/">IoT Training</a>
    <a href="http://glimonlinetrainings.com/itil-online-training/">ITIL Training</a>
    <a href="http://glimonlinetrainings.com/java-online-training/">Java Training</a>
    <a href="http://glimonlinetrainings.com/jmeter-online-training/">JMeter Training</a>
    <a href="http://glimonlinetrainings.com/joomla-online-training/">Joomla Training</a>
    <a href="http://glimonlinetrainings.com/kronos-online-training/">Kronos Training</a>
    <a href="http://glimonlinetrainings.com/load-runner-online-training/">LoadRunner Training</a>
    <a href="http://glimonlinetrainings.com/machine-learning-online-training/">Machine Learning Training</a>
    <a href="http://glimonlinetrainings.com/mainframe-online-training/">Mainframe Training</a>
    <a href="http://glimonlinetrainings.com/mainframe-admin-online-training/">Mainframe Admin Training</a>
    <a href="http://glimonlinetrainings.com/matlab-online-training/">Matlab Training</a>
    <a href="http://glimonlinetrainings.com/mcsa-online-training/">MCSA Training</a>
    <a href="http://glimonlinetrainings.com/mcse-online-training/">MCSE Training</a>
    <a href="http://glimonlinetrainings.com/mean-stack-online-training/">MEAN Stack Training</a>
    <a href="http://glimonlinetrainings.com/microsoft-azure-online-training/">Microsoft Azure Training</a>
    <a href="http://glimonlinetrainings.com/microsoft-dynamics-crm-online-training/">Microsoft Dynamics CRM Training</a>
    <a href="http://glimonlinetrainings.com/microstrategy-online-training/">Microstrategy Training</a>
    <a href="http://glimonlinetrainings.com/mobile-application-testing-online-training/">Mobile Application Testing Training</a>
    <a href="http://glimonlinetrainings.com/msbi-online-training/">MSBI Training</a>
    <a href="http://glimonlinetrainings.com/mulesoft-online-training/">Mulesoft Training</a>
    <a href="http://glimonlinetrainings.com/nodejs-online-training/">NodeJS Training</a>
    <a href="http://glimonlinetrainings.com/openstack-online-training/">Open stack Training</a>
    <a href="http://glimonlinetrainings.com/oracle-online-training/">Oracle Training</a>
    <a href="http://glimonlinetrainings.com/odi-online-training/">Oracle Data Integrator Training</a>
    <a href="http://glimonlinetrainings.com/oracle-dba-online-training/">Oracle DBA Training</a>
    <a href="http://glimonlinetrainings.com/oracle-soa-online-training/">Oracle SOA Training</a>
    <a href="http://glimonlinetrainings.com/pega-online-training/">Pega Training</a>
    <a href="http://glimonlinetrainings.com/pentaho-online-training/">Pentaho Training</a>
    <a href="http://glimonlinetrainings.com/perl-online-training/">Perl Training</a>
    <a href="http://glimonlinetrainings.com/phonegap-online-training/">Phonegap Training</a>
    <a href="http://glimonlinetrainings.com/php-online-training/">PHP Training</a>
    <a href="http://glimonlinetrainings.com/plc-scada-online-training/">PLC SCADA Training</a>
    <a href="http://glimonlinetrainings.com/pmp-online-training/">PMP Training</a>
    <a href="http://glimonlinetrainings.com/power-bi-online-training/">Power BI Training</a>
    <a href="http://glimonlinetrainings.com/primavera-online-training/">Primavera Training</a>
    <a href="http://glimonlinetrainings.com/python-online-training/">Python Training</a>
    <a href="http://glimonlinetrainings.com/qliksense-online-training/">Qlik Sense Training</a>
    <a href="http://glimonlinetrainings.com/qlikview-online-training/">Qlikview Training</a>
    <a href="http://glimonlinetrainings.com/qc-online-training/">Quality Control Training</a>
    <a href="http://glimonlinetrainings.com/r-programming-online-training/">R Programming Training</a>
    <a href="http://glimonlinetrainings.com/react-native-online-training/">React Native Training</a>
    <a href="http://glimonlinetrainings.com/reactjs-online-training/">ReactJS Training</a>
    <a href="http://glimonlinetrainings.com/revit-architecture-online-training/">Revit Architecture Training</a>
    <a href="http://glimonlinetrainings.com/rpa-online-training/">RPA Training</a>
    <a href="http://glimonlinetrainings.com/automation-anywhere-online-training/">Automation Anywhere Training</a>
    <a href="http://glimonlinetrainings.com/blueprism-online-training/">Blue Prism Training</a>
    <a href="http://glimonlinetrainings.com/openspan-online-training/">Openspan Training</a>
    <a href="http://glimonlinetrainings.com/uipath-online-training/">UiPath Training</a>
    <a href="http://glimonlinetrainings.com/ruby-on-rails-online-training/">Ruby On Rails Training</a>
    <a href="http://glimonlinetrainings.com/salesforce-online-training/">Salesforce Training</a>
    <a href="http://glimonlinetrainings.com/sap-abap-online-training/">SAP Abap Training</a>
    <a href="http://glimonlinetrainings.com/sap-ariba-online-training/">SAP Ariba Training</a>
    <a href="http://glimonlinetrainings.com/sap-basis-online-training/">SAP Basis Training</a>
    <a href="http://glimonlinetrainings.com/bi-bw-online-training/">SAP BI BW Training</a>
    <a href="http://glimonlinetrainings.com/sap-bo-online-training/">SAP BO Training</a>
    <a href="http://glimonlinetrainings.com/sap-bods-online-training/">SAP BODS Training</a>
    <a href="http://glimonlinetrainings.com/sap-crm-online-training/">SAP CRM Training</a>
    <a href="http://glimonlinetrainings.com/sap-erp-online-training/">SAP ERP Training</a>
    <a href="http://glimonlinetrainings.com/sap-fico-online-training/">SAP FICO Training</a>
    <a href="http://glimonlinetrainings.com/sap-fscm-online-training/">SAP FSCM Training</a>
    <a href="http://glimonlinetrainings.com/sap-grc-online-training/">SAP GRC Training</a>
    <a href="http://glimonlinetrainings.com/sap-hana-online-training/">SAP HANA Training</a>
    <a href="http://glimonlinetrainings.com/sap-hcm-online-training/">SAP HCM Training</a>
    <a href="http://glimonlinetrainings.com/sap-hr-online-training/">SAP HR Training</a>
    <a href="http://glimonlinetrainings.com/sap-mm-online-training/">SAP MM Training</a>
    <a href="http://glimonlinetrainings.com/sap-pp-online-training/">SAP PP Training</a>
    <a href="http://glimonlinetrainings.com/sap-ps-online-training/">SAP PS Training</a>
    <a href="http://glimonlinetrainings.com/sap-qm-online-training/">SAP QM Training</a>
    <a href="http://glimonlinetrainings.com/sap-scm-online-training/">SAP SCM Training</a>
    <a href="http://glimonlinetrainings.com/sap-sd-online-training/">SAP SD Training</a>
    <a href="http://glimonlinetrainings.com/sap-success-factor-online-training/">SAP Successfactors Training</a>
    <a href="http://glimonlinetrainings.com/sap-webdynpro-online-training/">SAP Webdynpro Training</a>
    <a href="http://glimonlinetrainings.com/sas-online-training/">SAS Training</a>
    <a href="http://glimonlinetrainings.com/base-sas-online-training/">Base SAS Training</a>
    <a href="http://glimonlinetrainings.com/sccm-online-training/">SCCM Training</a>
    <a href="http://glimonlinetrainings.com/scrum-master-online-training/">Scrum Master Training</a>
    <a href="http://glimonlinetrainings.com/selenium-online-training/">Selenium Training</a>
    <a href="http://glimonlinetrainings.com/seo-online-training/">SEO Training</a>
    <a href="http://glimonlinetrainings.com/servicenow-online-training/">ServiceNow Training</a>
    <a href="http://glimonlinetrainings.com/sharepoint-online-training/">SharePoint Training</a>
    <a href="http://glimonlinetrainings.com/sharepoint-admin-online-training/">SharePoint Admin Training</a>
    <a href="http://glimonlinetrainings.com/snaplogic-online-training/">SnapLogic Training</a>
    <a href="http://glimonlinetrainings.com/snowflake-online-training/">Snowflake Training</a>
    <a href="http://glimonlinetrainings.com/soapui-testing-online-training/">SoapUI Testing Training</a>
    <a href="http://glimonlinetrainings.com/solidworks-online-training/">Solidworks Training</a>
    <a href="http://glimonlinetrainings.com/splunk-online-training/">Splunk Training</a>
    <a href="http://glimonlinetrainings.com/sql-server-dba-online-training/">SQL Server DBA Training</a>
    <a href="http://glimonlinetrainings.com/ssas-online-training/">SSAS Training</a>
    <a href="http://glimonlinetrainings.com/cognos-online-training/">Cognos Training</a>
    <a href="http://glimonlinetrainings.com/sybase-online-training/">Sybase Training</a>
    <a href="http://glimonlinetrainings.com/tableau-online-training/">Tableau Training</a>
    <a href="http://glimonlinetrainings.com/talend-online-training/">Talend Training</a>
    <a href="http://glimonlinetrainings.com/tally-online-training/">Tally Training</a>
    <a href="http://glimonlinetrainings.com/teradata-online-training/">Teradata Training</a>
    <a href="http://glimonlinetrainings.com/test-complete-online-training/">Test Complete Training</a>
    <a href="http://glimonlinetrainings.com/tibco-amx-bpm-online-training/">Tibco ActiveMatrix BPM Training</a>
    <a href="http://glimonlinetrainings.com/tibco-bw-online-training/">Tibco BW Training</a>
    <a href="http://glimonlinetrainings.com/jaspersoft-online-training/">Tibco Jaspersoft Training</a>
    <a href="http://glimonlinetrainings.com/tibco-spotfire-online-training/">Tibco Spotfire Training</a>
    <a href="http://glimonlinetrainings.com/unix-online-training/">Unix Training</a>
    <a href="http://glimonlinetrainings.com/vlsi-online-training/">VLSI Training</a>
    <a href="http://glimonlinetrainings.com/vmware-online-training/">VMWare Training</a>
    <a href="http://glimonlinetrainings.com/web-design-online-training/">Web Designing Training</a>
    <a href="http://glimonlinetrainings.com/weblogic-online-training/">Weblogic Training</a>
    <a href="http://glimonlinetrainings.com/windows-powershell-online-training/">Windows Powershell Training</a>
    <a href="http://glimonlinetrainings.com/workday-online-training/">Workday Training</a>
    <a href="http://glimonlinetrainings.com/xamarin-online-training/">Xamarin Training</a>

  • Chennai Trainings
    Chennai Trainings is one of the best training institute in Chennai which provides various modes of trainings like classroom training, online training and live trainings. We provide both weekdays training and Weekend Trainings with flexible timing.
    <a href="https://chennaitraining.in/etl-testing-training-in-chennai/">ETL Testing Training In Chennai</a>
    <a href="https://chennaitraining.in/java-training-in-chennai/">Java Training In Chennai</a>
    <a href="https://chennaitraining.in/python-training-in-chennai/">Python Training In Chennai</a>
    <a href="https://chennaitraining.in/r-programming-training-in-chennai/">R Programming Training In Chennai</a>
    <a href="https://chennaitraining.in/salesforce-developer-training-in-chennai/">Salesforce Developer Training In Chennai</a>
    <a href="https://chennaitraining.in/sap-hana-training-in-chennai/">SAP HANA Training In Chennai</a>
    <a href="https://chennaitraining.in/sap-mm-training-in-chennai/">SAP MM Training In Chennai</a>
    <a href="https://chennaitraining.in/selenium-training-in-chennai/">Selenium Training In Chennai</a>
    <a href="https://chennaitraining.in/digital-marketing-training-in-chennai/">Digital Marketing Training In Chennai</a>
    <a href="https://chennaitraining.in/angular-js-training-in-chennai/">Angular js Training In Chennai</a>
    <a href="https://chennaitraining.in/aws-training-in-chennai/">AWS Training In Chennai</a>
    <a href="https://chennaitraining.in/big-data-training-in-chennai/">Big Data Training In Chennai</a>
    <a href="https://chennaitraining.in/ccna-training-in-chennai/">CCNA Training In Chennai</a>
    <a href="https://chennaitraining.in/dot-net-training-in-chennai/">Dot Net Training In Chennai</a>
    <a href="https://chennaitraining.in/hadoop-training-in-chennai/">Hadoop Training In Chennai</a>
    <a href="https://chennaitraining.in/informatica-training-in-chennai/">Informatica Training In Chennai</a>
    <a href="https://chennaitraining.in/pmp-training-in-chennai/">PMP Training In Chennai</a>
    <a href="https://chennaitraining.in/salesforce-admin-training-in-chennai/">Salesforce Admin Training In Chennai</a>
    <a href="https://chennaitraining.in/scrum-master-training-in-chennai/">Scrum Master Training In Chennai</a>
    <a href="https://chennaitraining.in/seo-training-in-chennai/">SEO Training In Chennai</a>
    <a href="https://chennaitraining.in/tally-training-in-chennai/">Tally Training In Chennai</a>
    <a href="https://chennaitraining.in/splunk-training-in-chennai/">Splunk Training In Chennai</a>
    <a href="https://chennaitraining.in/servicenow-training-in-chennai/">ServiceNow Training In Chennai</a>
    <a href="https://chennaitraining.in/tibco-bw-training-in-chennai/">Tibco BW Training In Chennai</a>
    <a href="https://chennaitraining.in/oracle-soa-training-in-chennai/">Oracle SOA Training In Chennai</a>
    <a href="https://chennaitraining.in/android-training-in-chennai/">Android Training In Chennai</a>
    <a href="https://chennaitraining.in/c-c-plus-plus-training-in-chennai/">C C++ Training In Chennai</a>
    <a href="https://chennaitraining.in/ios-training-in-chennai/">iOS Training In Chennai</a>
    <a href="https://chennaitraining.in/iot-training-in-chennai/">IoT Training In Chennai</a>
    <a href="https://chennaitraining.in/full-stack-developer-training-in-chennai/">Fullstack developer Training In Chennai</a>
    <a href="https://chennaitraining.in/devops-training-in-chennai/">Devops Training In Chennai</a>
    <a href="https://chennaitraining.in/datastage-training-in-chennai/">Datastage Training In Chennai</a>
    <a href="https://chennaitraining.in/abinitio-training-in-chennai/">Ab Initio Training In Chennai</a>
    <a href="https://chennaitraining.in/pentaho-training-in-chennai/">pentaho Training In Chennai</a>
    <a href="https://chennaitraining.in/msbi-training-in-chennai/">MSBI Training In Chennai</a>
    <a href="https://chennaitraining.in/informatica-mdm-training-in-chennai/">Informatica mdm Training In Chennai</a>
    <a href="https://chennaitraining.in/informatica-data-quality-training-in-chennai/">informatica Data Quality Training In Chennai</a>
    <a href="https://chennaitraining.in/informatica-iics-training-in-chennai/">Informatica IICS Training In Chennai</a>
    <a href="https://chennaitraining.in/talend-training-in-chennai/">Talend Training In Chennai</a>
    <a href="https://chennaitraining.in/power-bi-training-in-chennai/">Power BI Training In Chennai</a>
    <a href="https://chennaitraining.in/sap-bo-training-in-chennai/">SAP BO Training In Chennai</a>
    <a href="https://chennaitraining.in/qlikview-training-in-chennai/">Qlikview Training In Chennai</a>
    <a href="https://chennaitraining.in/tableau-training-in-chennai/">Tableau Training In Chennai</a>
    <a href="https://chennaitraining.in/ssas-training-in-chennai/">SSAS Training In Chennai</a>
    <a href="https://chennaitraining.in/cognos-training-in-chennai/">Cognos Training In Chennai</a>
    <a href="https://chennaitraining.in/ssrs-training-in-chennai/">SSRS Training In Chennai</a>
    <a href="https://chennaitraining.in/sas-training-in-chennai/">SAS Training In Chennai</a>
    <a href="https://chennaitraining.in/oracle-training-in-chennai/">Oracle Training In Chennai</a>
    <a href="https://chennaitraining.in/oracle-dba-training-in-chennai/">Oracle DBA Training In Chennai</a>
    <a href="https://chennaitraining.in/sql-server-dba-training-in-chennai/">SQL Server DBA Training In Chennai</a>
    <a href="https://chennaitraining.in/teradata-training-in-chennai/">Teradata Training In Chennai</a>
    <a href="https://chennaitraining.in/sap-hr-training-in-chennai/">SAP HR Training In Chennai</a>
    <a href="https://chennaitraining.in/sap-fico-training-in-chennai/">SAP FICO Training In Chennai</a>
    <a href="https://chennaitraining.in/sap-abap-training-in-chennai/">SAP Abap Training In Chennai</a>
    <a href="https://chennaitraining.in/bi-bw-training-in-chennai/">SAP BI BW Training In Chennai</a>
    <a href="https://chennaitraining.in/solidworks-training-in-chennai/">Solidworks Training In Chennai</a>
    <a href="https://chennaitraining.in/autocad-training-in-chennai/">Autocad Training In Chennai</a>
    <a href="https://chennaitraining.in/ansys-training-in-chennai/">Ansys Training In Chennai</a>
    <a href="https://chennaitraining.in/revit-architecture-training-in-chennai/">Revit Architecture Training In Chennai</a>
    <a href="https://chennaitraining.in/primavera-training-in-chennai/">Primavera Training In Chennai</a>
    <a href="https://chennaitraining.in/creo-training-in-chennai/">Creo Training In Chennai</a>
    <a href="https://chennaitraining.in/machine-learning-training-in-chennai/">Machine Learning Training In Chennai</a>
    <a href="https://chennaitraining.in/data-science-training-in-chennai/">Data Science Training In Chennai</a>
    <a href="https://chennaitraining.in/rpa-training-in-chennai/">RPA Training In Chennai</a>
    <a href="https://chennaitraining.in/blueprism-training-in-chennai/">Blue prism Training In Chennai</a>
    <a href="https://chennaitraining.in/openspan-training-in-chennai/">Openspan Training In Chennai</a>
    <a href="https://chennaitraining.in/uipath-training-in-chennai/">UI Path Training In Chennai</a>
    <a href="https://chennaitraining.in/automation-anywhere-training-in-chennai/">Automation Anywhere Training In Chennai</a>
    <a href="https://chennaitraining.in/microsoft-azure-training-in-chennai/">Microsoft azure Training In Chennai</a>
    <a href="https://chennaitraining.in/workday-training-in-chennai/">Workday Training In Chennai</a>
    <a href="https://chennaitraining.in/vmware-training-in-chennai/">VMWare Training In Chennai</a>
    <a href="https://chennaitraining.in/test-complete-training-in-chennai/">Test Complete Training In Chennai</a>
    <a href="https://chennaitraining.in/load-runner-training-in-chennai/">LoadRunner Training In Chennai</a>
    <a href="https://chennaitraining.in/jmeter-training-in-chennai/">JMeter Training In Chennai</a>
    <a href="https://chennaitraining.in/soapui-testing-training-in-chennai/">SoapUI Training In Chennai</a>
    <a href="https://chennaitraining.in/mobile-application-testing-training-in-chennai/">Mobile Application Testing Training In Chennai</a>
    <a href="https://chennaitraining.in/html-training-in-chennai/">HTML Training In Chennai</a>
    <a href="https://chennaitraining.in/php-training-in-chennai/">PHP Training In Chennai</a>
    <a href="https://chennaitraining.in/nodejs-training-in-chennai/">Nodejs Training In Chennai</a>
    <a href="https://chennaitraining.in/reactjs-training-in-chennai/">Reactjs Training In Chennai</a>
    <a href="https://chennaitraining.in/ccnp-training-in-chennai/">CCNP Training In Chennai</a>
    <a href="https://chennaitraining.in/mcsa-training-in-chennai/">MCSA Training In Chennai</a>
    <a href="https://chennaitraining.in/mcse-training-in-chennai/">MCSE Training In Chennai</a>
    <a href="https://chennaitraining.in/business-analyst-training-in-chennai/">Business Analyst Training in chennai</a>
    <a href="https://chennaitraining.in/embedded-systems-training-in-chennai/">embedded systems Training in chennai</a>
    <a href="https://chennaitraining.in/itil-training-in-chennai/">ITIL Training in chennai</a>
    <a href="https://chennaitraining.in/vlsi-training-in-chennai/">VLSI Training in chennai</a>
    <a href="https://chennaitraining.in/artificial-intelligence-training-in-chennai/">Artificial Intelligence Training in chennai</a>
    <a href="https://chennaitraining.in/google-cloud-training-in-chennai/">Google Cloud Training in chennai</a>
    <a href="https://chennaitraining.in/hp-uft-training-in-chennai/">HP UFT Training in chennai</a>
    <a href="https://chennaitraining.in/pega-training-in-chennai/">pega Training in chennai</a>
    <a href="https://chennaitraining.in/tibco-amx-bpm-training-in-chennai/">tibco active matrix BPM Training in chennai</a>
    <a href="https://chennaitraining.in/perl-training-in-chennai/">perl Training in chennai</a>
    <a href="https://chennaitraining.in/unix-training-in-chennai/">Unix Training in chennai</a>
    <a href="https://chennaitraining.in/sap-pp-training-in-chennai/">SAP PP Training in chennai</a>
    <a href="https://chennaitraining.in/sap-qm-training-in-chennai/">SAP QM Training in chennai</a>
    <a href="https://chennaitraining.in/sap-hcm-training-in-chennai/">SAP HCM Training in chennai</a>
    <a href="https://chennaitraining.in/sap-ps-training-in-chennai/">SAP PS Training in chennai</a>
    <a href="https://chennaitraining.in/sap-fscm-training-in-chennai/">SAP FSCM Training in chennai</a>
    <a href="https://chennaitraining.in/sap-basis-training-in-chennai/">sap basis Training in chennai</a>
    <a href="https://chennaitraining.in/sap-erp-training-in-chennai/">SAP ERP Training in chennai</a>
    <a href="https://chennaitraining.in/sap-crm-training-in-chennai/">SAP CRM Training in chennai</a>
    <a href="https://chennaitraining.in/sap-scm-training-in-chennai/">SAP SCM Training in chennai</a>
    <a href="https://chennaitraining.in/sap-grc-training-in-chennai/">SAP GRC Training in chennai</a>
    <a href="https://chennaitraining.in/sap-success-factor-training-in-chennai/">SAP successfactor Training in chennai</a>
    <a href="https://chennaitraining.in/web-design-training-in-chennai/">web designing Training in chennai</a>
    <a href="https://chennaitraining.in/sccm-training-in-chennai/">sccm Training in chennai</a>
    <a href="https://chennaitraining.in/ruby-on-rails-training-in-chennai/">ruby Training in chennai</a>
    <a href="https://chennaitraining.in/google-go-training-in-chennai/">google go Training in chennai</a>
    <a href="https://chennaitraining.in/jaspersoft-training-in-chennai/">Tibco jaspersoft Training in chennai</a>
    <a href="https://chennaitraining.in/odi-training-in-chennai/">Oracle Data Integrator Training in chennai</a>
    <a href="https://chennaitraining.in/phonegap-training-in-chennai/">PhoneGap Training in chennai</a>
    <a href="https://chennaitraining.in/xamarin-training-in-chennai/">Xamarin Training in chennai</a>
    <a href="https://chennaitraining.in/mean-stack-training-in-chennai/">Mean Stack Training in chennai</a>
    <a href="https://chennaitraining.in/openstack-training-in-chennai/">OpenStack Training in chennai</a>
    <a href="https://chennaitraining.in/microstrategy-training-in-chennai/">Microstrategy Training in chennai</a>
    <a href="https://chennaitraining.in/microsoft-dynamics-crm-training-in-chennai/">Microsoft Dynamics CRM Training in chennai</a>
    <a href="https://chennaitraining.in/mainframe-training-in-chennai/">Mainframe Training in chennai</a>
    <a href="https://chennaitraining.in/mainframe-admin-training-in-chennai/">Mainframe admin Training in chennai</a>
    <a href="https://chennaitraining.in/sharepoint-training-in-chennai/">Sharepoint Training in chennai</a>
    <a href="https://chennaitraining.in/sharepoint-admin-training-in-chennai/">Sharepoint admin Training in chennai</a>
    <a href="https://chennaitraining.in/windows-powershell-training-in-chennai/">Windows powershell Training in chennai</a>
    <a href="https://chennaitraining.in/mulesoft-training-in-chennai/">Mulesoft Training in chennai</a>
    <a href="https://chennaitraining.in/dell-boomi-training-in-chennai/">Dell Boomi Training in chennai</a>
    <a href="https://chennaitraining.in/react-native-training-in-chennai/">React Native Training in chennai</a>
    <a href="https://chennaitraining.in/cisco-ucce-training-in-chennai/">Cisco UCCE Training in chennai</a>
    <a href="https://chennaitraining.in/matlab-training-in-chennai/">Matlab Training in chennai</a>
    <a href="https://chennaitraining.in/plc-scada-training-in-chennai/">PLC SCADA Training in chennai</a>
    <a href="https://chennaitraining.in/appium-training-in-chennai/">Appium Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-ariba-training-in-chennai/">SAP Ariba Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-bods-training-in-chennai/">SAP BODS Training in Chennai</a>
    <a href="https://chennaitraining.in/cognos-tm1-training-in-chennai/">Cognos TM1 Training in Chennai</a>
    <a href="https://chennaitraining.in/tibco-spotfire-training-in-chennai/">Tibco Spotfire Training in Chennai</a>
    <a href="https://chennaitraining.in/qc-training-in-chennai/">QC Training in Chennai</a>
    <a href="https://chennaitraining.in/base-sas-training-in-chennai/">SAS Base Training in Chennai</a>
    <a href="https://chennaitraining.in/advance-sas-training-in-chennai/">Advance SAS Training in Chennai</a>
    <a href="https://chennaitraining.in/clinical-sas-training-in-chennai/">Clinical SAS Training in Chennai</a>
    <a href="https://chennaitraining.in/blockchain-training-in-chennai/">BlockChain Training in Chennai</a>
    <a href="https://chennaitraining.in/kronos-training-in-chennai/">Kronos Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-ec-training-in-chennai/">SAP EC Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-tr-training-in-chennai/">SAP TR Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-rem-training-in-chennai/">SAP REM Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-cs-training-in-chennai/">SAP CS Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-le-training-in-chennai/">SAP LE Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-ehs-training-in-chennai/">SAP EHS Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-srm-training-in-chennai/">SAP SRM Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-pm-training-in-chennai/">SAP PM Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-wf-training-in-chennai/">SAP WorkFlow Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-apo-training-in-chennai/">SAP APO Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-sm-training-in-chennai/">SAP SM Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-ep-training-in-chennai/">SAP EP Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-mii-training-in-chennai/">SAP MII Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-pi-training-in-chennai/">SAP PI Training in Chennai</a>
    <a href="https://chennaitraining.in/weblogic-training-in-chennai/">Weblogic Training in Chennai</a>
    <a href="https://chennaitraining.in/cloud-computing-training-in-chennai/">Cloud Computing Training in Chennai</a>
    <a href="https://chennaitraining.in/ajax-training-in-chennai/">Ajax Training in Chennai</a>
    <a href="https://chennaitraining.in/joomla-training-in-chennai/">Joomla Training in Chennai</a>
    <a href="https://chennaitraining.in/ansible-training-in-chennai/">Ansible Training in Chennai</a>
    <a href="https://chennaitraining.in/citrix-training-in-chennai/">Citrix Training in Chennai</a>
    <a href="https://chennaitraining.in/informix-training-in-chennai/">Informix Training in Chennai</a>
    <a href="https://chennaitraining.in/sybase-training-in-chennai/">Sybase Training in Chennai</a>
    <a href="https://chennaitraining.in/ethical-hacking-training-in-chennai/">Ethical Hacking Training in Chennai</a>
    <a href="https://chennaitraining.in/guidewire-training-in-chennai/">Guidewire Training in Chennai</a>
    <a href="https://chennaitraining.in/dell-emc-training-in-chennai/">Dell EMC Training in Chennai</a>
    <a href="https://chennaitraining.in/sap-lo-training-in-chennai/">SAP LO Training In Chennai</a>
    <a href="https://chennaitraining.in/sap-re-training-in-chennai/">SAP RE Training In Chennai</a>
    <a href="https://chennaitraining.in/sap-plm-training-in-chennai/">SAP PLM Training In Chennai</a>
    <a href="https://chennaitraining.in/sap-im-training-in-chennai/">SAP IM Training In Chennai</a>
    <a href="https://chennaitraining.in/microsoft-hybris-training-in-chennai/">Microsoft Hybris Training In Chennai</a>
    <a href="https://chennaitraining.in/spoken-english-course-in-chennai/">Spoken English Training In Chennai</a>
    <a href="https://chennaitraining.in/soft-skill-training-in-chennai/">Soft skill Training In Chennai</a>
    <a href="https://chennaitraining.in/ielts-training-in-chennai/">IELTS Training In Chennai</a>
    <a href="https://chennaitraining.in/toefl-training-in-chennai/">TOEFL Training In Chennai</a>

  • Intellecto Automation

    Intellecto Automation Service is the leading authority on smart homes technology, with countless home automation kits to suit our customers’ needs for the office or the residence.

    <a href="https://intellectoautomation.in/home-automation-company-in-chennai/">home automation in chennai</a>
    <a href="https://intellectoautomation.in/interior-designers-in-chennai/">interior designers in chennai</a>
    <a href="https://intellectoautomation.in/home-security-system-in-chennai/">home security systems in chennai </a>
    <a href="https://intellectoautomation.in/home-theatre-installation-in-chennai/">home theatres in chennai </a>
    <a href="https://intellectoautomation.in/lighting-automation-company-in-chennai/">lighting automation in chennai </a>
    <a href="https://intellectoautomation.in/modular-kitchen-in-chennai/">modular kitchen in Chennai</a>
    <a href="https://intellectoautomation.in/office-automation-company-in-chennai/">office automation in chennai </a>
    <a href="https://intellectoautomation.in/cctv-camera-installation-in-chennai/">cctv camera installation in chennai</a>

Add a Comment

As it will appear on the website

Not displayed

Your website