欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Linq查詢(xún)與性能舉例分析

這篇文章主要講解了“Linq查詢(xún)與性能舉例分析”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Linq查詢(xún)與性能舉例分析”吧!

瓊中黎族網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)建站!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)建站公司2013年成立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專(zhuān)注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)建站

Orcas(VS2008&Framework3.5)給我們帶來(lái)了很多令人興奮的新特性,尤其是LINQ的引進(jìn),可以說(shuō)方便了一大批開(kāi)發(fā)人員和框架設(shè)計(jì)人員。過(guò)去,當(dāng)我們使用O/RMapping的一些框架時(shí),最擔(dān)心的應(yīng)該是復(fù)雜的查詢(xún)和數(shù)據(jù)庫(kù)操作的性能問(wèn)題,那么LINQ在這個(gè)方面給我們帶來(lái)了什么呢?從LINQ查詢(xún)開(kāi)始說(shuō)起吧。

一:LINQ查詢(xún):

一個(gè)項(xiàng)目中,對(duì)數(shù)據(jù)庫(kù)操作最多的應(yīng)該就是查詢(xún),特別是復(fù)雜一些的項(xiàng)目,查詢(xún)往往是從很多張表里取一些數(shù)據(jù),“東拼西湊”的呈現(xiàn)給用戶(hù)。如果不使用O/R Mapping呢,我們處理的方式無(wú)非是兩種:復(fù)雜的SQL語(yǔ)句或者是存儲(chǔ)過(guò)程。

但是,在使用了O/R Mapping的情況下,為了保證取出的數(shù)據(jù)是強(qiáng)類(lèi)型,不得不用多個(gè)方法來(lái)進(jìn)行拼湊,麻煩且不說(shuō),性能損失是肯定的,那么也就出現(xiàn)了O/R Mapping框架和未封裝的ADO.NET一起用的尷尬場(chǎng)面。那么LINQ查詢(xún)?cè)趺刺幚淼哪??首先我們先?lái)看一些復(fù)雜的查詢(xún)語(yǔ)法。

設(shè)計(jì)兩張表,分別為表示部門(mén)(Department)和員工(Employee):

1、 模糊查詢(xún):

模糊查詢(xún)?cè)贠/RMapping的框架中是比較難實(shí)現(xiàn)的,即使實(shí)現(xiàn),效率也不是很高,LINQ提供了我們豐富的模糊查詢(xún)的方法,比如我們要在Employee表中查姓張的人,可以這樣:

DBDataClassesDataContext dbdata = new DBDataClassesDataContext();  var query = from employee in dbdata.Employees where employee.EmployeeName.StartsWith("張") select employee;

在實(shí)際執(zhí)行的時(shí)候,這句話(huà)被轉(zhuǎn)換成了:

SELECT [t0].[EmployeeId], [t0].[DepId], [t0].[EmployeeName], [t0].[EmployeeSalary] FROM [dbo].[Employee] AS [t0] WHERE [t0].[EmployeeName] LIKE @p0

這樣的SQL語(yǔ)句,這個(gè)里面的@p0這個(gè)參數(shù)在執(zhí)行的時(shí)候加上了“%”,也就是以@p0開(kāi)頭的任何符合條件的記錄都被取出來(lái)了。這樣的方法在LINQ查詢(xún)中還有Contains、EndsWith等。

2、嵌套查詢(xún):

如果我們需要取出市場(chǎng)部的所有員工,在以往的O/R Mapping框架中,往往需要取兩次(我們不考慮存在映射關(guān)系的情況),一次是取出市場(chǎng)部的編號(hào),再使用編號(hào)來(lái)取出所有員工。LINQ查詢(xún)給我們提供了更好的解決辦法,我們可以這樣操作:

var query = from employee in dbdata.Employees where employee.DepId ==  (from department in dbdata.Departments where department.DepName == "市場(chǎng)部"  select department ).Single().DepId  select employee;

這里我們使用了嵌套查詢(xún)來(lái)完成,這句話(huà)在執(zhí)行的時(shí)候,被轉(zhuǎn)換成了SQL的嵌套查詢(xún):

SELECT [t0].[EmployeeId], [t0].[DepId], [t0].[EmployeeName], [t0].[EmployeeSalary] FROM [dbo].[Employee] AS [t0] WHERE [t0].[DepId] = (SELECT [t1].[DepId] FROM [dbo].[Department] AS [t1] WHERE [t1].[DepName] = @p0)

當(dāng)然,在這里,我們不必那么麻煩,只需要使用已經(jīng)存在的實(shí)體關(guān)系,就可以輕松的完成:

var query = from employee in dbdata.Employees where employee.Department.DepName == "市場(chǎng)部" select employee;

不過(guò),這和剛才的查詢(xún)卻有本質(zhì)的差別,我們來(lái)看看這里,LINQ查詢(xún)轉(zhuǎn)換成什么樣的SQL語(yǔ)句了:

SELECT [t0].[EmployeeId], [t0].[DepId], [t0].[EmployeeName], [t0].[EmployeeSalary] FROM [dbo].[Employee] AS [t0] LEFT OUTER JOIN [dbo].[Department] AS [t1] ON [t1].[DepId] = [t0].[DepId] WHERE [t1].[DepName] = @p0

這里,轉(zhuǎn)換出來(lái)的并不是嵌套的SQL語(yǔ)句,而被轉(zhuǎn)換成了左連接查詢(xún),可以看出,嵌套查詢(xún)是我們?cè)谔厥獾那闆r下,可以使用的一個(gè)利器。

3、投影

如果說(shuō)剛才的查詢(xún),還只是很簡(jiǎn)單的查詢(xún),那么結(jié)合匿名類(lèi)來(lái)實(shí)現(xiàn)投影查詢(xún),則是LINQ查詢(xún)提供的一個(gè)利器,這種方法非常靈活,同時(shí)也滿(mǎn)足了我們絕大部分的查詢(xún)需求。下面我們來(lái)看一個(gè)例子:我們需要查詢(xún)出部門(mén)工資的總和,怎么做呢?

var query = from department in dbdata.Departments  select  new{ depid = department.DepId, depname=department.DepName, depsalary = department.Employees.Sum(e => e.EmployeeSalary) };

這句查詢(xún)語(yǔ)句中,在new關(guān)鍵字后面生成了一個(gè)匿名類(lèi),這個(gè)類(lèi)有三個(gè)屬性,分別是 depid,depname和depsalary,其中,depsalary是經(jīng)過(guò)計(jì)算獲得,這句話(huà)被轉(zhuǎn)換成:

SELECT [t0].[DepId] AS [depid], [t0].[DepName] AS [depname], (SELECT SUM([t1].[EmployeeSalary]) FROM [dbo].[Employee] AS [t1] WHERE [t1].[DepId] = [t0].[DepId] ) AS [depsalay] FROM [dbo].[Department] AS [t0]

好優(yōu)雅的代碼,實(shí)在是太方便了。

4、使用LINQ查詢(xún)的擴(kuò)展方法

LINQ查詢(xún)提供了很多擴(kuò)展方法,方便我們做各種查詢(xún),我們來(lái)看幾個(gè)典型的擴(kuò)展方法:

a) Average、Max

Decimal x = dbdata.Employees.Average(e => e.EmployeeSalary);  Decimal y = dbdata.Employees.Max(e => e.EmployeeSalary);

這是計(jì)算出員工的平均工資與***工資,你不需要編寫(xiě)任何的SQL語(yǔ)句,Orcas中提供的LINQ到SQL對(duì)象關(guān)系映射器會(huì)處理獲取,跟蹤,和更新映射到你的數(shù)據(jù)庫(kù)數(shù)據(jù)定義和存儲(chǔ)過(guò)程的對(duì)象。

你只要使用任何LINQ查詢(xún)擴(kuò)展方法對(duì)結(jié)果進(jìn)行過(guò)濾和構(gòu)形即可,LINQ到SQL會(huì)執(zhí)行獲取數(shù)據(jù)所需的SQL代碼(注意,上面的 Average和Max 擴(kuò)展方法很明顯地不會(huì)從數(shù)據(jù)表中返回所有的數(shù)據(jù)行,它們會(huì)使用TSQL的聚合函數(shù)來(lái)計(jì)算數(shù)據(jù)庫(kù)中的值,然后只返回一個(gè)標(biāo)量值)。

b) Where、OrderBy

有時(shí)候,我們只對(duì)某張表做簡(jiǎn)單的查詢(xún)和排序,那么,這個(gè)時(shí)候不必寫(xiě)冗長(zhǎng)的LINQ查詢(xún)語(yǔ)句,直接使用LINQ擴(kuò)展方法即可,如:

var query = dbdata.Employees.Where(e => e.EmployeeSalary > 2000).OrderBy(e => e.EmployeeName);

這里使用了Lambda語(yǔ)法,這句話(huà)被轉(zhuǎn)換成以下的SQL語(yǔ)句:

SELECT [t0].[EmployeeId], [t0].[DepId], [t0].[EmployeeName], [t0].[EmployeeSalary] FROM [dbo].[Employee] AS [t0] WHERE [t0].[EmployeeSalary] > @p0 ORDER BY [t0].[EmployeeName]

以上是通過(guò)利用由Lambda提供的對(duì)表達(dá)式樹(shù)支持,以及IQueryable接口來(lái)實(shí)現(xiàn)的,代碼干凈整潔。

C)Take、Skip

對(duì)于大批量的數(shù)據(jù)處理,一直是開(kāi)發(fā)人員的比較頭疼的事情,微軟在.NET1.1到2.0中的Gridview等控件,對(duì)大批量數(shù)據(jù)的處理上一直都不是很理想,LINQ查詢(xún)對(duì)于大批量數(shù)據(jù)的處理,可以很好的解決這個(gè)方面的問(wèn)題。

var query = dbdata.Employees.Skip(10).Take(10);

這句話(huà)表示跳過(guò)該表的10條記錄,再取10條,也就是取第11至20條記錄,轉(zhuǎn)換成SQL語(yǔ)句如下:

SELECT [t1].[EmployeeId], [t1].[DepId], [t1].[EmployeeName], [t1].[EmployeeSalary] FROM (SELECT ROW_NUMBER() OVER (ORDER BY [t0].[EmployeeId], [t0].[DepId], [t0].[EmployeeName], [t0].[EmployeeSalary]) AS [ROW_NUMBER], [t0].[EmployeeId], [t0].[DepId], [t0].[EmployeeName], [t0].[EmployeeSalary] FROM [dbo].[Employee] AS [t0]) AS [t1] WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1 ORDER BY [t1].[ROW_NUMBER]

從以上這句SQL語(yǔ)句來(lái)看,最消耗性能分頁(yè)操作完全交給了數(shù)據(jù)庫(kù)操作,其處理的機(jī)制不再像Gridview控件的分頁(yè),是將數(shù)據(jù)全部取出,然后再進(jìn)行分頁(yè)顯示,因此效率上要高了很多。

D)ToList和ToArray

在默認(rèn)情況下,查詢(xún)結(jié)果的數(shù)據(jù)類(lèi)型是IEnumerable類(lèi)型,可能很多開(kāi)發(fā)人員并不習(xí)慣這個(gè)類(lèi)型,而更加喜歡集合或者是數(shù)組,那么沒(méi)關(guān)系,可以使用ToList或者是ToArray來(lái)將查詢(xún)結(jié)果轉(zhuǎn)換成集合或者數(shù)組。

在這里,我們需要知道的是:使用查詢(xún)語(yǔ)句查詢(xún)結(jié)果的時(shí)候,實(shí)際上并沒(méi)有真正操作數(shù)據(jù)庫(kù),這里是運(yùn)用的延遲加載的機(jī)制,如果不希望使用延遲加載,而是需要立刻知道查詢(xún)的結(jié)果時(shí),使用ToList或者是ToArray便可以做到。這是非常有用的機(jī)制。

比如我們需要顯示兩個(gè)部門(mén)的員工時(shí),部門(mén)可以先取出放置在List中,然后再依次取出各個(gè)部門(mén)的員工,這時(shí)訪(fǎng)問(wèn)的效率要高一些,因?yàn)椴恍枰看味荚L(fǎng)問(wèn)數(shù)據(jù)庫(kù)去取出部門(mén)。

二:數(shù)據(jù)操作的性能分析

當(dāng)我們會(huì)熟練的使用以上的查詢(xún)方法對(duì)數(shù)據(jù)庫(kù)里的內(nèi)容做各種各樣的查詢(xún)以后,就應(yīng)當(dāng)要了解這些數(shù)據(jù)庫(kù)操作的機(jī)制,及時(shí)調(diào)整各種數(shù)據(jù)操作語(yǔ)句,以較高的效率運(yùn)行。那么,下面我們來(lái)看看LINQ的數(shù)據(jù)庫(kù)操作,看看她都做了些什么工作。

與NHibernate來(lái)比較,LINQ在O/R Mapping的性能與可控性上確實(shí)優(yōu)于NHibernate,首先,Linq默認(rèn)的數(shù)據(jù)映射采用的是Attribute來(lái)實(shí)現(xiàn),這是.NET特有的語(yǔ)法,在編譯時(shí)就已經(jīng)決定了數(shù)據(jù)對(duì)象的各種屬性,而NHibernate等大多數(shù)O/RMapping工具仍然采用XML映射文件來(lái)描述數(shù)據(jù)對(duì)象的屬性,從外部文件上讀取數(shù)據(jù)對(duì)象的屬性,顯然運(yùn)行時(shí)效率要有所損失。

其次,在獲得數(shù)據(jù)的方式上也有所差別,LINQ中強(qiáng)大的SQL分析機(jī)制,可以分析出各種數(shù)據(jù)操作的SQL語(yǔ)句,并且進(jìn)行優(yōu)化,其效率的提升也是顯而易見(jiàn)的。

當(dāng)然,作為一個(gè)O/R Mapping的工具來(lái)說(shuō),其效率一定達(dá)不到直接使用SQL語(yǔ)句訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的效率,也就是我們通常所說(shuō)的SqlDataReader/SqlDataAdapter訪(fǎng)問(wèn)數(shù)據(jù)庫(kù),但是,Linq的表現(xiàn)卻給了我們非常大的驚喜。

我做了一個(gè)測(cè)試,使用SqlDataReader和LINQ做相同的大批量數(shù)據(jù)查詢(xún)時(shí),落后竟然不到10%,而NHibernate的查詢(xún)效率,卻低了很多,幾乎慢了1倍。對(duì)于如此強(qiáng)大的數(shù)據(jù)映射功能,這樣的效率是我們可以接受的。但是很可惜的一點(diǎn)是,LINQ查詢(xún)目前只能支持對(duì)SQLServer的支持(但可以支持XML、Entity等)。

在數(shù)據(jù)查詢(xún)上,我們通過(guò)對(duì)LINQ查詢(xún)生成的SQL語(yǔ)句進(jìn)行分析,便可以?xún)?yōu)化查詢(xún),這是非常方便的,但是,針對(duì)數(shù)據(jù)更新的效率問(wèn)題,我們不得不談?wù)凩INQ的數(shù)據(jù)更新機(jī)制,一般情況下,數(shù)據(jù)更新我們會(huì)這么做:

var query = from emp in dbdata.Employees where emp.DepId=="1001" select emp;    Employee employee = query.First();    employee.EmployeeName = "李四";    dbdata.SubmitChanges();

對(duì)于以上這段代碼,我們可以看出,其功能是從Employee表中取出部門(mén)代碼為1001的所有員工,然后我們?nèi)〕?**條數(shù)據(jù)(這里為了簡(jiǎn)便,我們僅僅取出***條,其實(shí)可以用Where取出滿(mǎn)足條件的記錄),然后把名字修改成“李四”,再更新到數(shù)據(jù)庫(kù)中。

這段代碼,LINQ查詢(xún)都干了些什么呢?通過(guò)查詢(xún)從數(shù)據(jù)庫(kù)中取出若干條記錄,放在內(nèi)存中,并且都標(biāo)記為new(未改變)狀態(tài),當(dāng)修改了員工姓名的時(shí)候,被修改的對(duì)象被標(biāo)記為Dirty(已改變)。

在SubmitChanges的時(shí)候,再為內(nèi)存中對(duì)象狀態(tài)為Dirty的記錄自動(dòng)生成SQL語(yǔ)句并執(zhí)行,也就是說(shuō),我們要完成一次數(shù)據(jù)的更新,至少要完成一次查詢(xún)和一次更新。

由于采用了延時(shí)加載(Layze Load)的技術(shù),在以上語(yǔ)句中實(shí)際從數(shù)據(jù)庫(kù)中取出的記錄只有1條,更新的時(shí)候也只更新這一條,因此效率仍然是非常高的,我在測(cè)試的過(guò)程中發(fā)現(xiàn),從250000條數(shù)據(jù)中隨機(jī)抽取一條進(jìn)行更新,實(shí)際的效率和從10條數(shù)據(jù)中隨機(jī)抽取一條進(jìn)行更新幾乎沒(méi)有差別,因?yàn)楸容^更新?tīng)顟B(tài)是在內(nèi)存中進(jìn)行,因此效率是比較高的。下面我們?cè)倏纯磳?shí)際的更新生成了什么樣的SQL語(yǔ)句:

UPDATE [dbo].[Employee] SET [EmployeeName] = @p4 WHERE ([EmployeeId] = @p0) AND ([DepId] = @p1) AND  ([EmployeeName] = @p2) AND ([EmployeeSalary] = @p3)

原來(lái),我們只修改了EmployeeName的字段,生成的SQL語(yǔ)句卻也僅僅是更新了Employee字段。那么,我們?cè)倏纯春竺娴臈l件,為什么會(huì)包含除了主鍵以外的其他條件呢?原來(lái),這也是LINQ查詢(xún)自動(dòng)生成SQL語(yǔ)句的嚴(yán)謹(jǐn)所在,這是為了防止并發(fā)情況下,多個(gè)事務(wù)針對(duì)同一條記錄更新時(shí)發(fā)生錯(cuò)誤,假如A事務(wù)更新了該記錄,則B事務(wù)更新會(huì)失敗。

我們不禁要問(wèn),假如要更新主鍵字段怎么辦?會(huì)不會(huì)錯(cuò)誤的更新到多條記錄呢?答案是肯定的,肯定會(huì)錯(cuò)誤的更新到其他記錄,因此,LINQ中規(guī)定了主鍵字段是不允許更新的,如果確實(shí)要更新,那么就刪除掉該記錄,重新插入新紀(jì)錄。這么嚴(yán)謹(jǐn)?shù)腟QL語(yǔ)句,會(huì)給我們帶來(lái)一些麻煩,我們來(lái)看下面一個(gè)應(yīng)用場(chǎng)景:

如果我們?cè)诒碇性O(shè)有一個(gè)字段用于計(jì)數(shù)器,使用SQL語(yǔ)句是這樣的:

Update CountTable set CountColumn=CountColumn+1 where CountId=@countId

但使用LINQ查詢(xún)生成的Sql語(yǔ)句卻是:

UPDATE [dbo].[CountTable] SET [CountColumn] = @p2 WHERE ([CountId] = @p0) AND ([CountColumn] = @p1)

@p2這個(gè)參數(shù)是計(jì)算好后傳入的,@p1這個(gè)參數(shù)是CountColumn原來(lái)的值。也就是說(shuō),CountColumn+1這個(gè)值不是由數(shù)據(jù)庫(kù)運(yùn)算出來(lái)的,這樣一來(lái),當(dāng)并發(fā)數(shù)很高的時(shí)候,我們往往會(huì)更新失敗。我做了個(gè)測(cè)試,使用多線(xiàn)程模擬多用戶(hù)的情況下進(jìn)行計(jì)數(shù)統(tǒng)計(jì),數(shù)據(jù)庫(kù)中統(tǒng)計(jì)的值比使用靜態(tài)變量保存的值要小,這也就是說(shuō)數(shù)據(jù)庫(kù)更新是存在失敗的情況。

另外,這樣每次的更新,需要完成的操作有查找和更新兩個(gè)步驟,因此對(duì)于效率也有比較大的影響。

感謝各位的閱讀,以上就是“Linq查詢(xún)與性能舉例分析”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Linq查詢(xún)與性能舉例分析這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

網(wǎng)站名稱(chēng):Linq查詢(xún)與性能舉例分析
轉(zhuǎn)載來(lái)于:http://aaarwkj.com/article2/iggpoc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站關(guān)鍵詞優(yōu)化、域名注冊(cè)品牌網(wǎng)站設(shè)計(jì)、移動(dòng)網(wǎng)站建設(shè)、品牌網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

微信小程序開(kāi)發(fā)
97福利影院在线观看| 国产无套内射三级视频| 日韩欧美国产麻豆一区精品| 色偷偷亚洲精品一区二区| 人妻少妇被猛烈进入久久精品| 黄色免费大片在线播放| 四虎在线经典视频播放| 99亚洲综合一区二区三区| 国产在线播放精品视频| 日韩一区二区三区中文字幕| 丁香六月婷婷激情啪啪综合 | 国产二区三区在线播放| 青青草国产成人自拍视频在线观看| 韩国av网址在线观看| 久久综合午夜福利视频| 亚洲欧美日韩一区中文天国| 欧美日韩国产这里只有精品| 欧美日韩国产一下老妇| 国产精品视频一区二区噜| 激情国产白嫩美女在线观看| 国产高清自拍视频免费| 97超碰国产在线观看| 一区二区亚洲免费的视频| 亚洲av激情码国产一区| 亚洲一品道在线观看| 高清免费在线自偷自拍| 国产三级在线播放完整| 国产精品久久久久精品三级中文国| 国产又粗又长又大又长| 青青草av一区二区三区| 国自产偷精品不卡在线| 日本高清一区二区网站| 日韩精品一区三区二区| 亚洲全乱码精品一区二区| av成人综合在线资源站| 国产精品五月婷婷六月丁香| 久久精品国产亚洲熟女| 国产成人免费视频大全| 久久精品国产成人综合| 亚洲国产香蕉视频在线播放| 欧美亚洲国语精品一区二区|