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實體,就可以直接使用它。