您的位置:首页 > 数据库

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

2013-11-25 16:34 232 查看
写这个文章源于早先对ADO.Net获取数据库元数据上的认识,去年我在阅读ADO.Net Core Reference的时候曾经注意过DataSet的FillSchema的这个方法。这方面,在我之前的随笔中提到过Typed DataSet,而FillSchem与WriteXmlSchema的结合使用可以获得数据库的表结构架构,从而使用相应工具生成强类型的DataSet。但是我记得作者建议在具体应用开发中尽量少用FillSchema这个方法,因为出于性能考虑,其一般只适合作为测试过程中的一个方法。

当时我的理解就是,这是一个获取数据库元数据的一个方便的方法,但是由于其对性能的影响,因此通常应用中比较少用。而在我后面的开发中也未曾有机会接触这个方法。

今年早先1月份的时候看DAAB,注意到其封装的DataCommand对象提供了动态获取存储过程信息的支持:DeriveParameters。当时我的第一印象是,这也是获取数据库的“元数据”,因为之前有过FillSchema对性能影响上的认识,我当时就产生了一个问号:这样做适合吗?自动填充Command对象的Parameter集合,会影响应用程序的性能吗?

就此我也请教过M$的专家,给我的回答是两者机制不同,后者对性能影响不大。

昨日翻倒年初对这个问题疑惑而提的一篇帖子,突然很想进一步找找这两中方法的区别之处,简单了解了一下,以下做个简单的归纳。

DeriveParameters方法

先说简单的一个。DeriveParameters是SqlCommandBuilder类的一个公共方法,提供一个SqlCommannd的参数,该Command对象作为获取到的Parameters的存放容器。其实SqlCommand本身就有一个DeriveParameters的方法,但是它是内部方法,而SqlCommandBuilder.DeriveParameters就是封装了该方法的调用:

1public static void DeriveParameters(SqlCommand command)
2internal void DeriveParameters()
2private 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}

首先,该操作含有一个数据库的Query操作,这里其实是调用DBDataAdapter的SelectCommand的对象,执行一次查询,然后遍历查询返回的所有表,每遍历到一个表的时候,通过该表的信息实例化一个SchemaMapping对象,再有该对象创建为DataSet/DataTable创建架构信息。

这里,DataSet/DataTable是作为参数提供的,整个处理过程,首先必然的需要完成一次查询操作,由于使用IDataReader,所以在查询之后的所有操作期间,连接是保持着的,这一定程度上占用了一些资源(也可以说这些资源还不算太昂贵);其次,实例化一个SchemaMapping对象(该对象是内部类,我在MSDN上没有查到相关介绍性资料),我简单看了一下这个类的代码,在我看来,它的处理过程应该是占据了整个过程蛮大一部分资源的,这方面属于个人见解。

由于我的认识上的有限,也为了保证文章的内容无误导,暂且说到这里。这个方法的进一步讨论希望留给有兴趣的朋友。

总结

以上是我对这两个方法认识方面简单的一个概括,其实从上面的描述,也打消了我原先认为的这两个方法在获取元数据上有本质的差别。个人认为,之所以获取结构性元数据的消耗大,是因为获取逻辑的繁琐以及使用的对象的庞大,而参数信息相对而言完全属于轻量级的东西,所以所谓性能上的差异并非因为获取机制的本质差异引起的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: