EntityFramework走马观花之CRUD(上)
對于任何一個ORM框架,CRUD都是其核心功能,可以這么說,CRUD功能實(shí)現(xiàn)得好壞,直接決定了此ORM框架的命運(yùn)。
CRUD是英文Create、Read、Update、Delete四個單詞的縮寫,對應(yīng)于漢語,就是“增、刪、改、查”四個字。再細(xì)分一下,“增、刪、改”可歸為一類,其特點(diǎn)是要更新數(shù)據(jù)源,而“查”則歸為另一類,它不修改原始的數(shù)據(jù)源。
我們的技術(shù)探索之旅,從“查”開始。
1 兩種查詢數(shù)據(jù)的方式
EF主要使用兩種方式查詢數(shù)據(jù):LINQto Entities和一組針對IQueryable<T>的擴(kuò)展方法。
采用LINQ方式的查詢代碼擁有很強(qiáng)的可讀性:
?
[csharp]?view plaincopyprint?無需加注釋,只看代碼就能很輕松地知道其功能提取保存在數(shù)據(jù)庫中的所有書的書評數(shù)量信息。
上述功能也可以使用擴(kuò)展方法實(shí)現(xiàn),這時需要編寫Lambda表達(dá)式:
這兩種方式?jīng)]有好壞之分,只不過使用第二種方式可能會讓別人覺得你“比較牛B”。? :-)
2 裝入相關(guān)聯(lián)的數(shù)據(jù)
大多數(shù)數(shù)據(jù)實(shí)體間都有著各種各樣的關(guān)聯(lián),最常見的是比如一本書關(guān)聯(lián)多個書評,這是一對多的關(guān)聯(lián)。而書與書的作者之間的關(guān)系,就是多對多關(guān)聯(lián):一個作者可以寫多本書,一本書作者也可以不止一個。
EF在數(shù)據(jù)實(shí)體間建立導(dǎo)航屬性實(shí)現(xiàn)關(guān)聯(lián)。在實(shí)際項(xiàng)目中,經(jīng)常是得到一個(或一堆)實(shí)體對象之后,需要查詢相關(guān)聯(lián)的“另一堆”對象所封裝的信息,這就是“關(guān)聯(lián)數(shù)據(jù)的裝入”問題。
對于這個問題,EF支持三種裝入策略。
(1)當(dāng)導(dǎo)航屬性是virtual時,EF默認(rèn)使用“延遲裝入(lazy loading)”。比如書與書評的關(guān)聯(lián)定義如下:
則僅當(dāng)程序中需要訪問某Book對象的Reviews屬性時,EF才向數(shù)據(jù)庫發(fā)出SQL命令裝入相關(guān)的書評數(shù)據(jù)。
(2)如果確認(rèn)與某實(shí)體對象相關(guān)聯(lián)的數(shù)據(jù)是確實(shí)需要的,可以使用Include()方法通知EF這個情況,EF將告訴數(shù)據(jù)庫:“把XXX和XXX打包,一次性地發(fā)給我”:
?
[csharp]?view plaincopyprint?這種方式稱為“預(yù)先裝入(Eager Loading)”。避免了第2次訪問數(shù)據(jù)庫的需要。
(3)第三種方式稱為“顯式裝入(Explicit Loading)”,使用Load()方法實(shí)現(xiàn),例如,以下代碼讓EF裝入50條書和書評信息到內(nèi)存中:
[csharp]?view plaincopyprint?這些數(shù)據(jù)“就位”后,可以緩存起來備用。
我們也可以“有目的”地只提取需要的數(shù)據(jù),請看以下代碼:
?
[csharp]?view plaincopyprint?上述代碼將只提取第一本書的所有書評。
下面對這三種模式進(jìn)行一個小結(jié):
(1)就查詢性能而言,是“預(yù)先裝入(Eager Loading)”最好,因?yàn)閿?shù)據(jù)己全部裝入內(nèi)存,后繼的查詢無需再訪問數(shù)據(jù)庫。其缺點(diǎn)是可能會占用大量的內(nèi)存。
(2)如果能預(yù)知要訪問的數(shù)據(jù)項(xiàng),并且當(dāng)前在內(nèi)存的數(shù)據(jù)對象中,只有少數(shù)對象需要查詢獲取更進(jìn)一步的數(shù)據(jù),那么使用“顯式裝入(Explicit Loading)”策略能有效地減少數(shù)據(jù)傳輸量,獲得較高的性能。
(3)當(dāng)一個實(shí)體類擁有多個一對多的關(guān)聯(lián),而且難以預(yù)知要訪問的數(shù)據(jù)項(xiàng),則“延遲裝入(Lazy Loading)”又比較合適了,它僅在“需要用到時”才提取數(shù)據(jù),能有效地減少內(nèi)存占用,但可能給數(shù)據(jù)庫服務(wù)器帶來過多的數(shù)據(jù)查詢請求。
(4)當(dāng)數(shù)據(jù)實(shí)體對象需要序列化時,一定要使用“預(yù)先裝入(Eager Loading)”,其原因是序列化對象時需要使用反射查詢數(shù)據(jù)實(shí)體對象的所有屬性,如果是延遲裝入(Lazy Loading)”,將會導(dǎo)致向數(shù)據(jù)庫發(fā)出大量的查詢請求,而且每個對象都要發(fā)出“一堆”這樣的查詢請求,絕對會讓數(shù)據(jù)庫痛苦!
3 Find方法與本地?cái)?shù)據(jù)
DbSet有一個Local屬性很有趣,它引用當(dāng)前己裝入內(nèi)存的數(shù)據(jù),注意它包括當(dāng)前己從數(shù)據(jù)庫中取出或新加的但還沒有保存到數(shù)據(jù)庫中的數(shù)據(jù),我們可把它稱為DbSet對象的“本地?cái)?shù)據(jù)集合”。
本地?cái)?shù)據(jù)集合的一個重要特性是:針對它發(fā)出的各種查詢不會發(fā)往數(shù)據(jù)庫。
請看以下場景:
假設(shè)我只想提取數(shù)據(jù)庫中第1本和第11本書的書評信息,以下代碼完成這一工作:
?
[csharp]?view plaincopyprint?打開SQL Server Profiler,你會發(fā)現(xiàn)EF先后為上述代碼生成了4條SQL命令發(fā)給數(shù)據(jù)庫。
現(xiàn)在修改一下代碼,使用?“顯式裝入”+ Local查詢?方式:
?
[csharp]?view plaincopyprint?查看一下SQL ServerProfiler,你會發(fā)現(xiàn)EF只為上述代碼生成一條SQL命令(雖然這條命令比較復(fù)雜,但畢竟只有一條)發(fā)給數(shù)據(jù)庫,后繼的查詢都是在內(nèi)存中進(jìn)行的,相當(dāng)?shù)乜?#xff01;
“本地?cái)?shù)據(jù)集合”還有另一個值得關(guān)注的特性。
請注意DbSet.Local屬性的類型是ObservableCollection,當(dāng)向DbSet中添加和移除數(shù)據(jù)時,此“本地?cái)?shù)據(jù)集合”對象會激發(fā)CollectionChanged事件。這對于WPF桌面應(yīng)用來說實(shí)在是太妙了!
你可以在WPF桌面程序中這樣干:
使用DbContext提取數(shù)據(jù)后,讓W(xué)PF數(shù)據(jù)綁定控件(比如DataGrid)通過ViewSource組件綁定到相應(yīng)DbSet的Local屬性,之后就可以在窗體上進(jìn)行CRUD操作,所有操作被DbContext緩存起來,當(dāng)用戶點(diǎn)擊“保存”按鈕(或者是關(guān)閉窗體時),調(diào)用DbContext.saveChanges()方法存入數(shù)據(jù)庫。DbContext會自動跟蹤實(shí)體對象的狀態(tài),整個過程完全是自動化的!
如果你基于.NET 4.5并使用EF 6,則可以在WPF應(yīng)用中直接使用EF6新增的異步方法,比如DbContext.SaveChangesAsync(),EF會在獨(dú)立的線程中完成數(shù)據(jù)的提取、保存等工作(線程的分派工作在底層由.NET的TPL負(fù)責(zé),程序員可以不理會它),并且在這些工作結(jié)束時,異步方法的后繼代碼將在UI線程中執(zhí)行,這樣一來,多線程應(yīng)用中原來比較討厭的跨線程更新UI控件的問題就不存在了,用起來實(shí)在是方便,代碼可以精簡不少!
最后一個與“本地?cái)?shù)據(jù)集合”相關(guān)聯(lián)的話題是DbSet的Find方法,開發(fā)時記住以下這句話就行了:
使用Find方法查詢數(shù)據(jù)時,它會先在內(nèi)存中找,找不到之后再到數(shù)據(jù)庫中提取。
?
有關(guān)數(shù)據(jù)查詢的技巧還有不少,本篇文章只是介紹了我覺得比較重要的知識和比較有用的一些技巧,算是拋磚引玉吧。
?下篇文章帶領(lǐng)大家到EF“更新數(shù)據(jù)”這個領(lǐng)域“尋幽探勝”。
來源:?<http://blog.csdn.net/bitfan/article/details/13001935>?
來自為知筆記(Wiz)
轉(zhuǎn)載于:https://www.cnblogs.com/liyanwei/p/d9f9b690e71b14bcaf765a92b442e8e9.html
總結(jié)
以上是生活随笔為你收集整理的EntityFramework走马观花之CRUD(上)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从天而降的文字,文字掉落效果
- 下一篇: MONO,原来你是水中月