# Object classes

To store data in a solution, you need to create *object classes* to describe the types of data you'd like to store. It is common to set up some foundational object classes with a few initial properties as the first step in a new solution. Object classes are defined in the [Global data model](https://docs.appfarm.io/reference/data-model) and are exposed to the apps and services in your solution using [data sources](https://docs.appfarm.io/reference/apps/data/data-sources).

## Usage

To add an object class to your data model:

* Hover over the **+** icon in the top-right of the [data model designer](https://docs.appfarm.io/reference/data-model/..#data-model-designer).
* Click **Create Object Class**.

An object class is a structured definition of a single business object, for example, a `Project`. Each object class is assigned *properties,* which are individual fields for storing data, such as `Title`, `Status`, or `Created Date`. Each property has a *data type*, such as string, boolean, or datetime, which determines the format of the value allowed in the database. Object classes can also reference each other, allowing you to connect a `Task` to a `Project`.

{% hint style="success" %}
**Best practice**

Use the singular when naming an object class (Project, *not* Projects) since it does not contain any data but is a definition of how a single object is structured.
{% endhint %}

![An example of an object class Project, which is referenced by another object class, Task.](https://29237295-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MiLU-xcHu0eLZiTxcmZ%2F-Mk7Rhj8TuUmfzre68dw%2F-Mk7S2xKLnsq0ywRcQi7%2Fdata-model-diagram.png?alt=media\&token=87994ca9-c378-48a3-9f23-704bb9003872)

To read and modify objects in an object class, you must first create a [data source](https://docs.appfarm.io/reference/apps/data/data-sources) in an app or service. You can then use action nodes to [create an object](https://docs.appfarm.io/library/action-nodes/create-object) within an object class, assign values to the properties you have defined, and [persist](https://docs.appfarm.io/library/action-nodes/persist-objects) (store) the data in the database.

{% hint style="info" %}
**Good to know**

Every solution has one built-in object class called *User*. This object class represents the [users](https://docs.appfarm.io/reference/security/users) of your apps. The User object class cannot be modified, but it can be referenced in the same way as any other object class.
{% endhint %}

## File object class

This is a special type of object class that stores files such as documents and images in the database. For example, PDFs created using the [Generate document action node](https://docs.appfarm.io/library/action-nodes/generate-document) or files and images [uploaded](https://docs.appfarm.io/library/action-nodes/create-file-object) by end-users should be stored in file object classes. For static files used in your apps, you should use [Files](https://docs.appfarm.io/reference/resources/files).

To add a file object class to your data model:

* Hover over the **+** icon in the bottom-right of the [data model designer](https://docs.appfarm.io/reference/data-model/..#data-model-designer).
* Click **Create File Object Class**.

File object classes have [additional built-in properties](https://docs.appfarm.io/reference/object-class-properties#built-in-properties-for-file-object-classes) to store file metadata.

## General properties

These general properties describe an object class and should not be confused with object class properties, which are used to store data.

<table><thead><tr><th width="236">Property</th><th>Description</th></tr></thead><tbody><tr><td><strong>Name</strong></td><td>A descriptive name for the object class. Use the singular (Project, <em>not</em> Projects).</td></tr><tr><td><strong>Display Property</strong></td><td>A <a href="#data-types">string</a> property that may be used to represent an object, for example in <a href="../appfarm-client/developer-tools-for-apps">Developer tools</a>.</td></tr><tr><td><strong>Description</strong></td><td>A longer description of the object class. For your own reference.</td></tr><tr><td><strong>Icon</strong></td><td>An icon from the built-in icon library to represent the object class throughout Appfarm Create.</td></tr><tr><td><strong>Tags</strong></td><td>Add <a href="..#tags">tags</a>.</td></tr></tbody></table>

## Meta Data

You can enable additional [built-in object class properties](#built-in-properties). When any of the properties below are enabled, these properties will be stored for each *new* record.

<table><thead><tr><th width="236">Property</th><th>Description</th></tr></thead><tbody><tr><td><strong>Created By</strong></td><td>Add a read-only property to every object with a reference to the User that created the object.</td></tr><tr><td><strong>Updated By</strong></td><td>Add a read-only property to every object with a reference to the User that last updated the object.</td></tr><tr><td><strong>Random Identifier</strong></td><td><p>Add a read-only string property to every object with an automatically generated unique, random identifier.</p><p></p><p>This property is useful when you need to publicly expose a unique reference to an object, for example, when <a href="../../how-to/enhance-your-app/link-previews">sharing URLs on social media</a> or generating ticket references.<br><br><strong>Note</strong>: If you enable this property when objects have already been created in an object class, only the <em>new</em> objects will be automatically assigned a random identifier. For existing objects, it is necessary to <a href="../graphql/mutations#generate-random-identifiers">perform a mutation</a> via the GraphQL interface.</p></td></tr><tr><td><strong>Sequential Identifier</strong></td><td>This will generate a sequential identifier on each object (often also referred to as a sequential counter). The value will be set when the object is stored in the database. That is, when persisting a runtime object or creating an object in a database connected data source.<br><br><strong>Example</strong>: The Object Class <code>Order</code> has Sequential Identifier enabled, with a Starting Value of 10000. The last Order in the database has a Sequential Identifier of 12003. This means the next Order will get a Sequential Identifier of 12004. In this case, we may use the Sequential Identifier as the Order number.<br><br><strong>Note</strong>: If you enable this property when objects have already been created in an object class, only the <em>new</em> objects will be assigned a Sequential Identifier.</td></tr><tr><td><strong>Starting Value</strong></td><td>Only applicable when Sequential Identifier is enabled. This is the starting value of the Sequential Identifier. The default is 1, but you may choose a higher starting value (for example, if you want to generate order numbers starting at 10000, you may set Starting Value to 10000)</td></tr></tbody></table>

## Concurrency Control

By default, when 2 different users update the same object, the *last write wins*.&#x20;

{% tabs %}
{% tab title="Example - Last Write Wins" %}
Users John and Paula both read company `ThirtyFifty Inc` into a runtime only data source.

1. John updates the Status to `Inactive`, Paula updates the Status to `Prospect`. Both at the same time. The changes have not yet been saved.
2. John clicks Save. The entry in the database is updated to `Inactive`.
3. Paula clicks Save. The same entry in the database is updated to `Prospect`.

The outcome: ThirtyFifty Inc's Status is updated to `Prospect`. The last write (Paula) wins.
{% endtab %}
{% endtabs %}

The built-in Object Class Property **Strict Object Versioning** allows you to enable *first write wins*.&#x20;

{% tabs %}
{% tab title="Example - First Write Wins" %}
Users John and Paula both read company `ThirtyFifty Inc` into a runtime only data source.

1. John updates the Status to `Inactive`, Paula updates the Status to `Prospect`. Both at the same time. The changes have not yet been saved.
2. John clicks Save. The entry in the database is updated to `Inactive`.
3. Paula clicks Save. An exception is thrown (ConflictError (34013)), and the entry is not updated.

The outcome: ThirtyFifty Inc's Status is updated to `Inactive`. The first write (John) wins.
{% endtab %}
{% endtabs %}

Enabling Strict Object Versioning also enables a built-in integer property `Version No` for the objects of this Object Class. The Version No is automatically incremented every time the object is successfully updated.

{% hint style="warning" %}
Please note

* It is not recommended to use *Subscribe to updates* with *Strict Object Versioning* since this might break the strict versioning control.
* Components dispatching frequent updates might not work in conjunction with *Strict Object Versioning,* as subsequent updates might be dispatched with the old version number.
* Data connectors or updates using GraphQL cannot be used in conjunction with *Strict Object Versioning*.
  {% endhint %}

## URL Lifetime

This setting is only available for [file object classes](#file-object-class). It controls the lifespan of the generated signed URL, which can be used to provide external access to the file. The setting specifies how long (in seconds) the URL remains valid for accessing the file. If not set, the default lifetime is 12 hours (43 200 seconds). It can be set to a minimum of 60 seconds and a maximum of 1 week (604 800 seconds).

To optimize performance, Appfarm caches signed URLs. The caching behaviour depends on the URL's time to live (TTL):

* **TTL < 4 hours:** Cached for half the specified TTL.
* **TTL >= 4 hours:** Cached for 2 hours.

Note that changing the TTL only affects newly generated URLs. Existing URLs and cached URLs remain unaffected.

## Data Export

<table><thead><tr><th width="234">Property</th><th>Description</th></tr></thead><tbody><tr><td><strong>Enable Endpoint</strong></td><td>Enable the <a href="data-extract-api">Data Extract API</a> for this object class.</td></tr></tbody></table>

## GraphQL

Exposure of an object class via [GraphQL](https://docs.appfarm.io/reference/data-model/graphql) must be explicitly enabled. The specific types of [queries](https://docs.appfarm.io/reference/data-model/graphql/queries) and [mutations](https://docs.appfarm.io/reference/data-model/graphql/mutations) that should be available must also be enabled.

In addition to these properties, to successfully run those queries and mutations, you need to have a role with the appropriate [permissions](#permissions), and GraphQL must be enabled for the [environment](https://docs.appfarm.io/configuration/environments#general-settings).

<table><thead><tr><th width="234">Property</th><th>Description</th></tr></thead><tbody><tr><td><strong>Enable GraphQL</strong></td><td>Expose this object class via a GraphQL endpoint.</td></tr><tr><td><strong>Endpoint Name</strong></td><td>The name of the GraphQL endpoint. This is generated automatically based on the <strong>Collection Name</strong> of the object class.<br><br><strong>Warning:</strong> If the GraphQL endpoint is used in Production and this name is changed, existing queries will need to be altered.</td></tr><tr><td><strong>Enable Read</strong></td><td><a href="graphql/queries">Query</a> data within objects in this object class.</td></tr><tr><td><strong>Enable Aggregate</strong></td><td>Run aggregation queries such as <a href="../graphql/queries#count">count</a>.</td></tr><tr><td><strong>Enable Create</strong></td><td><a href="../graphql/mutations#create">Create</a> a new object in this object class.</td></tr><tr><td><strong>Enable Update</strong></td><td><a href="../graphql/mutations#update">Update</a> (edit) data within objects in this object class.</td></tr><tr><td><strong>Enable Delete</strong></td><td><a href="../graphql/mutations#delete">Delete</a> objects in this object class.</td></tr></tbody></table>

## GDPR

To maintain an overview of the personal information you are storing, you can assign a GDPR classification and describe why this information is collected and stored and how this information is used. Please refer to your subscription agreement for further information about your obligations around data privacy.

<table><thead><tr><th width="234">Property</th><th>Description</th></tr></thead><tbody><tr><td><strong>GDPR Classification</strong></td><td><p>A privacy classification for the data stored in this property. The options are:</p><ul><li><code>None</code>: This property does not store personal information.</li><li><code>Personal</code>:  This property stores personal information. For example name, address, phone number, email address, social security number, or profile picture.</li><li><code>Sensitive:</code> This property stores sensitive personal information. For example ethnic origin, political views, religion, health information, or sexual orientation. </li></ul></td></tr><tr><td><strong>GDPR Details</strong></td><td>A description of why this information is collected and stored and how it is used. For your own reference.</td></tr></tbody></table>

## Permissions

Object class permissions form a key part of your solutions' security. They determine which roles can access and modify data in that object class. By default, the [built-in roles](https://docs.appfarm.io/security/roles#built-in-roles) Owners, Maintainers, and Developers get full read and write access to each object class when it's created.

When editing an object class you can grant and revoke permissions for the built-in roles as well as for each custom role. You can also edit these rules for all object classes under [Permissions](https://docs.appfarm.io/security/permissions#object-classes). Changes to object class permissions require a [deploy](https://docs.appfarm.io/reference/operations/deploy) to come into effect in an environment.

<table><thead><tr><th width="232">Permission</th><th>Description</th></tr></thead><tbody><tr><td><strong>Create</strong></td><td>Create a new object in this object class.</td></tr><tr><td><strong>Read</strong></td><td>Read data within objects in this object class.</td></tr><tr><td><strong>Update</strong></td><td>Update (edit) data within objects in this object class.</td></tr><tr><td><strong>Delete</strong></td><td>Delete objects in this object class.</td></tr><tr><td><strong>Aggregate</strong></td><td>Run aggregation queries such as <a href="../graphql/queries#count">count</a> via GraphQL.</td></tr></tbody></table>

## Object class properties

&#x20;See article [Object class properties](https://docs.appfarm.io/reference/data-model/object-class-properties).
