黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

EF 優(yōu)化

系統(tǒng) 2065 0

本文介紹一些改善EF代碼、優(yōu)化其性能的相關(guān)方法,如NoTracking,GetObjectByKey, Include等 ,還包括編譯查詢、存儲(chǔ)模型視圖以及沖突處理等內(nèi)容。


l ? ? ? ? MergeOption.NoTracking


當(dāng)我們只需要讀取某些數(shù)據(jù)而不需要?jiǎng)h除、更新的時(shí)候,可以指定使用MergeOption.NoTracking的方式來執(zhí)行只讀查詢(EF默認(rèn)的方式是AppendOnly)。當(dāng)指定使用NoTracking來進(jìn)行只讀查詢時(shí),與實(shí)體相關(guān)的引用實(shí)體不會(huì)被返回,它們會(huì)被自動(dòng)設(shè)置為null。因此,使用NoTracking可以提升查詢的性能。示例代碼如下:


[ Test ]

?

? ? ? ? public void NoTrackingTest()

?

? ? ? ?{

?

? ? ? ? ? ? using ( var db = new NorthwindEntities1 ())

?

? ? ? ? ? ?{

?

// 針對(duì)Customers查詢將使用MergeOption.NoTracking

?

? ? ? ? ? ? ? ?db.Customers.MergeOption = MergeOption .NoTracking;

?

? ? ? ? ? ? ? ? var cust = db.Customers.Where(c => c.City == "London" );

?

? ? ? ? ? ? ? ? foreach ( var c in cust)

?

? ? ? ? ? ? ? ? ? ? Console .WriteLine(c.CustomerID);

?

?

?

? ? ? ? ? ? ? ? // 也可以這樣寫

?

? ? ? ? ? ? ? ? //var cust1 = ((ObjectQuery<Customers>)cust).Execute(MergeOption.NoTracking);

?

?

?

? ? ? ? ? ? ? ? //Esql 寫法

?

? ? ? ? ? ? ? ? //string esql = "select value c from customers as c where c.CustomerID='ALFKI'";

?

? ? ? ? ? ? ? ? //db.CreateQuery<Customers>(esql).Execute(MergeOption.NoTracking).FirstOrDefault();

?

?

?

? ? ? ? ? ?}


? ? ? ?}


l ? ? ? ? GetObjectByKey/First


GetObjectByKey
在EF中,使用GetObjectByKey方法獲取數(shù)據(jù)時(shí),它首先會(huì)查詢是否有緩存,如果有緩存則從緩存中返回需要的實(shí)體。如果沒有則查詢數(shù)據(jù)庫,返回需要的實(shí)體,并添加在緩存中以便下次使用。
First: 總從數(shù)據(jù)庫中提取需要的實(shí)體。
因此,我們應(yīng)在合適的地方選擇GetObjectByKey方法來獲取數(shù)據(jù),以減少對(duì)數(shù)據(jù)庫的訪問提升性能。示例代碼如下:


[ Test ]

?

? ? ? ? public void GetByKeyTest()

?

? ? ? ?{

?

? ? ? ? ? ? using ( var db = new NorthwindEntities1 ())

?

? ? ? ? ? ?{

?

? ? ? ? ? ? ? ? // 從數(shù)據(jù)庫中提取數(shù)據(jù)

?

? ? ? ? ? ? ? ? var cst = db.Customers.First(c => c.CustomerID == "ALFKI" );

?

? ? ? ? ? ? ? ? Console .WriteLine(cst.CustomerID);

?

?

?

? ? ? ? ? ? ? ? // 將從緩存中提取數(shù)據(jù)

?

? ? ? ? ? ? ? ? EntityKey key = new EntityKey ( "NorthwindEntities1.Customers" , "CustomerID" , "ALFKI" );

?

? ? ? ? ? ? ? ? var cst1 = db.GetObjectByKey(key) as Customers ;

?

? ? ? ? ? ? ? ? Console .WriteLine(cst1.CustomerID);

?

?

?

?

?

? ? ? ? ? }


? ? ? ?}
此外,需要注意的是如果 GetObjectByKey 沒有獲取到符合條件的數(shù)據(jù),那么它會(huì)拋異常。為了避免此情況發(fā)生,在有可能出現(xiàn)異常的地方,我們應(yīng)該使用 TryGetObjectByKey 方法。 TryGetObjectByKey 方法獲取數(shù)據(jù)的方式和 GetObjectByKey 類似,只是當(dāng)沒有取到符合條件的數(shù)據(jù)時(shí), TryGetObjectByKey 會(huì)返回 null 而不是拋異常。示例代碼如下:


[ Test ]

?

? ? ? ? public void TryGetByKeyTest()

?

? ? ? ?{

?

? ? ? ? ? ? using ( var db = new NorthwindEntities1 ())

?

? ? ? ? ? ?{

?

?

?

? ? ? ? ? ? ? ? // 沒有符合條件的數(shù)據(jù)會(huì)有異常拋出

?

? ? ? ? ? ? ? ? EntityKey key = new EntityKey ( "NorthwindEntities1.Customers" , "CustomerID" , " ♂風(fēng)車車.Net" );

?

? ? ? ? ? ? ? ? var cst = db.GetObjectByKey(key) as Customers ;

?

? ? ? ? ? ? ? ? Console .WriteLine(cst.CustomerID);

?

?

?

? ? ? ? ? ? ? ? // 沒有符合條件的數(shù)據(jù)會(huì)有返回null

?

? ? ? ? ? ? ? ? EntityKey key1 = new EntityKey ( "NorthwindEntities1.Customers" , "CustomerID" , " ♂風(fēng)車車.Net" );

?

? ? ? ? ? ? ? ? Object cst1 = null ;

?

? ? ? ? ? ? ? ?db.TryGetObjectByKey(key1, out cst1);

?

? ? ? ? ? ? ? ? if (cst1 != null )

?

? ? ? ? ? ? ? ? ? ? Console .WriteLine((( Customers )cst1).CustomerID);

?

?

?

? ? ? ? ? ?}


? ? ? ?}


l ? ? ? ? First /FirstOrDefault


First: 當(dāng)我們使用First來獲取數(shù)據(jù),如果沒有符合條件的數(shù)據(jù),那么我們的代碼將會(huì)拋出異常。
FirstOrDefault: 當(dāng)我們使用 FirstOrDefault 來獲取的數(shù)據(jù),如果沒有符合條件的數(shù)據(jù),那么它將返回null。
顯然,對(duì)于一個(gè)良好的代碼,是對(duì)可以預(yù)見的異常進(jìn)行處理,而不是等它自己拋出來。示例代碼如下:


[ Test ]

?

? ? ? ? public void FirstTest()

?

? ? ? ?{

?

? ? ? ? ? ? using ( var db = new NorthwindEntities1 ())

?

? ? ? ? ? ?{

?

?

?

? ? ? ? ? ? ? ? // 拋異常的代碼

?

? ? ? ? ? ? ? ? var cst = db.Customers.First(c => c.CustomerID == " ♂風(fēng)車車.Net" );

?

? ? ? ? ? ? ? ? Console .WriteLine(cst.CustomerID); // 此處將出拋異常

?

? ? ? ? ? ? ?

?

? ? ? ? ? ? ? ? // 推薦的使用如下代碼:

?

? ? ? ? ? ? ? ? var cst1 = db.Customers.FirstOrDefault(c => c.CustomerID == " ♂風(fēng)車車.Net" );

?

? ? ? ? ? ? ? ? if (cst1 != null )

?

? ? ? ? ? ? ? ? ? ? Console .WriteLine(cst1.CustomerID);

?

? ? ? ? ? ?}


? ? ? ?}


l ? ? ? ? 延遲加載/Include


EF 不支持實(shí)體的部分屬性延遲加載,但它支持實(shí)體關(guān)系的延遲加載。默認(rèn)情況,實(shí)體的關(guān)系是不會(huì)加載。如下代碼:


[ Test ]

?

? ? ? ? public void IncludeTest()

?

? ? ? ?{

?

? ? ? ? ? ? using ( var db = new NorthwindEntities1 ())

?

? ? ? ? ? ?{

?

? ? ? ? ? ? ? var csts = db.Customers;

?

? ? ? ? ? ? ? ? foreach ( var c in csts)

?

? ? ? ? ? ? ? ?{

?

? ? ? ? ? ? ? ? ? ? Console .WriteLine(c.CustomerID);

?

? ? ? ? ? ? ? ? ? ? foreach ( var o in c.Orders)

?

? ? ? ? ? ? ? ? ? ? ? ? Console .WriteLine( " ? " + o.OrderID);

?

? ? ? ? ? ? ? ?}

?

? ? ? ? ? ?}


? ? ? ?}
上述代碼中,因?yàn)镺rders沒有被加載,所以在輸出Orders的時(shí)候,是不會(huì)有任何輸出的。
當(dāng)我們需要加載某些關(guān)聯(lián)的關(guān)系時(shí),可是用 Include 方法,如下代碼所示:


[ Test ]

?

? ? ? ? public void IncludeTest()

?

? ? ? ?{

?

? ? ? ? ? ? using ( var db = new NorthwindEntities1 ())

?

? ? ? ? ? ?{

?

? ? ? ? ? ? ? var csts = db.Customers.Include( "Orders" );

?

? ? ? ? ? ? ? ? foreach ( var c in csts)

?

? ? ? ? ? ? ? ?{

?

? ? ? ? ? ? ? ? ? ? Console .WriteLine(c.CustomerID);

?

? ? ? ? ? ? ? ? ? ? foreach ( var o in c.Orders)

?

? ? ? ? ? ? ? ? ? ? ? ? Console .WriteLine( " ? " + o.OrderID);

?

? ? ? ? ? ? ? ?}

?

? ? ? ? ? ?}

?

? ? ? ?}

?

上述代碼中,Customers關(guān)聯(lián)的Orders將被加載。

?

l ? ? ? ? CompiledQuery

?

提供對(duì)查詢的編譯和緩存以供重新使用。當(dāng)相同的查詢需要執(zhí)行很多遍的時(shí)候,那么我們可以使用 ComplieQuery 將查詢的語句進(jìn)行編譯以便下次使用,這樣可以免去對(duì)同一語句的多次處理,從而改善性能。

?

示例代碼如下:

?

[ Test ]

?

? ? ? ? public void ComplieTest()

?

? ? ? ?{

?

? ? ? ? ? ? using ( var db = new NorthwindEntities1 ())

?

? ? ? ? ? ?{

?

? ? ? ? ? ? ? ? // 對(duì)查詢進(jìn)行編譯

?

? ? ? ? ? ? ? ? var customer = CompiledQuery .Compile< NorthwindEntities1 , IQueryable < Customers >>(

?

? ? ? ? ? ? ? ? ? ?(database) => database.Customers.Where(c => c.City == "London" ));

?

? ? ? ? ? ? ?

?

? ? ? ? ? ? ? ? // 執(zhí)行20次相同的查詢

?

? ? ? ? ? ? ? ? for ( int i = 0; i < 20; i++)

?

? ? ? ? ? ? ? ?{

?

? ? ? ? ? ? ? ? ? ? DateTime dt = System. DateTime .Now;

?

? ? ? ? ? ? ? ? ? ? foreach ( var c in customer(db))

?

? ? ? ? ? ? ? ? ? ? ? ? Console .WriteLine(c.CustomerID);

?

? ? ? ? ? ? ? ? ? ? Console .WriteLine( DateTime .Now.Subtract(dt).TotalMilliseconds);

?

? ? ? ? ? ? ? ? ? ? Console .WriteLine( "---------------------------------------------------" );

?

? ? ? ? ? ? ? ?}

?

?

?

? ? ? ? ? ? }

?

? }

?

l ? ? ? ? 存儲(chǔ)模型視圖

?

EF 中,當(dāng)執(zhí)行實(shí)體查詢的時(shí)候,運(yùn)行時(shí)首先將實(shí)體模型轉(zhuǎn)換成 ESQL 視圖,而 ESQL 視圖則是根據(jù) msl 文件來生成相應(yīng)的代碼。此外, ESQL 視圖包含了相應(yīng)的查詢語句。 ESQL 視圖被創(chuàng)建后將在應(yīng)用程序域中進(jìn)行緩存以便下次使用。這個(gè)運(yùn)行時(shí)生成存儲(chǔ)模型視圖是比較耗時(shí)的過程。

?

為了,免去運(yùn)行時(shí)生成存儲(chǔ)模型視圖,我們可以預(yù)先產(chǎn)生這個(gè)的存儲(chǔ)模型視圖。具體步驟如下:

?

首先,使用 EdmGen2 來產(chǎn)生存儲(chǔ)模型視圖,相應(yīng)的命令如下:

?

Edmgen2 /ViewGen cs NorthwindEntites.edmx

?

執(zhí)行此命令后, edmgen2 會(huì)在當(dāng)前目錄下生成一個(gè)名為 NorthwindEntites.GeneratedViews.cs 這個(gè)文件,就是我們要使用的存儲(chǔ)模型視圖文件。

?

將此文件添加到項(xiàng)目中就行,其他的代碼不需要改變, EF 會(huì)自動(dòng)調(diào)用此視圖文件。如下示例代碼:

?

[ Test ]

?

? ? ? ? public void ViewTest()

?

? ? ? ?{

?

? ? ? ? ? ? using ( var db = new NorthwindEntities1 ())

?

? ? ? ? ? ?{

?

? ? ? ? ? ? ? ? var suppliers = db.Suppliers;

?

? ? ? ? ? ? ? ? foreach ( var s in suppliers)

?

? ? ? ? ? ? ? ? ? ? Console .WriteLine(s.ContactName);

?

? ? ? ? ? ?}

?

? ? ? ?}

?

沒有使用存儲(chǔ)模型視圖的情況是:

?

1 passed, 0 failed, 0 skipped, took 7.09 seconds.

?

項(xiàng)目中添加了 NorthwindEntites.GeneratedViews.cs 文件,執(zhí)行情況是:

?

1 passed, 0 failed, 0 skipped, took 5.38 seconds.

?

可見,使用了存儲(chǔ)模型視圖的確是提高了性能。

?

l ? ? ? ? 沖突處理

?

EF 中,默認(rèn)情況并不會(huì)檢查并發(fā)沖突。因?yàn)? EF 實(shí)現(xiàn)的是樂觀的并發(fā)模式,當(dāng)有并發(fā)的沖突發(fā)生時(shí),將會(huì)拋出 Optimistic Concurrency Exception 異常。我們可以通過使用 RefreshMode 這個(gè)枚舉來指定當(dāng)發(fā)生沖突時(shí)如何處理。

?

RefreshMode 有兩中枚舉值:

?

ClientsWins: 當(dāng)提交修改,更新數(shù)據(jù)庫中的值。

?

StoreWins: 放棄修改,使用數(shù)據(jù)庫中的值。

?

示例代碼片段如下:

?

var db2 = new NorthwindEntities1 ();

?

? ? ? ? ? ? var customer2 = db2.Customers.FirstOrDefault(c => c.CustomerID == "2009" );

?

? ? ? ? ? ? if (customer2 != null )

?

? ? ? ? ? ?{

?

? ? ? ? ? ? ? ?customer2.ContactName = " ♂風(fēng)車車.Net" ;

?

? ? ? ? ? ? ? ?customer2.City = "CD" ;

?

? ? ? ? ? ? ? ?customer2.Region = "GX" ;

?

? ? ? ? ? ?}

?

? ? ? ? ? ? try

?

? ? ? ? ? ?{

?

? ? ? ? ? ? ? ?db2.SaveChanges();

?

? ? ? ? ? ?}

?

? ? ? ? ? ? catch ( OptimisticConcurrencyException ex) // 捕獲到?jīng)_突,則進(jìn)行相應(yīng)的處理

?

? ? ? ? ? ?{

?

? ? ? ? ? ? ? ?db2.Refresh( RefreshMode .ClientWins, customer2);

?

? ? ? ? ? ? ? ?db2.SaveChanges();

?

? ? ? ? ? ?}

?

上述代碼片段,只是說明怎么處理并發(fā)沖突,不是具體的并發(fā)。(ps:本來是準(zhǔn)備開個(gè)線程來模擬并發(fā)的,但是始終沒成功,沒明白什么原因,望高人指點(diǎn)呢!)

出處:
http://www.cnblogs.com/xray2005

EF 優(yōu)化


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論