MS Access:容器对象表单属于什么对象模型?

时间:2018-12-30 08:24:45

标签: object ms-access dao

据我了解,DAO和ADO对象模型仅具有用于数据访问的对象,例如表和查询,而没有与数据表示有关的对象,例如表单和报表。

与此相符,MS documentation of DAO objects中的一长串对象不包括表格或报告。

另外,MS documentation on the DAO container object表示“下表列出了Microsoft Access数据库引擎定义的每个Container对象的名称”,并且该表列出了三个对象:数据库,表和关系。

但是,当我在Access 2007 VBA中运行以下例程时:

Sub ListDocuments()

Dim oDB As DAO.Database: Set oDB = CurrentDb()
Dim oContainer As DAO.Container

For Each oContainer In oDB.Containers
    Debug.Print oContainer.Name
  Next oContainer

End Sub

我得到以下输出:

DataAccessPages
Databases
Forms
Modules
Relationships
Reports
Scripts
SysRel
Tables

此输出有两个问题:

  • 次要问题:它具有一个名为“ Relationships”而不是“ Relations”的容器对象。这是否表示上面引用的容器对象文档列表中有错字?
  • 更糟糕的问题。 DAO容器对象的列表包括一个称为“窗体”的对象。请注意,这与Access对象模型中具有相同名称的对象不同。 MS documentation on the Access object Forms说,它仅包含打开的表单。该页面说,包含封闭表单的Access对象是AllForms。在具有当前关闭的一种形式的Access文件中,在“立即窗口”中,? Forms.Count = 0,但是? CurrentDb().Containers("Forms").Documents.Count = 1。因此,这两个都称为“表单”的东西是不同的东西。

此容器对象Forms似乎在任何地方都没有记录。它的存在似乎与上面引用的陈述相矛盾,即Access仅定义了三个容器对象。而且,由于它在DAO对象容器中,因此似乎也与DAO不包含表单和报表对象的想法相矛盾。

所以我的问题是,此容器对象表单来自何处?它属于什么对象模型?如果您知道答案,则可以链接到该文档的一些文档。

4 个答案:

答案 0 :(得分:1)

如果您真的想掌握Access编程的详细信息,其他答案和联机文档都包含值得理解的有用信息。但是,它们通常排除假定的或遗忘的关键细节。在自己直接回答您的问题之前,请考虑以下几点:

    从技术上讲,“对象”模型是单词的错误选择,因为更恰当的术语是类模型。通常,对象是类的内存实例。在运行时,确实存在一个实际对象的层次结构,但是有时引用不引用特定实例(即对象)而是引用整个类很有用。我通常会非常小心地使用术语,但是(尤其是在参考其中一些较旧的模型时)(坦率地说)文档中使用的名称和术语是草率的。这是所有失败术语的免责声明。我会尽力弄清楚区别对于理解至关重要。
  • 与Access相关的各种对象模型中存在冗余。某些冗余可能有充分的理由,但是至少某些冗余可能没有没有的充分理由(至少没有发布的理由)。而是各个组件的某些部分是随着时间推移而发展起来的成熟产品的结果。需要在不同的层次上公开不同的信息,而不仅仅是使整个模型开放,可访问且一致,而是采用“按需”范式进行设计。
    • 冗余同时存在
        名称中的
      • :具有相同或相似名称的不同类并不相同,但是可以提供不同的方法和属性集来操纵相同的基础实体。集合名称和枚举名称也是如此。有时它们甚至不提供相同的基础实体,尽管它们可能提供类似的功能(例如ADO.Recordset和DAO.Recordset)
      • 可用性:一些相同的对象通过不同的父对象/容器对象的不同集合和属性公开。

  

它具有一个名为“ Relationships”而不是“ Relations”的容器对象。这是否表示上面引用的容器对象的文档清单中有错字?

是的,“关系”和“关系”之间的任何差异只是一个错误,可能没有更深的含义。

  

此容器对象表单来自何处?

这只是猜测,至少是对直接答案的尝试:

提供容器对象作为发现相关对象的向后参考。当MS Access通过DAO创建/加载数据库时,显然会出于自身目的添加其他Container对象。 DAO提供了一个通用的Containers集合,并允许其他对象添加到其中。

尽管DAO的目的只是简单地访问和表示数据本身,但显然MS认为提供一种通过DAO对象模型发布(也称为公开)相关对象的方法很有用。我认为它就像许多对象的Parent属性一样。没有这样的Parent属性,通常就没有内置的方法来确定对象与其源的关系。同样,在复杂的应用程序中,如果没有容器集合,可能没有其他方法可以确定数据库的各种详细信息。 Albert D. Kallal已经强调了DAO与Container对象之间不需要任何特殊的连接。也许Container类和对象确实没有任何有意义的关系,但是MS显然出于某种原因决定将其附加到DAO对象模型上,因此我发现缺少Kallal先生的解释。 Access仍然是具有隐藏方法的专有产品,MS不会发布所有API和类的详细信息。老实说,我不相信这是武断的-即使没有共享,MS也有其原因。

  

它属于什么对象模型?

从文档中描述的内容以及在 VBA对象浏览器中探索细节,并使用诸如TypeName之类的某些VBA方法,看来Containers集合和Container对象确实是DAO对象模型的一部分。但是,容器对象(和相关的文档对象)本身可以引用和/或保存DAO对象模型之外的对象。严格来说,访问表单的概念不在DAO之外。表单的实际类和对象是Access对象模型的一部分。


再进一步一点,各种集合不仅是“开放形式”还是“所有形式”。尽管它们都返回称为“表单”的概念实体,但它们甚至都没有返回相同类型的运行时对象。 CurrentDB.Database.Containers(FormContainerIndex)集合返回Container个对象和Document个对象(其中FormContainerIndex可以等于2,也可以不等于2)。 Application.CurrentProject.AllForms集合返回AccessObject的实例。 Application.Forms集合返回具有特定表单类类型的实际表单对象。

我认为这是一个很好的问题。问题中的文档链接揭示了这种混淆的复杂性,因为在Access上下文中各种概念都融合在一起了。 MS文档的一棵树清楚地表明DAO和ADO是与Access截然不同且分开的,但是另一文档分支将相同的对象放到了相关的数据访问概念列表中。

答案 1 :(得分:0)

它来自:

Microsoft Access

您可以轻松地检查以下内容:

? Forms.Parent.Name
Microsoft Access

这包含所有打开或不打开的表单:

Application.CurrentProject.AllForms

当前数据库引用该容器。这些将返回相同的计数:

? CurrentDb.Containers(acForm).Documents.Count
? Application.CurrentProject.AllForms.Count
在您引用的文档中,

CurrentDb (或任何其他 DAO.Database 对象)可能是DAO所在的地方。

答案 2 :(得分:0)

这里没有太多要写的东西。

Access有一些“容器”对象。我们可以在这些容器中存储图片,PDF文档或其他内容。

我们甚至可以将说关系图存储在那些容器中。 (哦,等等–他们做到了!!!)

容器就是这样-Access应用程序中的一些容器。

因此,它们几乎可以是Access应用程序设计人员想要存储在容器中的任何东西。

我的意思是,确实,这与表格没有太大不同。该表可能有发票,或者说有一些客户

然后推断DAO具有“客户”对象或“发票”对象作为DAO对象模型的一部分,在这里毫无意义。

容器“对象”仅是-事物的容器。它们与DAO对象模型无关。

“容器”是Access系统(不是DAO)提供的对象列表。

DAO对象模型没有“容器”方法或“容器”属性。

坦白地说,Access中使用的“本机”数据库引擎是JET(现在称为ACE)。公平地说,由于访问数据库引擎与DAO对象模型非常紧密地联系在一起,因此可以肯定地说,Access(开发人员工具)与DAO紧密联系而与ADO紧密联系。

虽然您最自由地使用DAO或ADO从JET / ACE引擎获取数据,但DAO无疑是这里的首选。

此首选项的“主要原因”是DAO与JET / ACE数据库引擎非常紧密地联系在一起。 Access最初是围绕JET + dao库代码构建的,因此其根源与DAO对象模型更加紧密。

但是,如果要从SQL Server获取数据,那么很长一段时间以来,大多数开发人员都更喜欢ADO对象模型。如果说使用SQL Server或说MySQL或Oracle作为后端数据库(使用MS-access作为前端),则使用ADO有许多优点。

使用ADO的“主要”优势是ADO使用的SQL与“行业”标准使用的SQL语法“更接近”(ansi-92)。因此,如果您使用SQL Server,或者说使用Oracle作为后端,则使用ADO编写的SQL可以正常运行(通常)。 (而且您可能可以在两个数据库之间切换,而不必更改使用的sql语法。)

对于DAO,您正在使用Access(喷射)SQL语法,或者更好的说是JET / ACE语法。当您使用ADO但仍使用JET / ACE引擎时,可以使用sql ansi-92语法。结果是您的sql语法将更加匹配SQL Server上使用的语法,或者说oracle。

对于访问+ JET / ACE应用程序,推荐的标准选择是使用DAO。 (18年前,Microsoft在Access 2000中将“默认”对象模型更改为ADO。开发人员在某种程度上进行了“反叛”,在Access 2003中,他们将DAO作为默认值返回。(您至今,STILL仍可以选择对象模型,或者更糟的是将两者“混合” –不要去那里!!)所以Microsoft并没有强制进行更改,但是“默认”设置是ADO –但是我们总是总是将引用更改回DAO并保留像往常一样编写代码。

因此,多年来,微软一直在推动所有人使用ADO,包括非常流行的MS-access系统。

但是,我们大多数开发人员都忽略了Microsoft的建议,并在构建本机访问应用程序时继续使用DAO。如前所述,在相当长的一段时间内,DAO是默认的对象模型。由于DAO被“弃用”,因此Access团队采用了DAO对象和代码库,现在他们拥有了该库。 (之前,它只是所有开发人员都可以使用的标准Microsoft库)。因此对于V6,vb.net等,他们倾向于使用ADO。

因此,您现在可以“读取”已弃用DAO,但是Access使用的是ACE数据库引擎附带的更新和较新版本。 (因此,当DAO作为独立的对象库被淘汰时,DAO代码将更新,并且新功能将在Access中继续作为ACE数据引擎对象。

当您设置对ACE数据引擎的引用时,所有DAO代码都应该可以正常工作。 这意味着什么(自2007年访问以来),您无需为DAO对象模型设置外部引用-它现在是JET / ACE数据库引擎的一部分。 (在访问2007之前,您必须设置对DAO的引用。如果要使用ADO,则始终必须设置该引用,直到今天仍然如此)。

之所以做出此更改,是因为实际上只有Access社区和开发人员都在使用DAO –其他大多数平台都在使用ADO(出于许多原因,但是一个重要原因是ADO不受限制,也不在MS-中具有起源)像DAO一样访问数据库引擎,直到今天仍然如此。

请记住,大约5到10年间,Microsoft没有SQL Server,因此Access + DAO是他们的“大事”。当他们最终开始销售SQL Server时,关于Microsoft推销DAO的事情当然发生了变化。 DAO是MS-access数据引擎技术的“主要”。

如果将来您将数据从Access移到sql服务器,并继续使用MS-access作为GUI前端,则访问社区STILL建议您坚持使用用于开发应用程序的任何对象模型。因此,访问使用DAO开发但使用sql server作为后端数据库的应用程序就可以了,并且应该保持这种状态。

如果您使用ADO开发,那么如果您开始将SQL Server与Access一起使用,则希望继续。请注意,我所说的是您编写的VBA代码-特定的ADO记录集。

您仍然始终使用Access中存在的“相同”内部容器-如果在编写代码以修改Access客户端中的数据时使用ADO或DAO,则这些容器不会更改。

如果您要从“第一天”开始使用SQL Server作为后端,而Access作为前端,ADO肯定会具有一些优势,但是即使在那些情况下,如果您的访问应用程序是使用DAO编写的,那么我将继续甚至在SQL Server上也可以使用DAO。

但是,对于.net开发人员,Visual Basic开发人员而言,他们很可能使用ADO对象模型来提高他们的技能,并且当他们使用MS-access作为开发工具时,他们可以继续使用熟悉的“长时间”在MS-access中编写代码时使用ADO数据对象模型。

如前所述,我不建议在给定的单个应用程序中混合使用两个对象模型,因为这会造成混淆。

编辑:

要引用此链接: https://docs.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/container-object-dao

每个数据库对象都有一个由内置Container对象组成的Containers集合。应用程序可以定义自己的文档类型和相应的容器(仅Microsoft Access数据库引擎数据库);但是,并非总是可以通过DAO支持这些对象。

这些容器对象中的某些是由Microsoft Access数据库引擎定义的,而其他则可能是由其他应用程序定义的。下表列出了Microsoft Access数据库引擎定义的每个Container对象的名称及其包含的信息类型。

答案 3 :(得分:0)

不确定这是多么不合时宜,但我碰到了它,没有读完整个内容,所以我希望上面还没有回答。但是,从粗略的阅读看来,似乎有人错过了某处的东西。

以下是我用来尝试了解VBA怪癖及其结果的一些代码。结果首先,代码之后。

致电DumpDBContainers()

当前数据库包含9个容器

容器DataAccessPages包含0个文档
容器数据库包含3个文档
容器表单包含14个文档
容器模块包含20个文档
容器关系包含4个文档
容器报告包含0个文档
容器脚本包含22个文档
SysRel容器包含1个文档
容器表包含151个文档

Public Sub DumpDBContainers()

Dim dbs As Database, Cntr As Container
Dim bNmeOnly As Boolean

Set dbs = CurrentDb()

Debug.Print " "
Debug.Print "Current database contains " & dbs.Containers.count & " containers"
Debug.Print " "

For Each Cntr In dbs.Containers
    Debug.Print "Container " & Cntr.Name & Space(30 - Len(Cntr.Name)) & "contains " & Cntr.Documents.count & " documents"
Next Cntr

End Sub