??????????????С??????????μ??????????????????????????????????

????????????????д?????????????????С??λ?????????????????????У??????????????????磬????????????????????File???????????????DummyFile?????????????????????????????????????????????????????????class???????????/???????л???????????????????á???????????????IFile??IDatabase????????????File??Database??
??????????????????????????????????????????????????????鰴????????????????????????????????????м??????????磺???????CunsomerData??????????LINQ to SQL???????????????????У?????????????????????????????
??????????????????TDD?????????????????????????????д????????????д??????????磬??д????????????CustomerData??????????????????CustomerData????CustomerData???????????????InsertCustomer ??DeleteCustomer ?? GetCustomer????????????????????Щ????Customer???????????????? ?????????????????????????????????д??CustomerData????????????????????????????????д????????????????????и????????TDD?????????????????????????????С????е??????????????????磬CustomerData????????SqlConnection?????????ISqlConnection ?????е?????????CustomerData????
??????????????????????
?????????????????????????????鷳????????д????????????????????????????????????????????????????У???????????????????????????????????????????????????? ???磺?????????Stack ?????????????????Pop??????????????????е????????????????????????????????κζ??????Pop????????????????????????Pop?????????????????????????????????????Pop ??
???????BDD???????
???????????????У?????????е?????????????????LINQ??SQL???????????????????????????檔???磬??????????????????????????????棬????????????????棬?????У???????????м???????????????????????????PageRepository ?????????漰Page?????????????????????????o??????CRUD????????????????????GetPageById ????????PageId???????Page????????С?
????public class PageRepository : IPageRepository
????{
????#region Fields
????private readonly IDropthingsDataContext _database;
????private readonly ICache _cacheResolver;
????#endregion Fields
????#region Constructors
????public PageRepository(IDropthingsDataContext database?? ICache cacheResolver)
????{
????this._database = database;
????this._cacheResolver = cacheResolver;
????}
????#endregion Constructors
????#region Methods
????public Page GetPageById(int pageId)
????{
????string cacheKey = CacheSetup.CacheKeys.PageId(pageId);
????object cachedPage = _cacheResolver.Get(cacheKey);
????if (null == cachedPage)
????{
????var page = _database.GetSingle<Page?? int>(
????DropthingsDataContext.SubsystemEnum.Page??
????pageId??
????LinqQueries.CompiledQuery_GetPageById);
????page.Detach();
????_cacheResolver.Add(cacheKey?? page);
????return page;
????}
????else
????{
????return cachedPage as Page;
????}
????}
????}
????PageRepository???IDropthingsDataContext ???????????LINQ to SQL???????λDataContext ?????????£?LINQ??SQL????????DataContext??????????????ò??????????DataContext?????????????????????ICache?????????漰???????????????У???????????????EnterpriseLibraryCache???????ICache ??
?????????????????????????PageRepository??????????棬?? GetPageById??????PageId ?????????黺?棬?????????У???????????е?????м???????????????檔
????public void GetPage_Should_Return_A_Page_from_database_when_cache_is_empty_and_then_caches_it()
????{
????var cache = new Mock();
????var database = new Mock();
????IPageRepository pageRepository = new PageRepository(database.Object?? cache.Object);
????const int pageId = 1;
????var page = default(Page);
????var samplePage = new Page() { ID = pageId?? Title = "Test Page"?? ...};
????database
????.Expect(d => d.GetSingle<Page?? int>(
????DropthingsDataContext.SubsystemEnum.Page??
????1?? LinqQueries.CompiledQuery_GetPageById))
????.Returns(samplePage);
????"Given PageRepository and empty cache".Context(() =>
????{
????// cache is empty
????cache.Expect(c => c.Get(It.IsAny())).Returns(default(object));
????// It will cache the Page object afte loading from database
????cache.Expect(c =>
????c.Add(It.Is(cacheKey =>
????cacheKey == CacheSetup.CacheKeys.PageId(pageId))??
????It.Is(cachePage =>
????object.ReferenceEquals(cachePage?? samplePage))))
????.AtMostOnce().Verifiable();
????});
????"when GetPageById is called".Do(() =>
????page = pageRepository.GetPageById(1));
????"it checks in the cache first and finds nothing and then caches it".Assert(() =>
????cache.VerifyAll());
????"it loads the page from database".Assert(() =>
????database.VerifyAll());
????"it returns the page as expected".Assert(() =>
????{
????Assert.Equal(pageId?? page.ID);
????}); 
????}
????????????????????
?????????д?????????????????????????????ò????????????????????е?????????????????????????á?????????????У???????cache??database????????о?????????????????????????????磬??????????????AspectF?????????????PageRepository ??????????????????PageRepository??????????????????????????????????棬????????仺?????????黺?棬?????????????????????????????У???????????м?????????????????GetPageById??????AspectF ???????????
????public Page GetPageById(int pageId)
????{
????return AspectF.Define
????.Cache(_cacheResolver?? CacheSetup.CacheKeys.PageId(pageId))
????.Return(() =>
????_database.GetSingle<Page?? int>(DropthingsDataContext.SubsystemEnum.Page??
????pageId?? LinqQueries.CompiledQuery_GetPageById).Detach());
????}