Each LINQ to SQL datacontext we instantiate holds its own identity map (based on Martin Fowlers Identity Map Pattern). This is basically a dictionary with identity keys pointing to entities in memory previously retrieved from the database – within the scope of the datacontext, that is.
In the example below we retrieve two hotels from the database with the same identity and on the same datacontext. The database gets called only ones for our LINQ query. Hotel1 and Hotel2 are pointing to the same object in memory. They are registered in the same identity map.
using System; using System.Linq; using Remondo.Database; namespace LinqToSqlIdentityMap { internal class Program { private static void Main() { using (var dataContext = new HotelsDataContext {Log = Console.Out}) { Hotel hotel1 = dataContext.Hotels.First(h => h.ID == 5); Hotel hotel2 = dataContext.Hotels.First(h => h.ID == 5); Console.WriteLine("Hotel 1 - {0}", hotel1.GetHashCode()); Console.WriteLine("Hotel 2 - {0}", hotel2.GetHashCode()); Console.ReadKey(); } } } }
In the example below we retrieve two Hotels from our database with the same identity, but from a different datacontext. Now Hotel1 and Hotel2 are two different objects in memory and registered in two different identity maps. We see the database gets called twice for the same query.
using System; using System.Linq; using Remondo.Database; namespace LinqToSqlIdentityMap { internal class Program { private static void Main() { using (var dataContext1 = new HotelsDataContext {Log = Console.Out}) using (var dataContext2 = new HotelsDataContext {Log = Console.Out}) { Hotel hotel1 = dataContext1.Hotels.First(h => h.ID == 5); Hotel hotel2 = dataContext2.Hotels.First(h => h.ID == 5); Console.WriteLine("Hotel 1 - {0}", hotel1.GetHashCode()); Console.WriteLine("Hotel 2 - {0}", hotel2.GetHashCode()); Console.ReadKey(); } } } }
In the next example we change the name of Hotel 1 on the first datacontext. We call SubmitChanges, so the database has stored the new name for this hotel. However the in-memory hotel object for datacontext 2 still has the old name. We need to call the Refresh method of the second datacontext for its hotel object to retrieve the new name from the database.
using System; using System.Data.Linq; using System.Linq; using Remondo.Database; namespace LinqToSqlIdentityMap { internal class Program { private static void Main() { using (var dataContext1 = new HotelsDataContext()) using (var dataContext2 = new HotelsDataContext()) { Hotel hotel1 = dataContext1.Hotels.First(h => h.ID == 5); Hotel hotel2 = dataContext2.Hotels.First(h => h.ID == 5); PrintHotelNames(hotel2, hotel1); // Start Logging to the console window from here dataContext1.Log = Console.Out; dataContext2.Log = Console.Out; PrintActionTitle("*** Updating Hotel 1 on datacontext 1"); hotel1.Name = "Hotel de L'Europe"; dataContext1.SubmitChanges(); PrintHotelNames(hotel2, hotel1); PrintActionTitle("*** Refreshing Hotel 2 on datacontext 2"); dataContext2.Refresh(RefreshMode.OverwriteCurrentValues, hotel2); PrintHotelNames(hotel2, hotel1); Console.ReadKey(); } } private static void PrintActionTitle(string actionTitle) { Console.WriteLine(); Console.WriteLine(actionTitle); Console.WriteLine(); } private static void PrintHotelNames(Hotel hotel2, Hotel hotel1) { Console.WriteLine("Hotel 1 - {0}", hotel1.Name); Console.WriteLine("Hotel 2 - {0}", hotel2.Name); } } }



