1.Identity Map模式簡介
Identity Map(標識映射)模式是通過將所有已加載對象放在一個映射中確保所有對象只被加載一次,並且在引用這些對象時使用該映射來查找對象。在處理數據並發訪問時,要有一種策略讓多個用戶共同影響同一個業務實體,這個固然很重要。同樣重要的是,單個用戶在一個長運行事務或復雜事務中始終使用業務實體的一致版本。Identity Map模式提供的功能;為事務中使用所有的業務對象均保存一個版本,如果一個實體被請求兩次,返回同一個實體。
每個業務事務使用一個Identity Map,可以確保如果在同一個事務中兩次檢索同一個實體,則該實體將是唯一的,而且包含該事務所做的任何修改。
2.Identity Map模式示例
代碼結構:

Employee.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DataAccessPatterns.IdentityMapPattern.Model { public class Employee { public Guid ID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } }
IEmployeeRepository.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DataAccessPatterns.IdentityMapPattern.Model { public interface IEmployeeRepository { Employee FindBy(Guid ID); } }
IdentityMap.cs: 該類使用泛型提供類型安全的Identity Map實現,用於在業務事務期間提供唯一的實體。Identity Map包含一個散列表來存儲事務中使用的業務實體,並提供簡單的接口來存儲和檢索實體。
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; namespace DataAccessPatterns.IdentityMapPattern.Repository { public class IdentityMap<T> { Hashtable entities = new Hashtable(); public T GetByID(Guid id) { if (entities.ContainsKey(id)) { return (T)entities[id]; } else { return default(T); } } public void Store(T entity, Guid key) { if (!entities.ContainsKey(key)) { entities.Add(key, entity); } } } }
EmployeeRepository.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using DataAccessPatterns.IdentityMapPattern.Model; namespace DataAccessPatterns.IdentityMapPattern.Repository { public class EmployeeRepository : IEmployeeRepository { private IdentityMap<Employee> _employeeMap; public EmployeeRepository(IdentityMap<Employee> employeeMap) { _employeeMap = employeeMap; } public Employee FindBy(Guid Id) { Employee employee = _employeeMap.GetByID(Id); if (employee == null) { employee = DatastoreFindBy(Id); if (employee != null) { _employeeMap.Store(employee, employee.ID); } } return employee; } private Employee DatastoreFindBy(Guid Id) { Employee employee = default(Employee); // Code to hydrate employee from datastore... return employee; } } }
調用FindBy方法時,Employee Repository首先檢查IdentityMap以確定之前是否已經檢索Employee實體。如果是,則將其返回給調用者。如果沒有,則使用Employee實例的標識從數據存儲中查詢該實例,然后將其添加到IdentityMap中,如果再次需要從Employee Repository中檢索同樣的Employee實體,就可以直接使用它。
