1

我想在网格视图中列出 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 查询窗格中,这工作得很好。但是,当我通过 .NET 中的 OleDbCommand 对象运行查询时,尽管查询生成了一个结果集,但我得到了一行包含 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());

错误信息是:

System.InvalidOperationException 未处理。

提供程序无法确定 Int32 值。例如,行刚刚创建,Int32 列的默认值不可用,消费者尚未设置新的 Int32 值。源="系统.数据"

所以我的解决方法是制作一个 TEMP 表并从中读取(或为该列设置一个默认值......这克服了错误,但仍将流氓表包含在结果集中)。

这里发生了什么?MSysNavPaneGroupCategories 甚至不应该进入结果集。

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

这个 url说 MSysNavPaneGroupCategories 是三个系统表之一

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

.. 在 Access 2007 中。

这个微软网址

导航窗格是 Microsoft Office Access 2007 中的新功能,是一个中心位置,您可以从中轻松查看和访问所有数据库对象(数据库对象:Access 数据库包含表、查询、表单、报表、页面、宏、和模块。Access 项目包含窗体、报表、页面、宏和模块等对象。)、运行报表或直接在表中输入数据。

...在 Access 2007 中。

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

4

1 回答 1

1

Jet 的本机数据访问库 DAO 提供了一个 TableDefs 集合,它应该可以很容易地获取记录计数并将数据插入到您的网格中。像这样的东西可以在 VBA 中完成工作(这可以让你开始——它是空气代码):

  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 案例转换为 CASE ELSE,并使用 SELECT COUNT(* )。

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

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

但是,再一次,我必须说这是最好的方法,甚至是好方法。我只是把它作为思考的食物扔在那里,主要是因为我喜欢利用 RecordCount 属性(我相信它是 SELECT COUNT(*) FROM 表返回的内容,但更快,因为你没有有打开记录集的开销),您可以使用它。

于 2010-01-08T05:45:08.503 回答