EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
EF里的默認(rèn)映射以及如何使用Data Annotations和Fluent API配置數(shù)據(jù)庫(kù)的映射
I.EF里的默認(rèn)映射
上篇文章演示的通過定義實(shí)體類就可以自動(dòng)生成數(shù)據(jù)庫(kù),并且EF自動(dòng)設(shè)置了數(shù)據(jù)庫(kù)的主鍵、外鍵以及表名和字段的類型等,這就是EF里的默認(rèn)映射。具體分為:
摘自這里
默認(rèn)的映射一般只是簡(jiǎn)單映射,方便使用罷了。當(dāng)然這些都是可以進(jìn)行修改的,請(qǐng)往下看。
II.使用Data Annotations和Fluent API配置數(shù)據(jù)庫(kù)的映射
Data Annotations翻譯過來就是數(shù)據(jù)注解,是通過直接在實(shí)體類的屬性上加注類似標(biāo)簽的東西達(dá)到對(duì)數(shù)據(jù)庫(kù)的映射;
Fluent API翻譯過來就是流利的API,Fluent API是在DbContext中定義數(shù)據(jù)庫(kù)配置的一種方式。要使用Fluent API 就必須在你自定義的繼承自DbContext的類中重載OnModelCreating這個(gè)方法。注意:
實(shí)戰(zhàn):
1.Data Annotations:
設(shè)置Destination表的Name不為null:
很簡(jiǎn)單,直接在屬性上加[Required]標(biāo)注即可;
2.Fluent API:
用Fluent api必須重寫OnModelCreating方法,我們?cè)谏舷挛念惱镏貙懴翺nModelCreating方法并添加不為空的配置:
方法分析:先找到需要配置的實(shí)體類,然后點(diǎn)Property就是點(diǎn)出屬性,=>是lambda表達(dá)式的寫法,找到Name屬性,然后調(diào)用IsRequired方法設(shè)置不為null。初見這東西肯定不好理解,多寫寫就熟悉了。
兩種配置方式個(gè)人更喜歡Fluent API的方式,故放出的demo中Data Annotations也是有的,不過都被注釋了。隨著開發(fā)的深入,有些東西還是必須用Fluent API的方式才能配置出來的。
注意:我的類庫(kù)都修改了默認(rèn)命名空間(右鍵類庫(kù) - 屬性),都加了個(gè)CodeFirst. 方便區(qū)分,其他類庫(kù)中調(diào)用,我也是習(xí)慣用完整的命名空間.類庫(kù)再.實(shí)體類來調(diào)用。
思考:使用Fluent API方式配置,每次都需要在OnModelCreating方法里寫上一行配置,這樣一個(gè)實(shí)體類如果有3個(gè)屬性需要配置,10個(gè)實(shí)體類就需要配置30個(gè),那么就得在OnModelCreating方法里寫30行,很麻煩且不易維護(hù)。
解決辦法:注意返回值可以看出modelBuilder的Entity<>泛型方法的返回值是EntityTypeConfiguration<>泛型類。我們可以定義一個(gè)繼承自EntityTypeConfiguration<>泛型類的類來定義domain中每個(gè)類的數(shù)據(jù)庫(kù)配置。
ok,我們?cè)贒ataAccess類庫(kù)下新建一個(gè)繼承自EntityTypeConfiguration<>泛型類的DestinationMap類,在構(gòu)造函數(shù)里寫上配置:
需添加引用:using System.Data.Entity.ModelConfiguration;
這樣,以后Destination需要配置的都來這里配置,然后添加到上下文中的OnModelCreating方法即可:
其他類的配置也是這樣,先添加一個(gè)類名+Map的方法(命名隨意),然后添加到OnModelCreating方法。
隨意配置一些屬性,然后跑下程序看生成的數(shù)據(jù)庫(kù):
可見:Name列已經(jīng)不可空,Description也設(shè)置了長(zhǎng)度不超過500等等。
注意:如果重新跑程序生成數(shù)據(jù)庫(kù)報(bào)這個(gè)錯(cuò):
The model backing the 'BreakAwayContext' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data.
意思就是,當(dāng)前數(shù)據(jù)庫(kù)正在使用中,無法刪除再重新生成。這個(gè)時(shí)候斷開數(shù)據(jù)庫(kù)連接,再跑下程序就可以了。以后每次配置實(shí)體類再重新跑程序都需要斷開數(shù)據(jù)庫(kù)連接。
不知道大家還記不記得第一篇文章講的EdmMetadata這個(gè)表,EF會(huì)自動(dòng)生成這個(gè)表。這個(gè)表是監(jiān)控實(shí)體類變化的,其實(shí)是個(gè)詬病,每次操作數(shù)據(jù)庫(kù)都會(huì)發(fā)訪問這張表的sql到數(shù)據(jù)庫(kù),用sql Profiler跟蹤下即可發(fā)現(xiàn)如下sql:
2013.08.07補(bǔ)充:感謝園長(zhǎng)dudu在回復(fù)中(4樓)的糾正,不是每次操作數(shù)據(jù)庫(kù)都會(huì)發(fā)送sql到數(shù)據(jù)庫(kù),只是在EF初始化的時(shí)候會(huì)發(fā)送訪問EdmMetadata表的sql到數(shù)據(jù)庫(kù)。另推薦dudu的兩篇文章供大家閱讀:讓Entity Framework不再私闖sys.databases 揭開Entity Framework LINQ查詢的一點(diǎn)面紗
SELECT TOP (1) [Extent1].[Id] AS [Id], [Extent1].[ModelHash] AS [ModelHash] FROM [dbo].[EdmMetadata] AS [Extent1] ORDER BY [Extent1].[Id] DESC注:sql Profiler是一個(gè)監(jiān)控發(fā)送到數(shù)據(jù)庫(kù)sql語句的工具。sql server 2008自帶,操作簡(jiǎn)單,如果不會(huì)請(qǐng)自行搜索相關(guān)資料。如果沒有這個(gè)工具,那么是數(shù)據(jù)庫(kù)版本不對(duì)或者數(shù)據(jù)庫(kù)裝出了問題。sql Profiler這工具后面講一對(duì)一、一對(duì)多、多對(duì)多的各種操作時(shí)會(huì)經(jīng)常使用到,也是我們調(diào)試EF語句性能的好幫手:
擴(kuò)展:可以在OnModelCreating方法里添加:
需引入命名空間:
using System.Data.Entity.ModelConfiguration.Conventions; using System.Data.Entity.Infrastructure;第一句是移除復(fù)數(shù)表名的契約,就是EF默認(rèn)生成的表名都是實(shí)體類的復(fù)數(shù)形式,有這句,表名就是實(shí)體類的名字了,不會(huì)再加個(gè)s了,當(dāng)然你也可以通過強(qiáng)大的Fluent API配置這個(gè)。
第二句就是移除對(duì)EdmMetadata表的訪問的,下次再操作數(shù)據(jù)庫(kù),就不會(huì)有訪問EdmMetadata表的sql了。
注意:如果之前已經(jīng)有數(shù)據(jù)庫(kù)了,那么再加上移除對(duì)EdmMetadata表訪問的配置再跑程序會(huì)報(bào)一個(gè)NotSupportedException的錯(cuò):
Model compatibility cannot be checked because the EdmMetadata type was not included in the model. Ensure that IncludeMetadataConvention has been added to the DbModelBuilder conventions.
這個(gè)時(shí)候,先把BreakAwayConfigFile數(shù)據(jù)庫(kù)分離,然后在本地刪除掉數(shù)據(jù)庫(kù)文件,再跑程序就可以了。如果不知道sql server的mdf和ldf文件的默認(rèn)路徑,請(qǐng)自行搜索。
結(jié)果跑了下程序,的確沒有產(chǎn)生對(duì)EdmMetadata表訪問的sql了,但是sql Profiler監(jiān)控到了更多的sql語句被發(fā)送到了數(shù)據(jù)庫(kù)。當(dāng)初為了少一個(gè)訪問EdmMetadata表的sql,結(jié)果多了更多的sql,并且如果再次生成數(shù)據(jù)庫(kù)還必須要手動(dòng)分離現(xiàn)有數(shù)據(jù)庫(kù)并刪除硬盤上的數(shù)據(jù)庫(kù)文件。這里使不使用還是有待商量的,暫時(shí)注釋掉:
思考:EF小組設(shè)計(jì)EdmMetadata表肯定有它的道理,移除對(duì)其的訪問也不一定是科學(xué)的。這里僅做學(xué)習(xí)演示,真正的項(xiàng)目中可能也很少用Code First的方式生成數(shù)據(jù)庫(kù)的。至少4.1版本下的EF使用Code First是有缺陷的,每次都要干掉所有數(shù)據(jù),這個(gè)肯定不合適。后續(xù)版本的EF有數(shù)據(jù)遷徙的功能能解決這個(gè),目前只是學(xué)習(xí)4.1這個(gè)經(jīng)典的EF版本。
補(bǔ)充:實(shí)際開發(fā)中還是database First的方式比較主流。
上面只演示了簡(jiǎn)單的Data Annotations和Fluent API的一些簡(jiǎn)單配置,其實(shí)還有很多,下面列出部分常用,初學(xué)者應(yīng)該都試著敲敲,然后對(duì)照著生成的數(shù)據(jù)庫(kù)好好學(xué)習(xí)下如何配置:
部分摘自這里
目前階段看這個(gè)的確稍顯復(fù)雜,僅做了解和方便后期查閱。后續(xù)講一對(duì)一、一對(duì)多和多對(duì)多的關(guān)系時(shí)反復(fù)的手寫Fluent API的時(shí)候就會(huì)很好理解了。
源碼:點(diǎn)擊下載
EF Code First 系列文章導(dǎo)航:分類: 4.Entity Framework
轉(zhuǎn)載于:https://my.oschina.net/wzzz/blog/494743
總結(jié)
以上是生活随笔為你收集整理的EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hitpoint:外贸企业如何选择合适的
- 下一篇: Android Resources