Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Part 15 - Identity Cache in Linq to SQL

Suggested Videos
Part 12 - Single table inheritance - saving to database
Part 13 - Compiled queries in Linq to SQL
Part 14 - How to directly execute sql queries using Linq to SQL



In this video we will discuss what is Identity cache and it's impact on Linq to SQL queries.



What is Identity Cache
DataContext object uses Identity Cache to manage objects. Let us understand this with an example. We will be using the following students table in this demo.
identity map pattern c#

References:
http://msdn.microsoft.com/en-us/library/vstudio/dd627203(v=vs.100).aspx

In this example, we are retrieving two students from the database with the same identity and using the the same datacontext object. With the first LINQ query is executed, it gets translated to T-SQL. The SQL query is executed and the result is brought back into the application, where a Student object is created. The object identity is stored in the Identity cache. When the second LINQ query is issued for the same student object, LINQ checks the identity cache and returns a reference to the student object that already exists. Notice that there is only one call to the database, inspite of  having 2 linq queries. S1 and S2 are pointing to the same student object in memory. 
using (SampleDataContext dbContext = new SampleDataContext())
{
    dbContext.Log = Console.Out;

    Student S1 = dbContext.Students.FirstOrDefault(x => x.ID == 1);
    Student S2 = dbContext.Students.FirstOrDefault(x => x.ID == 1);

    Console.WriteLine("S1 == S2 : {0}", object.ReferenceEquals(S1, S2));
}

Output:
identity map pattern

Each instance of LINQ to SQL DataContext class has its own identity cache. This means if we have 2 different DataContext instances, and when we issue 2 linq queries 2 retrieve a student with the same identity, we get 2 different student objects back. S1 and S2 are two different objects in memory and registered in two different identity maps. Notice that the database also gets called 2 times. 

using (SampleDataContext dbContext1 = new SampleDataContext())
using (SampleDataContext dbContext2 = new SampleDataContext())
{
    dbContext1.Log = Console.Out;
    dbContext2.Log = Console.Out;

    Student S1 = dbContext1.Students.FirstOrDefault(x => x.ID == 1);
    Student S2 = dbContext2.Students.FirstOrDefault(x => x.ID == 1);

    Console.WriteLine("S1 == S2 : {0}", object.ReferenceEquals(S1, S2));
}

Output :
linq to sql identity map pattern

In this example we changed the FirstName of the student using the first datacontext object. We then called SubmitChanges() method, so the database has stored the new name for this student. However the student object for datacontext 2 still has the old name, because when we reissue the linq query for the same student object, this object is retrieved from the identity cache and not from the database. To have data retrieved from the database and to refresh the cache with updated values, we need to call the Refresh method of the second datacontext object. 

using (SampleDataContext dbContext1 = new SampleDataContext())
using (SampleDataContext dbContext2 = new SampleDataContext())
{
    dbContext1.Log = Console.Out;
    dbContext2.Log = Console.Out;

    Student S1 = dbContext1.Students.FirstOrDefault(x => x.ID == 1);
    Student S2 = dbContext2.Students.FirstOrDefault(x => x.ID == 1);

    Console.WriteLine("S1.FirstName = {0}", S1.FirstName);
    Console.WriteLine("S2.FirstName = {0}", S2.FirstName);

    S1.FirstName = "Updated.....";
    dbContext1.SubmitChanges();
    Console.WriteLine("FirstName updated.....");

    S2 = dbContext2.Students.FirstOrDefault(x => x.ID == 1);

    Console.WriteLine("S1.FirstName = {0}", S1.FirstName);
    Console.WriteLine("S2.FirstName = {0}", S2.FirstName);

    dbContext2.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, S2);
    Console.WriteLine("After calling the refresh method");

    Console.WriteLine("S1.FirstName = {0}", S1.FirstName);
    Console.WriteLine("S2.FirstName = {0}", S2.FirstName);
}

Output :
Identity Cache in Linq to SQL

LINQ to SQL Tutorial

1 comment:

  1. Hi,

    Thanks for all your great tutorials. They are really simple and concise. I'm having an issue with this identity cache,

    I tried running the first part of this tutorial..

    Student S1 = dbContext.Students.FirstOrDefault(x => x.ID == 1);
    Student S2 = dbContext.Students.FirstOrDefault(x => x.ID == 1);
    Console.WriteLine("S1 == S2 : {0}", object.ReferenceEquals(S1, S2));

    For me the select statement gets triggered twice, and Console.writeline returns false. Is there anything which needs to be done to turn on or off identity cache?

    Thanks..

    ReplyDelete

It would be great if you can help share these free resources