菜鳥對(duì)于ADO.NET訪問(wèn)技術(shù)說(shuō)明詳談
在上一文末寫了幾個(gè)關(guān)于用Include加載多級(jí)實(shí)體的查詢,不過(guò)前天在ADO.NET訪問(wèn)看到一個(gè)關(guān)于Include加載多級(jí)實(shí)體的問(wèn)題,經(jīng)過(guò)一番交流和測(cè)試,算是明白了所以然.雖然自己常常在那樣寫ADO.NET訪問(wèn)查詢,也許是因?yàn)樵谑褂玫倪^(guò)程中沒(méi)有遇到棘手的問(wèn)題,所以也沒(méi)去多想.
在本文之前,還是先說(shuō)說(shuō)那個(gè)問(wèn)題.在edm中這樣的一個(gè)關(guān)系:Customers 1 --- * Orders * --- 1 Status,在這個(gè)關(guān)系下面做這樣一個(gè)查詢 var = query from customer in Customers.Include("Orders.Status") ADO.NET訪問(wèn)在調(diào)試的時(shí)候他發(fā)現(xiàn)Customer的Order被及時(shí)加載(PreLoad),Status卻沒(méi)有.所以問(wèn)題人覺得這是不是EF在設(shè)計(jì)上的緣故,還是其他什么原因.我告訴他不是設(shè)計(jì)上的原因,因?yàn)槲揖统D敲磳?當(dāng)然標(biāo)準(zhǔn)的寫法是Inclue("Orders").Include("Orders.Status").
之前我在adonot blog上看到關(guān)于Linq to Sql與 Linq to Entity 在Eager Loading方式上的區(qū)別,也見過(guò)那樣寫,ADO.NET訪問(wèn)當(dāng)然最關(guān)鍵的,我那樣做查詢沒(méi)有出先上述的問(wèn)題.不過(guò)我還是在想,難道這個(gè)查詢出現(xiàn)問(wèn)題是和模型的1:n:1關(guān)系有關(guān)嗎?
以前都沒(méi)在意這些,我在使用過(guò)類似這種查詢的地方,的確沒(méi)有符合這種關(guān)系.于是我昨天做了一個(gè)測(cè)試在ADO.NET訪問(wèn)里面恰好有Products 1--* OrderDetails *--1 Orders 符合條件的一組關(guān)系,并做了寫了如下的代碼,ADO.NET訪問(wèn)一邊debug,一邊跟蹤數(shù)據(jù)庫(kù),的確只生成一條sql.后來(lái)我又選了1:n:n以及Customer 1:n Order 1:nOrderDetails的關(guān)系組也均都只生成一條sql.
在上面這段代碼中,通過(guò)getOrderListByCity方法London城市的Orders,并由每一個(gè)Order查找相應(yīng)Customer的CustomerID.由于存在一個(gè)循環(huán),故總共訪問(wèn)數(shù)據(jù)33次.但是真的是由于Orders.CustomerID有33個(gè)嗎?顯然不是,ADO.NET訪問(wèn)從上圖運(yùn)行結(jié)果來(lái)看就知道,其中有很多CustomerID是重復(fù)的.那有什么方法阻止數(shù)據(jù)庫(kù)重復(fù)查詢呢?.在EF內(nèi)對(duì)于關(guān)連實(shí)體(導(dǎo)航屬性)除了關(guān)聯(lián)實(shí)體外還有一個(gè)屬性**Reference屬性
該屬性暴露了一個(gè)屬性IsLoad,判斷關(guān)聯(lián)實(shí)體是否已經(jīng)加載.在EF中實(shí)體是依靠entityKey(數(shù)據(jù)庫(kù)表主鍵)來(lái)識(shí)別的,一旦該entity Key對(duì)應(yīng)的實(shí)體已被加載,context就不會(huì)重復(fù)去數(shù)據(jù)庫(kù)去取了,如果該entity key對(duì)應(yīng)實(shí)體沒(méi)有被加載,就會(huì)去數(shù)據(jù)庫(kù)去取.所以增加這樣一個(gè)判斷