Check out the Latest Articles:
My First Data Access Layer Amends Part 1

Ok so yesterday I posted about a Data Access Layer (DAL) I had been working on (Article Here). Today I came across this article. The Identity Map pattern it uses taken from Martin Fowlers blog is a great idea and I decided to implement this in my DAL.

I also moved away from using an abstract GetAll, Add, Update, Delete etc method and instead decided to use the template pattern to perform these operations. This then means that when I need to remove objects from the object cache of the Identity Map implementation I can do so in one place instead of having to do so in every repository I create.

The previously abstract Update method now looks like the below. With the object being updated removed from the cache if the ExecuteWrite method is successful.

1
2
3
4
5
6
7
8
9
10
protected abstract CommandType GetUpdateCommandType();
protected abstract string GetUpdateCommandText();
protected abstract ICollection<IDataParameter> GetUpdateParameters(T item);

public bool Update(T item)
{
     bool result = ExecuteWrite(GetUpdateCommandType(), GetUpdateCommandText(), GetUpdateParameters(item));
     if (result) Cache.Remove(item);
     return result;
}

The specifics to execute the ExecuteWrite method are now provided in the repositories by the implementation of the abstract methods you can see above.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected override CommandType GetUpdateCommandType()
{
     return CommandType.StoredProcedure;
}

protected override string GetUpdateCommandText()
{
     return "UpdatePerson";
}

protected override ICollection<IDataParameter> GetUpdateParameters(Person item)
{
     return _paramCollectionRepository.GetPersonIdFirstNameLastNameEmailParamCollection(item.PersonId,
                                                                                        item.FirstName,
                                                                                        item.LastName,
                                                                                        item.Email);
}

I have implemented my Object Cache in the mapping classes of my DAL like so.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public override Person Map(IDataRecord record)
{
     try
     {
          int id = (DBNull.Value == record[_columnProvider.PersonID]) ? 0 : (int) record[_columnProvider.PersonID];

          var cachedEntity = Cache.TryToFind(typeof(Person), id);
          if (cachedEntity != null) return (Person)cachedEntity;

          Person p = new Person();

          p.PersonId = id;
          p.FirstName = (DBNull.Value == record[_columnProvider.FirstName]) ? string.Empty : (string)record[_columnProvider.FirstName];
          p.LastName = (DBNull.Value == record[_columnProvider.LastName]) ? string.Empty : (string)record[_columnProvider.LastName];
          p.Email = (DBNull.Value == record[_columnProvider.Email]) ? string.Empty : (string)record[_columnProvider.Email];

          Cache.Store(typeof(Person), id, p);

          return p;
     }
     catch (Exception)
     {      
          throw;
     }
}

If the object can be located in the cache we no longer continue with mapping from the database and instead just return the object from the cache. If it is not in the cache we map the object and chuck it in there.

My object cache is just taken from the article above. However I include the code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public interface IObjectCache
{
     object TryToFind(Type type, object id);
     void Store(Type type, object id, object entity);
     void ClearAll();
     void RemoveAllInstancesOf(Type type);
     void Remove(object entity);
}

public class ObjectCache : IObjectCache
{
     private readonly Dictionary<Type, Dictionary<string, object>> cache = new Dictionary<Type, Dictionary<string, object>>();

     public object TryToFind(Type type, object id)
     {
          if (!cache.ContainsKey(type)) return null;

          string idAsString = id.ToString();
          if (!cache[type].ContainsKey(idAsString)) return null;

          return cache[type][idAsString];
     }

     public void Store(Type type, object id, object entity)
     {
          if (!cache.ContainsKey(type)) cache.Add(type, new Dictionary<string, object>());

          cache[type][id.ToString()] = entity;
     }

     public void ClearAll()
     {
          cache.Clear();
     }

     public void RemoveAllInstancesOf(Type type)
     {
          if (cache.ContainsKey(type))
          {
               cache.Remove(type);
          }
     }

     public void Remove(object entity)
     {
          var type = entity.GetType();

          if (!cache.ContainsKey(type)) return;

          string keyToRemove = null;

          foreach (var pair in cache[type])
          {
               if (pair.Value == entity)
               {
                    keyToRemove = pair.Key;
               }
          }

          if (keyToRemove != null)
          {
               cache[type].Remove(keyToRemove);
          }
     }
}

Updated Source Code Here.

This will probably change in the future as I will probably create more realistic Domain objects that inherit from an abstract BusinessObject class which contains the primary key and implements an interface. Which may allow me to structure things in a nicer way. However for the time being this is just me playing around with some ideas which I will hopefully build upon over time.



  1. It‘s quite in here! Why not leave a response?