日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

浅析ado.net获取数据库元数据信息

發(fā)布時間:2023/11/27 生活经验 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅析ado.net获取数据库元数据信息 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

寫這個文章源于早先對ADO.Net獲取數(shù)據(jù)庫元數(shù)據(jù)上的認識,去年我在閱讀ADO.Net Core Reference的時候曾經(jīng)注意過DataSet的FillSchema的這個方法。這方面,在我之前的隨筆中提到過Typed DataSet,而FillSchem與WriteXmlSchema的結(jié)合使用可以獲得數(shù)據(jù)庫的表結(jié)構(gòu)架構(gòu),從而使用相應工具生成強類型的DataSet。但是我記得作者建議在具體應用開發(fā)中盡量少用FillSchema這個方法,因為出于性能考慮,其一般只適合作為測試過程中的一個方法。

當時我的理解就是,這是一個獲取數(shù)據(jù)庫元數(shù)據(jù)的一個方便的方法,但是由于其對性能的影響,因此通常應用中比較少用。而在我后面的開發(fā)中也未曾有機會接觸這個方法。

今年早先1月份的時候看DAAB,注意到其封裝的DataCommand對象提供了動態(tài)獲取存儲過程信息的支持:DeriveParameters。當時我的第一印象是,這也是獲取數(shù)據(jù)庫的“元數(shù)據(jù)”,因為之前有過FillSchema對性能影響上的認識,我當時就產(chǎn)生了一個問號:這樣做適合嗎?自動填充Command對象的Parameter集合,會影響應用程序的性能嗎?

就此我也請教過M$的專家,給我的回答是兩者機制不同,后者對性能影響不大。

昨日翻倒年初對這個問題疑惑而提的一篇帖子,突然很想進一步找找這兩中方法的區(qū)別之處,簡單了解了一下,以下做個簡單的歸納。

DeriveParameters方法

先說簡單的一個。DeriveParameters是SqlCommandBuilder類的一個公共方法,提供一個SqlCommannd的參數(shù),該Command對象作為獲取到的Parameters的存放容器。其實SqlCommand本身就有一個DeriveParameters的方法,但是它是內(nèi)部方法,而SqlCommandBuilder.DeriveParameters就是封裝了該方法的調(diào)用:

1public?static?void?DeriveParameters(SqlCommand?command)
2{
3??????SqlConnection.SqlClientPermission.Demand();
4??????if?(command?==?null)
5??????{
6????????????//?throw?an?exception
7??????}

8??????command.DeriveParameters();
9}

來看一下SqlCommand的DeriveParameters方法:
?1internal?void?DeriveParameters()
?2{
?3??????
?4??????//?Validate?command?type(is?storedprocedure?)?and?command?info
?5??????
?6
?7??????//?Retrieve?command?text?detail
?8??????string[]?txtCommand?=?ADP.ParseProcedureName(this.CommandText);
?9
10??????SqlCommand?cmdDeriveCommand?=?null;
11
12??????this.cmdText?=?"sp_procedure_params_rowset";
13??????if?(txtCommand[1]?!=?null)
14??????{
15????????????this.cmdText?=?"["?+?txtCommand[1]?+?"].."?+?this.cmdText;
16
17????????????if?(txtCommand[0]?!=?null)
18????????????{
19??????????????????this.cmdText?=?txtCommand[0]?+?"."?+?this.cmdText;
20????????????}

21
22????????????cmdDeriveCommand?=?new?SqlCommand(this.cmdText,?this.Connection);
23??????}

24??????else
25??????{
26????????????cmdDeriveCommand?=?new?SqlCommand(this.cmdText,?this.Connection);
27??????}

28??????cmdDeriveCommand.CommandType?=?CommandType.StoredProcedure;
29??????cmdDeriveCommand.Parameters.Add(new?SqlParameter("@procedure_name",?SqlDbType.NVarChar,?0xff));
30??????cmdDeriveCommand.Parameters[0].Value?=?txtCommand[3];
31??????ArrayList?parms?=?new?ArrayList();
32??????try
33??????{
34????????????try
35????????????{
36??????????????????using?(SqlDataReader?drParam?=?cmdDeriveCommand.ExecuteReader())
37??????????????????{
38????????????????????????SqlParameter?parameter?=?null;
39????????????????????????while?(drParam.Read())
40????????????????????????{
41??????????????????????????????parameter?=?new?SqlParameter();
42??????????????????????????????parameter.ParameterName?=?(string)?drParam["PARAMETER_NAME"];
43??????????????????????????????parameter.SqlDbType?=?MetaType.GetSqlDbTypeFromOleDbType((short)?drParam["DATA_TYPE"],?(string)?drParam["TYPE_NAME"]);
44??????????????????????????????object?len?=?drParam["CHARACTER_MAXIMUM_LENGTH"];
45??????????????????????????????if?(len?is?int)
46??????????????????????????????{
47????????????????????????????????????parameter.Size?=?(int)?len;
48??????????????????????????????}

49??????????????????????????????parameter.Direction?=?this.ParameterDirectionFromOleDbDirection((short)?drParam["PARAMETER_TYPE"]);
50??????????????????????????????if?(parameter.SqlDbType?==?SqlDbType.Decimal)
51??????????????????????????????{
52????????????????????????????????????parameter.Scale?=?(byte)?(((short)?drParam["NUMERIC_SCALE"])?&?0xff);
53????????????????????????????????????parameter.Precision?=?(byte)?(((short)?drParam["NUMERIC_PRECISION"])?&?0xff);
54??????????????????????????????}

55??????????????????????????????parms.Add(parameter);
56????????????????????????}

57??????????????????}

58????????????}

59????????????finally
60????????????{
61??????????????????cmdDeriveCommand.Connection?=?null;
62????????????}

63??????}

64??????catch
65??????{
66????????????throw;
67??????}

68
69??????if?(params.Count?==?0)
70??????{
71????????????//?throw?an?exception?that?current?storedprocedure?does?not?exist
72??????}

73??????
74??????this.Parameters.Clear();
75??????foreach?(object?parm?in?parms)
76??????{
77????????????this._parameters.Add(parm);
78??????}

79}

ADP.ParseProcedureName其實就是獲取存儲過程命令的細節(jié)信息,有興趣的可以反編譯來看看。

縱觀整個方法,有效性驗證-〉獲取命令字符串-〉執(zhí)行查詢-〉填充參數(shù)列表-〉返回。應該是非常簡潔明朗的,最多也就是在數(shù)據(jù)庫Query的階段需要有一個來回,其他操作根本就談不上有什么復雜度,而且也不存在大數(shù)據(jù)的對象,對性能的損耗談不上多巨大。

下面來看看FillSchema的處理過程

FillSchema方法

這個部分因為代碼比較多,所以我就抽關(guān)鍵的部分來看一下。

首先,FillSchema是DataAdapter類定義的一個方法,而具體實現(xiàn)則是在該類的子類DBDataAdapter中完成的(SqlDataAdapter繼承于DBDataAdapter)。

通過反編譯,可以發(fā)現(xiàn)FillSchema的關(guān)鍵處理步驟是在其調(diào)用私有方法FillSchemaFromCommand來完成的。簡單看一下該方法體的內(nèi)容:

?1private?DataTable[]?FillSchemaFromCommand(object?data,?SchemaType?schemaType,?IDbCommand?command,?string?srcTable,?CommandBehavior?behavior)
?2{
?3??????IDbConnection?connection?=?DbDataAdapter.GetConnection(command,?"FillSchema");
?4??????ConnectionState?state?=?ConnectionState.Open;
?5??????DataTable[]?arrTables?=?new?DataTable[0];
?6??????try
?7??????{
?8????????????try
?9????????????{
10??????????????????DbDataAdapter.QuietOpen(connection,?out?state);
11??????????????????using?(IDataReader?reader?=?command.ExecuteReader((behavior?|?CommandBehavior.SchemaOnly)?|?CommandBehavior.KeyInfo))
12??????????????????{
13????????????????????????if?(reader?==?null)
14????????????????????????{
15??????????????????????????????return?arrTables;
16????????????????????????}

17????????????????????????int?tblIndex?=?0;
18????????????????????????while?(true)
19????????????????????????{
20??????????????????????????????if?(0?<?reader.FieldCount)
21??????????????????????????????{
22????????????????????????????????????try
23????????????????????????????????????{
24??????????????????????????????????????????string?txtTableName?=?null;
25??????????????????????????????????????????SchemaMapping?mapping?=?new?SchemaMapping(this,?reader,?true);
26??????????????????????????????????????????if?(data?is?DataTable)
27??????????????????????????????????????????{
28????????????????????????????????????????????????mapping.DataTable?=?(DataTable)?data;
29??????????????????????????????????????????}

30??????????????????????????????????????????else
31??????????????????????????????????????????{
32????????????????????????????????????????????????mapping.DataSet?=?(DataSet)?data;
33????????????????????????????????????????????????txtTableName?=?DbDataAdapter.GetSourceTableName(srcTable,?tblIndex);
34??????????????????????????????????????????}

35??????????????????????????????????????????mapping.SetupSchema(schemaType,?txtTableName,?false,?null,?null);
36??????????????????????????????????????????DataTable?currentTable?=?mapping.DataTable;
37??????????????????????????????????????????if?(currentTable?!=?null)
38??????????????????????????????????????????{
39????????????????????????????????????????????????arrTables?=?DbDataAdapter.AddDataTableToArray(arrTables,?currentTable);
40??????????????????????????????????????????}

41????????????????????????????????????}

42????????????????????????????????????finally
43????????????????????????????????????{
44??????????????????????????????????????????tblIndex++;
45????????????????????????????????????}

46??????????????????????????????}

47??????????????????????????????if?(!reader.NextResult())
48??????????????????????????????{
49????????????????????????????????????return?arrTables;
50??????????????????????????????}

51????????????????????????}

52??????????????????}

53????????????}

54????????????finally
55????????????{
56??????????????????DbDataAdapter.QuietClose(connection,?state);
57????????????}

58??????}

59??????catch
60??????{
61????????????throw;
62??????}

63??????return?arrTables;
64}


首先,該操作含有一個數(shù)據(jù)庫的Query操作,這里其實是調(diào)用DBDataAdapter的SelectCommand的對象,執(zhí)行一次查詢,然后遍歷查詢返回的所有表,每遍歷到一個表的時候,通過該表的信息實例化一個SchemaMapping對象,再有該對象創(chuàng)建為DataSet/DataTable創(chuàng)建架構(gòu)信息。

這里,DataSet/DataTable是作為參數(shù)提供的,整個處理過程,首先必然的需要完成一次查詢操作,由于使用IDataReader,所以在查詢之后的所有操作期間,連接是保持著的,這一定程度上占用了一些資源(也可以說這些資源還不算太昂貴);其次,實例化一個SchemaMapping對象(該對象是內(nèi)部類,我在MSDN上沒有查到相關(guān)介紹性資料),我簡單看了一下這個類的代碼,在我看來,它的處理過程應該是占據(jù)了整個過程蠻大一部分資源的,這方面屬于個人見解。

由于我的認識上的有限,也為了保證文章的內(nèi)容無誤導,暫且說到這里。這個方法的進一步討論希望留給有興趣的朋友。

總結(jié)

以上是我對這兩個方法認識方面簡單的一個概括,其實從上面的描述,也打消了我原先認為的這兩個方法在獲取元數(shù)據(jù)上有本質(zhì)的差別。個人認為,之所以獲取結(jié)構(gòu)性元數(shù)據(jù)的消耗大,是因為獲取邏輯的繁瑣以及使用的對象的龐大,而參數(shù)信息相對而言完全屬于輕量級的東西,所以所謂性能上的差異并非因為獲取機制的本質(zhì)差異引起的。

?

總結(jié)

以上是生活随笔為你收集整理的浅析ado.net获取数据库元数据信息的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。