[返回博客](/cn/blog) # BimRv SDK：什么是可扩展存储机制？

Evgeniy Tikhonov 三月 25, 2021 [\#rvt](/cn/blog/tag/rvt) [\#rfa](/cn/blog/tag/rfa) [\#getting started](/cn/blog/tag/getting-started)

<a class="a2a_button_facebook"></a><a class="a2a_button_twitter"></a><a class="a2a_button_linkedin"></a>

可扩展存储机制允许将用户数据直接存储在模型元素中。此机制不用于项目或族内部，因此不影响项目或族的参数。有广泛的模型元素集可以存储用户数据。此机制的一个共同特点是使用基于模式的技术。

根据此方法，要在模型元素中存储用户数据，应使用以下对象定义数据：

- 字段 (Field) — 包含数据名称、类型和单位信息，并用作访问实体中相应数据的键。
- 模式 (Schema) — 数据字段对象的集合。
- 实体 (Entity) — 包含与模式对应的数据的对象，可以插入到元素中。

BimRv SDK支持使用以下实现模式、字段构建器和帮助器的类来创建和使用基于模式的数据结构：

- OdBmESSchemaBuilder — 执行模式定义的创建。
- OdBmESFieldBuilder — 在创建新字段时与OdBmESSchemaBuilder一起使用的辅助类。
- OdBmESEntityHelper — 用于访问现有可扩展实体字段值的辅助类。
- OdBmESSchemaHelper — 允许读取现有模式的属性和字段。
- OdBmESFieldHelper — 在读取字段属性和定义时与OdBmESSchemaHelper一起使用的辅助类。

BimRv SDK可扩展帮助器支持以下数据类型：

- bool
- OdInt16
- OdInt32
- double
- float
- OdString
- OdGuid
- OdBmObjectId
- OdGePoint2d
- OdGePoint3d
- OdArray
- OdMap (除double、float、OdGePoint2d和OdGePoint3d外，所有类型都支持作为键)
- OdBmObject (另一个模式的实例)

通过使用属性，可以配置架构以限制所有用户、特定应用程序供应商或来自供应商的特定应用程序的读取和/或写入访问。

下一节将介绍可扩展存储的简单用法。

#### 创建存储描述

要创建新模式，请使用 OdBmESSchemaBuilder 类：

```
OdBmESSchemaBuilder schemaBuilder(pDb);
schemaBuilder.setSchemaName(L"WireSpliceLocation")
  .setSchemaGUID(OdGUID("720080CB-DA99-40DC-9415-E53F280AA1F0"))
  .setVendorId(L"BimRv")
  .setDocumentation(L"WireSpliceLocation schema")
  .setReadAccessLevel(OdBm::ESSchemaAccessLevel::Public)
  .setWriteAccessLevel(OdBm::ESSchemaAccessLevel::Public);
```

应使用 OdBmESFieldBuilder 类在存储中创建字段。此类包含用于设置字段属性的方法，例如：

- setDocumentation() — 字段的描述。
- setSubSchemaGUID() — 描述存储在字段中的子实体的模式的全局唯一标识符 (GUID)。
- setUnitType() — 字段中存储的值所表示的单位类型。

下面是创建两个简单字段（一个数组字段和一个映射字段）的示例：

```
schemaBuilder.addSimpleField<bool>(L"BooleanField").setDocumentation(L"Boolean value");
schemaBuilder.addSimpleField<OdGePoint3d>(L"XYZField").setUnitType(OdBm::UnitType::UT_Length).setDocumentation(L"XYZ value");
schemaBuilder.addArrayField<OdGUID>(L"GUIDArrayField").setDocumentation(L"GUID array value");
schemaBuilder.addMapField<OdString, OdString>(L"StringMapField").setDocumentation(L"Map value");
```

字段名称用于访问字段数据以写入和读取值。在模式中定义所有字段后，调用 finish() 方法以完成模式构建器：

```
OdTfClass* pSchema = schemaBuilder.finish();
```

要创建模式实例（实体），请调用 OdBmESEntityHelper 类的 createEntity() 方法：

```
OdBmObjectPtr pESEntity = OdBmESEntityHelper::createEntity(pSchema);
```

字段属性以及模式属性（例如单位类型、名称和文档）在创建后无法更改。

#### 设置值

要设置实体字段的新值，请使用 OdBmESEntityHelper 类：

```
OdBmESEntityHelper helper(pESEntity);

helper.set<bool>(L"BooleanField", true);
helper.set<OdGePoint3d>(L"XYZField", OdGePoint3d(20., 21., 22.), OdBm::DisplayUnitType::DUT_METERS);

OdArray<OdGUID>guids;
guids.push_back(OdGUID("60E23C30-169B-4C46-BD2B-DC9FC476FD09"));
guids.push_back(OdGUID("1BAD71AA-137E-4519-8D9B-B0ED1672D1BF"));
helper.set<OdArray<OdGUID>>(L"GUIDArrayField", guids);

OdBmMap<OdString, OdString> stringMap;
stringMap[L"key1"] = L"value1";
stringMap[L"key2"] = L"value2";
helper.set<OdBmMap<OdString, OdString>>(L"StringMapField", stringMap);

```

显示单位类型参数仅用于 float、double、OdGePoint3d 和 OdGePoint2d 数据类型，并设置字段的单位类型。此方法内部不执行任何转换。

对于 OdBmObjectPtr，在 OdBmESEntityHelper 类实例的 set() 方法调用中使用 clone()：

```
helper.set<OdBmObjectPtr>(L"EntityField", pESEntity->clone());
```

set&lt;&gt;() 方法的模板参数必须与字段类型完全匹配（字段本身是在创建模式阶段指定的）。

#### 存储数据

应用程序可以将模式实例附加到模型中的任何元素。为避免在共享项目中锁定元素，请使用由 OdBmDataStorage 类表示的特殊元素。

```
OdBmDataStoragePtr pDataStorageElem = OdBmDataStorage::createObject();
pDataStorageElem->setName(L"DataStorageElem");

ODBM_TRANSACTION_BEGIN(t, pDb)
  t.start();
  hStorage = pDb->addElement(pDataStorageElem).getHandle();
  pDataStorageElem->setESEntity(pESEntity);
  t.commit();
ODBM_TRANSACTION_END()
```

#### 从存储中读取数据

以下代码示例说明了如何从存储助手读取数据：

```
OdBmObjectPtr pESEntity = pDataStorageElem->getESEntity(OdGUID(L"720080CB-DA99-40DC-9415-E53F280AA1F0")); 
OdBmESEntityHelper helper(pESEntity);

bool b = helper.get<bool>(L"BooleanField");
OdGePoint3d xyz = helper.get<OdGePoint3d>(L"XYZField", OdBm::DisplayUnitType::DUT_DECIMETERS);
```

get&lt;&gt;() 方法中的数据类型可以是第一节中列出的类型之一。作为模式的创建者，您应该知道每个字段的类型。如果不知道，您可以将值作为 OdTfVariant 对象进行处理：

```
OdTfVariant v;
pESEntity->getProperty(L"BooleanField", v);
```

您可以在 BimRv/Examples/ExBimDump 中找到将 OdTfVariant 对象转换为字符串的示例，特别是在 BmDumper::dumpVariant 方法实现中。

get&lt;&gt;() 方法中的显示单位类型参数用于将数据转换为所需的单位，例如，先前为字段设置的值的坐标等于 OdGePoint3d(200., 210., 220.)：

```
OdArray<OdGUID>guids = helper.get<OdArray<OdGUID>>(L"GUIDArrayField");
OdBmMap<OdString, OdString> strings = helper.get<OdBmMap<OdString, OdString>>(L"StringMapField");
```

#### 读取信息例程

要读取记录的信息，请获取模型元素，并确定存储 GUID 和字段名称。要在数据库中获取架构，请使用 OdBmESSchemaHelper 类的静态 listSchemas() 方法：

```
std::set<OdGUID> schemas = OdBmESSchemaHelper::listSchemas(pDb);
```

要访问数据库中与架构相关的元素，请使用静态 getElements() 方法：

```
OdBmObjectIdArray objects = OdBmESSchemaHelper::getElements(guid, pDb);
```

从字段检索信息的另一种方法是使用 OdBmESFieldHelper：

```
OdBmESFieldHelper fieldHelper(helper.getField(L"BooleanField"));
```

字段助手对象提供了访问字段属性的方法：

- getDocumentation() — 返回字段的描述。
- getFieldName() — 返回字段的名称。
- getContainerType() — 返回字段的类型：包含一个值的简单字段或包含多个值的容器。
- getEntryIndex() — 返回字段的索引。
- getSubSchemaGUID() — 返回描述存储在字段中的子实体的全局唯一标识符 (GUID)。
- getUnitType() — 返回字段中存储的值所表示的单位类型。

OdBmESSchemaHelper 类有助于获取有关架构的信息：

```
OdBmESEntityHelper helper(pESEntity);
OdBmESSchemaHelper schHelper(helper.getSchema());
```

- getDocumentation() — 返回架构的描述。
- getVendorId() — 返回第三方供应商的字符串标识符，该供应商可以在供应商访问级别下访问架构的实体。
- getSchemaName() — 返回架构的名称。
- getSchemaGUID() — 返回架构的全局唯一标识符 (GUID)。
- getReadAccessLevel() — 检索架构的当前读取访问级别。
- getWriteAccessLevel() — 检索架构的当前写入访问级别。

## 今天就开始行动

**免费试用 ODA 软件 60 天。  
无风险，无需信用卡。**

[免费试用](https://www.opendesign.com/cn/free-trial)
