Identity Map(标识映射)模式:通过将所有已加载对象放在一个映射中确保所有对象只被加载一次,在引用这些对象时使用该映射来查找对象。
①、在处理数据并发访问时,要有一种策略让多个用户共同影响同一个业务实体。
②、单个用户在一个长运行事务或复杂事务中,始终使用业务实体的一致版本。
using System; namespace Chap7.IdentityMap.Model { public class Employee { public Guid Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } }
using System; namespace Chap7.IdentityMap.Model { /// <summary> /// 定义一个接口,用来通过ID,检索employee /// </summary> public interface IEmployeeRepository { Employee FindBy(Guid Id); } }
using System; using System.Collections; namespace Chap7.IdentityMap.Repository { /// <summary> /// 用一个散列表来存储事务中使用到的业务实体 /// </summary> /// <typeparam name="T"></typeparam> public class IdentityMap<T> { Hashtable entites = new Hashtable(); public T GetById(Guid Id) { if (entites.ContainsKey(Id)) return (T)entites[Id]; else return default(T); } public void Store(T entity, Guid key) { if (!entites.ContainsKey(key)) entites.Add(key, entity); } } }
using System; using Chap7.IdentityMap.Model; namespace Chap7.IdentityMap.Repository { /// <summary> /// 调用FindBy方法时,先检查IdentityMap,以确定之前是否已经检索Employee实体。如果是,则将其返回给调用者。如果没有则使用Employee实例的标识从数据库中查询该实例,然后将其添加到IdentityMap中去,如果再次 /// 需要从Employee Respository中检索同样的Employee实体,就可以使用它了。 /// </summary> public class EmployeeRepository : IEmployeeRepository { private IdentityMap<Employee> _employeeMap; public EmployeeRepository() { _employeeMap = new IdentityMap<Employee>(); } 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); return employee; } } }