天天看點

架構設計之ADO.NET Command的ExecuteScalar誤用情景及底層解說

最近下載下傳了點資料,學了學Android,發現Android入門還算簡單,從.NET過渡到Android,也就三七十一天的事。

大夥有空也可以學學。。。

好了,言歸正文,那日,有網友發了一個他們公司的資料層架構的DLL,讓我審視(Reflector檢視如下):

架構設計之ADO.NET Command的ExecuteScalar誤用情景及底層解說

炸一看架構,支援的資料庫種類繁多,看來寫架構的人涉及面還挺廣的。

往裡一看,比較悲催,有廣度而無深度,另外資料庫種類的dll需要提前引用,那是相當浩大的資料庫工程:

架構設計之ADO.NET Command的ExecuteScalar誤用情景及底層解說

架構具體就不過多點評了,在不經意思間,本人看到有一個閃光點,覺的可以和大夥分享分享:

1:檢測某列是否存在:

架構設計之ADO.NET Command的ExecuteScalar誤用情景及底層解說

2:檢測某表是否存在:

架構設計之ADO.NET Command的ExecuteScalar誤用情景及底層解說

這是一條判斷某字段列和某表是否存在的方法,此處用了select X from table的方式,然後調用了GetSingle(sql)。

而 GetSingle的代碼如下:

架構設計之ADO.NET Command的ExecuteScalar誤用情景及底層解說

代碼裡,關于ADO.net的相關對象沒提升到全局變量以重用這個不是講的重點,就先忽略先,今天分享的知識點是ExecuteScalar:

對于ADO.NET的Command指令,有三個方法,大夥很熟悉:

1:ExecuteDataReader,傳回資料流,用于清單讀取。

2:ExecuteScalar,傳回首行首列。

3:ExecuteNonQuery,傳回首影響的行。

解說:

如果我們從語義上講,用ExecuteScalar執行一條select * from table,隻傳回首行首列,看似還過的去,然實際不然。

實際上,後面的ExecuteScalar,或是ExecuteNonQuery,内部都是調用的ExecuteDataReader來處理的,見如下代碼即知:

架構設計之ADO.NET Command的ExecuteScalar誤用情景及底層解說

說明分析:

微軟并沒有什麼特殊照顧,是以原來的語句,仍會到資料庫裡,按語句的要求,并找出全部滿足條件的資料流進行傳回。

當然,值的欣慰的是,DataReader是一個流資料傳輸,它并不是一次性傳輸所有資料,而是部分段傳輸。

中間我做了一個小測試,大體過程是這樣的:

使用DataReader去讀取資料傳回一個SqlDataReader,然後斷點,接着把資料庫服務給停了,然後繼續調試,發現資料還可以正常讀取。

說明還未讀取之時,部分資料就先通過管道把資料從資料庫傳輸到程式的記憶體中了,後來按F5繼續,讀取後面就會抛程序管道已關閉的錯誤。

總結:

本文說明兩點使用方法上的兩點:

1: 本來是Top 1 的語句,結果變成Select *,這兩條語句在資料庫端執行,性能的差異不說大夥也懂了。

2: ExecuteScalar雖然是傳回首行首列,但實際傳回的是個DataReader,如果你查詢的是清單,實際上記憶體傳輸了清單,隻是最終你程式讀取了清單中的第一個位元組。

當然了,由于流的傳輸,并不一次性傳輸全部,隻是部分段傳輸,是以性能的損失并不是太明顯。

要寫好底層架構,任重而道遠,望大夥再接再勵。

<b>     本文轉自cyq1162 51CTO部落格,原文連結:http://blog.51cto.com/cyq1162/1252193</b><b>,如需轉載請自行聯系原作者</b>

<b></b>