2020年4月18日 星期六

[MVC/Pattern] Unit of Work與Repository模式紀錄

前言:
上一次用到Unif Of Work,已經快3年了,有機會就來記錄一下吧。

先上個圖:


Repository部分讓商業邏輯跟資料存取可以拆開,也是一種pattern,
IRepository定義了常用的CRUD操作,使用泛型處理不同的資料實體,
建立Repository instance時,注入搭配的UnitOfWork instance。

而Unit Of Work負責處理資料交易的部分,確保資料與db是一致的。
當然,多了這些抽象,寫測試也就水到渠成了。

實際程式碼如下:
public interface IUnitOfWork : IDisposable
{ 

	DbContext DbContext { get; set; }
    
	void Commit();

}

public class UnitOfWork : IUnitOfWork
{

        public DbContext DbContext { get; set; }

        public UnitOfWork()
        {
            DbContext = new ApplicationDbContext();
        }

        public void Commit()
        {
            DbContext.SaveChanges();
        }

        public void Dispose()
        {
            DbContext.Dispose();
        }
        
}

public interface IRepository<T> where T : class
{

        IUnitOfWork UnitOfWork { get; set; }

        void Create(T entity);

        IQueryable<T> ReadAll();

        IQueryable<T> Read(Expression<Func<T, bool>> filter);

        void Delete(T entity);

        void Save();

}

public class Repository<T> : IRepository<T> where T : class
{

	private DbSet _entity;
    
	public Repository(IUnitOfWork unitOfWork)
	{
	    UnitOfWork = unitOfWork;
	}

	public IUnitOfWork UnitOfWork { get; set; }

	public void Create(T entity)
        {
            Entity.Add(entity);
        }

        public IQueryable ReadAll()
        {
            return Entity;
        }

        public IQueryable Read(Expression> filter)
        {
            return Entity.Where(filter);
        }

        public void Delete(T entity);
        {
            Entity.Remove(entity);
        }

        public void Save()
        {
            UnitOfWork.Commit();
        }

}


參考資料:
https://docs.microsoft.com/zh-tw/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
https://web.csulb.edu/~pnguyen/cecs475/pdf/repository%20pattern.pdf

2020年2月29日 星期六

[.Net/C#] C#中List與Array的關係(relationship between List and Array)

前言:
有一次聽到同事A跟同事B說,這裡不要用List,
用Array效能比較好,因為是直接存取記憶體。

當下覺得有點怪怪的,因為就我所知,
該程式是宣告固定長度的List,那跟宣告為Array不是一樣嗎?


從list.cs的Source code可以看到:
宣告固定長度的List,內部的確是用Array宣告。

正確的說,使用List其實就是在操作Array,
所以資料都是在記憶體上。

照這樣看來,宣告固定長度的List跟宣告Array,
在搜尋效能上,應該是一樣的?
簡單來測試一下:

結果跟我想的不一樣...


使用Array「大量」存取時,執行時間少了一半,
推測是因為List在存取Count跟使用indexer取得元素時,有做了一些檢查,
即使時間複雜度一樣,但step count多了一些,
這樣看來,如果是固定長度還是直接用Array,
會變動元素,當然就是List的強項了。


參考資料:

2020年1月31日 星期五

[Web] 初探Http Cache策略(cache-control)

前言:
瀏覽器會將從server下載回來的靜態檔案做快取,
好處是節省頻寬與資源,加快瀏覽速度。
壞處是需要針對存取資源做適當的快取配置,
讓client在瀏覽網頁的速度與資源的更新取得平衡。


作法:
除了更新資源檔案的檔名外,
一般都是從HTTP/1.1 header中的cache-control指令下手,
設定max-age(單位為秒數),讓browser定期跟server擷取資源,
不過各browser作法略有不同。
FireFox從第2次開始,會自行帶max-age=0給server,

Chrome不會自行帶max-age的指令,還是需server設定,
且需再增加no-cache指令,讓browser發request來重新驗證資源是否更新,
否則Chrome仍然使用local cache。


max-age雖然可讓browser定期擷取資源,但若資源內容沒有變動,
也沒有下載的必要,因此會搭配ETag指令:
server會依快取的檔案內容產出一字串,回應給browser,
之後browser送出request會夾帶If-None-Match指令,如果字串比對一致,
則回傳status code 304(表Not Modified),如下圖:

反之,若字串沒有match了,代表資源內容變更了,此時browser再重新擷取該資源即可。


建議font可善用CDN cache,分散又可降低server loading。


參考資料:
https://tools.ietf.org/html/rfc2616
https://tools.ietf.org/html/rfc7234
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching
https://developer.mozilla.org/zh-TW/docs/Web/HTTP/Caching
https://medium.com/@codebyamir/a-web-developers-guide-to-browser-caching-cc41f3b73e7c