代码之家  ›  专栏  ›  技术社区  ›  rism

为什么“MSysNavPaneGroupCategories”出现在中。NET OLEDB提供对Access 2K db的查询,条件为:WHERE MSysObjects。名字不像“MSys*”

  •  1
  • rism  · 技术社区  · 15 年前

    我想在MS Access数据库的网格视图中列出所有表及其行数。我使用的查询如下:

    SELECT MSysObjects.Name, CLng(DCount('*',[name])) AS RecordCount
        FROM MSysObjects WHERE (((MSysObjects.Type)=1)
        AND (MSysObjects.Name NOT LIKE 'MSys*')) 
        ORDER BY MSysObjects.Name;
    

    在MS Access查询窗格中,这一切正常。但当我通过中的OleDbCommand对象运行查询时。NET,尽管查询生成了一个结果集,但我得到了一行数据,其中包含MSysNavPaneGroupCategories。当我试图:

     DataRow row = null;
     do
     {
        row = dt.NewRow();
        row["TableName"] = (string)dr["Name"];
        row["RecordCount"] = (int)dr["RecordCount"]; // Fails here when dr["Name"]==MSysNavPaneGroupCategories
        dt.Rows.Add(row);
     } while (dr.Read());
    

    错误消息是:

    系统无效手术除外 未经处理。

    提供商无法确定 Int32值。例如,争吵是 刚刚创建,默认为 Int32列不可用,并且 消费者尚未设定新的价格 Int32值。Source=“System.Data”

    所以我的解决方法是创建一个临时表,并从中读取数据(或者为列设置一个默认值……这克服了错误,但仍然在结果集中包含rogue表)。

    这是怎么回事?MSysNavPaneGroupCategories甚至不应该进入结果集。

    MSysNavPaneGroupCategories系统表中没有太多信息。

    This url MSysNavPaneGroupCategories表示,MSysNavPaneGroupCategories是

    定义文档中的所有内容 导航窗格。

    …2007年。

    This Microsoft url

    导航窗格,在Microsoft中新增 OfficeAccess2007是一个 您可以轻松 查看并访问所有数据库 对象(数据库对象:访问 数据库包含以下对象: 表格、查询、表格、报告、, 页面、宏和模块。通道 项目包含以下对象: 表单、报告、页面、宏和 模块。),运行报告或输入数据 直接放在桌子上。

    ... 在Access 2007中。

    当这个表是Access 2007功能时,为什么它会出现在Access 2K数据库表列表中?为什么它会出现在一个与条件不匹配的查询中?

    1 回复  |  直到 8 年前
        1
  •  1
  •   David-W-Fenton    15 年前

    Jet的原生数据访问库DAO提供了一个TableDefs集合,可以轻松获取记录计数并将数据插入网格。类似的东西可以在VBA中完成这项工作(这可以让你开始——它是air代码):

      Dim db As DAO.Database
      Dim tdf As DAO.TableDef
      Dim strTableName As String
      Dim strConnect As String
      Dim strType As String 
      Dim strDatabase As String
      Dim strConnectType As String
    
      Set db = DBEngine.OpenDatabase("[path/filename of MDB/ACCDB file]")
      For Each tdf In db.TableDefs
        If (tdf.Attributes And dbSystemObject) = 0 Then ' examine only non-system tables
           strTableName = tdf.Name
           If Len(tdf.Connect) > 0 Then
              strConnect = tdf.Connect
              strDatabase = Split(strConnect, "=")(1)
           End If
           If (tdf.Attributes And dbAttachedTable) Then ' linked Jet/ACE table
              Debug.Print strTableName & ": " & DBEngine.OpenDatabase(strDatabase).TableDefs(strTableName).RecordCount
           ElseIf (tdf.Attributes And dbAttachedODBC) Then ' ODBC table
              Debug.Print strTableName & ": " & DBEngine(0)(0).OpenRecordset("SELECT COUNT(*) FROM " & strTableName)(0)
           Else ' local table
              Debug.Print strTableName & ": " & tdf.RecordCount
           End If
        End If
      Next tdf
      Set tdf = Nothing
      db.Close
      Set db = Nothing
    

    上面的代码只处理Jet/ACE和ODBC数据源,不处理Excel电子表格、文本/CSV或DBF文件,但如果需要这些文件,可以将ODBC大小写转换为其他大小写,并使用SELECT COUNT(*)处理所有这些数据源。

    通过首先遍历所有非系统tableDef并获得所有唯一后端的列表,显然也可以优化上述内容,因此您只需为每个Jet/ACE后端执行一次OpenDatabase。然后,还可以使用单个ODBC连接到ODBC数据源,或者将ODBC连接字符串转换为ADO,并在需要时获取更多信息。

    现在,这是否是一个好主意取决于具体情况。所有TableDef都有一个RecordCount属性,Jet/ACE将该属性作为表元数据的一部分进行维护。但它只能在本地表上立即访问——也就是说,它不适用于链接表。这就是为什么在打开后端数据库的基础上检查附加的Jet/ACE表。

    但是,再一次,我必须说这是最好的方法,甚至是一个好方法。我只是把它作为思考的对象,主要是因为我喜欢利用RecordCount属性(我相信,它是通过SELECT COUNT(*)从表中返回的属性,但速度更快,因为您没有打开记录集的开销),您可以使用它。