分享

代码生成器开发笔记(2)-数据库架构

 quasiceo 2013-03-04

代码生成器开发笔记(2)-数据库架构

分类: Sql Server 2005 217人阅读 评论(0) 收藏 举报

代码生成器开发笔记(2)-数据库架构

程序 2009-06-13 01:30:01 阅读55 评论0   字号: 订阅

  要完成代码生成器,第一个要解决的是完全解析数据库架构。

  对SQL Server当然没什么问题,早在ADO时代就可以通过查询sysobjects之类的系统表来完全得到所需的架构信息,不过这种方式较为烦琐,而且对其它数据库也不一定适用。要支持的四种数据库中,SQL Server是最熟悉的,也是绝对保证不会有问题的,对Access数据库,虽然不太清楚它的架构信息是如何保存的,但ADO时代就可以使用ADOX来获得,ADO.NET当然也应该提供类似的方法,所以也不必担心。而Oracle和MySql只是用过,对其架构就完全不了解了,不过这两个数据库系统当然也会提供让开发者能获得架构信息的方式,所以倒也不用担心不能获得架构信息。

  这里考虑的是不能用查询系统表的方式来获得架构信息,其它三种不同数据库,即使全部提供了类似SQL Server的系统表,但各自存储的方式不同,必然导致代码无法重用,而给四个数据库系统写不同的提取架构信息的方法,那将是一件非常可怕的事情,这绝不是我的第一选择,除非ADO.NET没有提供更好的方法。

  以前从没有仔细研究过ADO.NET,对新技术,我一向是够用就行,从开发角度来讲,只要知道连接、命令等几个对象足矣,这次不同了,必须得深入一下……

  没必要去买书,也没必要去网上漫无目的地搜索,最好的参考当然是MSDN。

  首先从最熟悉的SqlConnection类入手,在MSDN中找到该类的所有方法,逐个研究,很快发现一个方法:GetSchema()——返回数据源的架构信息。而且它是SqlConnection的基类DbConnection中的虚方法(抽象方法?没注意),这就意味着OleDbConnection和OracleConnection也同样可以使用这个方法,至于MySql,虽然还没用C#写过MySql应用程序,但是不必担心,它的C#支持类库,用脚想也知道一定是继承同一个基类。所以只要搞清楚了一个数据库中的GetSchema用法,其它数据库也就迎仞而解了。更重要的是,这是完全面向对象的,代码可以重用。

  通过GetSchema,在MSDN中找到了“检索数据库架构信息”一章,终于搞清了在ADO.NET中获得数据库架构信息的方法,而且正如我所想,这是完全面向对象的,只需用简单工厂模式创建不同的Connection对象即可完全实现代码重用,大大简化了代码量。

  ADO.NET 2.0 允许提供程序编写者公开 5 种不同类型的元数据。这些主要的元数据 — “元数据集合”或“类别” — 在 System.Data.Common.DbMetaDataCollectionNames 类中被枚举出来。 

MetaDataCollections — 可用元数据集合的列表。 
 
Restrictions — 对于每个元数据集合,存在一批可以用于限制被请求的架构信息范围的限定符。 
 
DataSourceInformation — 关于数据提供程序引用的数据库实例的信息。 
 
DataTypes — 一组关于数据库支持的每个数据类型的信息。 
 
ReservedWords — 适用于该种数据库查询语言的保留字。通常“查询语言”等同于一种 SQL 的方言。 

Restrictions
Restrictions 可以用来限制返回元数据的数量。实际上也就是对返回的架构信息进行过滤。使用时,根据不同的架构来设置Restrictions的值,例如在查询数据库中所有用户表时,可以使用以下代码:

                using (DbConnection conn = DbFactory.CreateConnection(type, connectionString))
                {
                    conn.Open();
                    string[] restrictions = new string[4];
                    restrictions[3] = "BASE TABLE";    //SQL Server中用户表的类型名称
                    DataTable dt = conn.GetSchema("Tables",restrictions );  //查询数据提供程序的表视图
                    foreach (DataRow row in dt.Rows)
                    {
                        Table table = new Table(row["TABLE_NAME"].ToString());
                        tables.Add(table);  //添加到自定义的表集合中
                    }

  conn.GetSchema("Tables")的返回值是一个包含4个字段的结果集,其中第4个字段是表类型,将数据中的第4个元素的值设为"BASE TABLE",其含义等同于SQL语句中的WHERE table_type='BASE TABLE'。
  对无需过滤的字段,需要将restrictions数组中的相应元素设为null而不是空字符串(Empty),设置为空字符串的同义SQL语句为WHERE 字段名=''。

  Tables是架构集名称,具体解释可参见MSDN帮助,类似的架构名还有Columns、Views等,通过GetSchema(架构集名称,Restrictions)可以获得数据库架构的完整信息。

  然而架构集合是ADO.NET预定义好的,我们只能获得它定义好的架构信息,这些预定义的架构集合中并没有包含所有我们想要的东西,例如主键字段、主外键表等,要想获得这些信息,我们还得想办法。

  MSDN上的一篇文章谈到了这个问题。http://msdn.microsoft.com/zh-cn/library/ms379543(VS.80).aspx

  也就是说,我们可以通过自定义元数据的方式来获得我们想要的数据库架构信息。通过在配置文件中加入相应说明来告诉ADO.NET。

<?xml version="1.0" encoding="utf-8" ?> 
      <configuration> 
      <system.data.sqlclient> 
      <settings> 
      <add name="MetaDataXml" value="SQLBrokerAware.xml">
      </add> 
      </settings> 
      </system.data.sqlclient> 
      </configuration> 

例如这样一个配置文件,告诉ADO.NET,当使用SQL Server数据提供程序查询架构信息时,使用SQLBrokerAware.xml文件中的定义来进行查询。这份文件必须放在.NET框架安装目录下的CONFIG目录中。通常,.NET框架的典型安装目录是Windows/Microsoft.net/Frameword/版本号。可以通过检查注册表HKEY_LOCAL_MACHINE/Software/Micorsoft/.NetFrameword/InstallRoot的值来确定安装目录,并且在程序中使用Environment.Version检查.NET框架的版本号,最终确定元数据描述文件应该放在哪里。

  有了这个文件,我们可以对任意一个支持ADO.NET的数据库查询我们想知道的架构信息。以下是关键部分的描述:

  <MetaDataCollections>
    <CollectionName>Tables</CollectionName>
    <NumberOfRestrictions>4</NumberOfRestrictions>
    <NumberOfIdentifierParts>3</NumberOfIdentifierParts>
    <PopulationMechanism>SQLCommand</PopulationMechanism>
    <PopulationString>select table_catalog, table_schema, table_name, table_type from information_schema.tables where table_catalog = {0} and table_schema = {1} and table_name = {2} and table_type = {3}</PopulationString>
  </MetaDataCollections>

这里描述了如何获得数据库中表的信息。

MetaDataCollections——元数据集合,每一个集合都必须放在这个标签内

CollectionName——集合名称,GetSchema方法的第一个参数

NumberOfRestrictions——允许的限制数,决定了代码中定义的restrictions数组的大小

NumberOfIdentifierParts——必须的限制数,此值不为零时,restrictions数组不能为null的元素的个数。

PopulationMechanism——向数据库发出命令的DbCommand实例。根据不同的数据库,这个值应该是                                       SqlCommand、OracleCommand等。

PopulationString——用来替换“基查询”的SQL语句。显然修改这个值,我们可以得到我们想要的任何信息。

  关于元数据描述文件更多定义,可以使用托管代码反汇编工具ILDasm反编译system.data.sqlclient.dll文件,查看里面的System.Data.SqlClient.SqlMetaData.xml文件,这个文件就是ADO.NET预定义好的元数据描述文件。

  具体做法是:进入VS命令环境,切换到.NET框架安装目录下,运行以下命令:ildasm System.Data.dll /out:system.data/dummy.il,将会在当前目录下生成system.data目录,并将反编译后生成的文件放在里面。这里的system.data是我自定义的目录名,你也可以换成其它名称,目录不需要预先存在,ildasm会自动创建。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多