日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

EF 優(yōu)化

系統(tǒng) 1924 0

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


l ? ? ? ? MergeOption.NoTracking


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


[ Test ]

?

? ? ? ? public void NoTrackingTest()

?

? ? ? ?{

?

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

?

? ? ? ? ? ?{

?

// 針對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ù)據(jù)庫,返回需要的實體,并添加在緩存中以便下次使用。
First: 總從數(shù)據(jù)庫中提取需要的實體。
因此,我們應(yīng)在合適的地方選擇GetObjectByKey方法來獲取數(shù)據(jù),以減少對數(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ù),那么它會拋異常。為了避免此情況發(fā)生,在有可能出現(xiàn)異常的地方,我們應(yīng)該使用 TryGetObjectByKey 方法。 TryGetObjectByKey 方法獲取數(shù)據(jù)的方式和 GetObjectByKey 類似,只是當沒有取到符合條件的數(shù)據(jù)時, TryGetObjectByKey 會返回 null 而不是拋異常。示例代碼如下:


[ Test ]

?

? ? ? ? public void TryGetByKeyTest()

?

? ? ? ?{

?

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

?

? ? ? ? ? ?{

?

?

?

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

?

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

?

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

?

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

?

?

?

? ? ? ? ? ? ? ? // 沒有符合條件的數(shù)據(jù)會有返回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: 當我們使用First來獲取數(shù)據(jù),如果沒有符合條件的數(shù)據(jù),那么我們的代碼將會拋出異常。
FirstOrDefault: 當我們使用 FirstOrDefault 來獲取的數(shù)據(jù),如果沒有符合條件的數(shù)據(jù),那么它將返回null。
顯然,對于一個良好的代碼,是對可以預(yù)見的異常進行處理,而不是等它自己拋出來。示例代碼如下:


[ 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 不支持實體的部分屬性延遲加載,但它支持實體關(guān)系的延遲加載。默認情況,實體的關(guān)系是不會加載。如下代碼:


[ 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);

?

? ? ? ? ? ? ? ?}

?

? ? ? ? ? ?}


? ? ? ?}
上述代碼中,因為Orders沒有被加載,所以在輸出Orders的時候,是不會有任何輸出的。
當我們需要加載某些關(guān)聯(lián)的關(guān)系時,可是用 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

?

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

?

示例代碼如下:

?

[ Test ]

?

? ? ? ? public void ComplieTest()

?

? ? ? ?{

?

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

?

? ? ? ? ? ?{

?

? ? ? ? ? ? ? ? // 對查詢進行編譯

?

? ? ? ? ? ? ? ? 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 ? ? ? ? 存儲模型視圖

?

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

?

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

?

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

?

Edmgen2 /ViewGen cs NorthwindEntites.edmx

?

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

?

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

?

[ Test ]

?

? ? ? ? public void ViewTest()

?

? ? ? ?{

?

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

?

? ? ? ? ? ?{

?

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

?

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

?

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

?

? ? ? ? ? ?}

?

? ? ? ?}

?

沒有使用存儲模型視圖的情況是:

?

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

?

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

?

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

?

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

?

l ? ? ? ? 沖突處理

?

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

?

RefreshMode 有兩中枚舉值:

?

ClientsWins: 當提交修改,更新數(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)_突,則進行相應(yīng)的處理

?

? ? ? ? ? ?{

?

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

?

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

?

? ? ? ? ? ?}

?

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

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

EF 優(yōu)化


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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

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

【本文對您有幫助就好】

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

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 腾冲县| 乐东| 通河县| 关岭| 两当县| 蕲春县| 镇雄县| 临西县| 菏泽市| 偃师市| 玉龙| 和平区| 拉萨市| 岫岩| 巩义市| 田东县| 高淳县| 南京市| 射阳县| 松桃| 镇雄县| 安顺市| 渑池县| 灌南县| 邢台县| 永吉县| 通化县| 白水县| 汝城县| 南平市| 凤山市| 宜阳县| 德格县| 巴林左旗| 正定县| 东明县| 浏阳市| 呼伦贝尔市| 舞阳县| 西安市| 堆龙德庆县|