I would rephrase that because you said it backwards. Properties of the object model are a subset of those in the properties collection not the other way around.
So in some cases you can only reference a property through the properties collection "myDb.Properties("propertyName"), while other times you can reference it directly through either the object model "myDB.propertyName" or through the properties collection. If it is in the object model it is also in the properties collection.
My understanding.
The reason why some properties are not in the object model especially DAO objects is for several reasons. DAO is used in other things besides Access so some of the properties only have meaning in Access. So having a properties collection allows you to "extend" the object model to fit your needs. Other places these properties will have no meaning. So only attributes that are universal and stable are in the strong typed properties of the object model. I think another reason may be compactness. As I demoed in the other link certain properties have no meaning until you get into a certain state. If a field in a table is displayed using a textbox then properties for a combobox have no meaning. Some of it may be versioning too. If after the release of a DAO object model you were to add new properties it may cause backward compatibility issues.
Here is a more extensive discussion from
chat. I did not verify all assertions, but most sounds legit.
In Microsoft Access/Jet/ACE
DAO (Data Access Objects), you’ll notice two “layers” of metadata on objects such as Database, TableDef, Field, Index, Relation, etc.:
- Strongly‑typed properties and methods on the object itself (what IntelliSense shows, e.g., TableDef.Name, Field.Type, Index.Primary).
- An extensible Properties collection (e.g., TableDef.Properties("Description"), Field.Properties("ValidationRule")).
Why do some attributes live in the first, and others only in the second? The short answer is:
binary compatibility and extensibility of a COM/DAO library across engines, versions, and providers. Here’s the deeper breakdown.
1) DAO is a COM library with a fixed, versioned type interface
DAO is implemented as a COM type library. Public members exposed directly on objects (Database, TableDef, Field, etc.) are
compiled and frozen per version (e.g., DAO 3.6, 12.0). Adding or changing those members is risky:
- Binary compatibility: Once an interface ships, adding/removing properties can break compiled VBA/VB code and other clients.
- Cross‑provider scope: DAO front‑ends multiple data engines (Jet/ACE, ODBC, ISAMs). Only attributes that are universal and stable across engines tend to become first‑class properties.
So, core things every client needs—like Field.Name, Field.Type, Recordset.Edit, Index.Name, Relation.Attributes—are
baked into the object model as strongly‑typed properties. That keeps the main model stable and predictable across versions.
2) The Properties collection exists for extensibility and provider‑specific metadata
The Properties collection is DAO’s “escape hatch” for
engine‑, provider‑, or version‑specific attributes that the core interface didn’t (or couldn’t) standardize:
- Provider/engine specific: Jet/ACE invents new attributes (e.g., engine type, ANSI padding, Unicode compression) that shouldn’t bloat the core interface or force a DAO version bump.
- Version agility: New Access/ACE releases can add attributes without breaking old code. If a caller doesn’t know about a property, it simply won’t ask for it.
- Optional/rare features: Some attributes apply only to certain object types or configurations (e.g., validation text on a field; SubdatasheetName; replication IDs). Keeping these in Properties avoids cluttering the main interface.
- Backward compatibility: Older code can continue to automate DAO without recompilation, while newer clients can discover added capabilities through Properties.
Think of Properties as a
metadata key/value bag attached to a DAO object, designed so engines and tools can add capabilities without changing the strongly‑typed contract.
3) Practical examples you’ll likely encounter
Common first‑class vs. Properties‑only examples
- First‑class on Field: Name, Type, Size, Attributes, DefaultValue (the major, portable stuff).
- Properties on Field:
- ValidationRule / ValidationText (rule text strings the engine/UI interpret)
- Description (UI/Design‑time metadata)
- AllowZeroLength (text‑specific input rule in Jet/ACE)
- UnicodeCompression (ACE storage behavior)
- First‑class on TableDef: Name, Attributes, Connect, SourceTableName.
- Properties on TableDef:
- Description
- SubdatasheetName, SubdatasheetHeight (Access UI behavior)
- Engine settings such as Jet OLEDB:Engine Type/ACE analogues (depending on provider)
- Indexes/Relations: core flags (e.g., Index.Primary, Relation.Attributes) are first‑class; descriptive text or UI extras tend to show up in Properties.
You’ll also run into Access‑UI properties that DAO carries because the Access designer uses DAO to persist them (subdatasheet settings, column widths, etc.). Those are
not broadly meaningful to non‑Access engines, so they remain in Properties.
4) Why not just promote everything to a real property?
Promoting a property from Properties("X") to a first‑class Object.X:
- Requires changing the public interface of the COM type library (new v‑table, new GUIDs/typelibs in some cases).
- Introduces versioning headaches for code compiled against the old interface.
- Creates portability issues if the attribute only makes sense for Jet/ACE (but DAO also fronts ODBC/ISAM).
DAO’s philosophy (dating back to the 1990s) favors a small, stable core plus an extensible bag. That’s why many “design‑time” or “engine‑specific” attributes never become first‑class members.