Understanding the different storage types

The storage used by your application records contributes to the most important part of the overall data storage allocation on the platform. There is also another type of storage used by the files uploaded or created on the platform. From the Storage Usage page under the Setup menu, you can see a summary of the records used, including those that reside in the Salesforce Standard Objects.

Note

Later in this chapter, we will be creating a Custom Metadata Type object to store configuration data. Storage consumed by this type of object is not reflected on the Storage Usage page and is managed and limited in a different way.

Understanding the different storage types

Tip

The preceding page also shows which users are using the most amount of storage. In addition to the individual's User Details page, you can also locate the Used Data Space and Used File Space fields; next to these are the links to view the users' data and file storage usage.

The limit shown for each is based on a calculation between the minimum allocated data storage depending on the type of organization or the number of users multiplied by a certain amount of MB, which also depends on the organization type; whichever is greater becomes the limit. For full details of this, click on the Help for this Page link shown on the page.

Data storage

Unlike other database platforms, Salesforce typically uses a fixed 2 KB per record size as part of its storage usage calculations, regardless of the actual number of fields or the size of the data within them on each record. There are some exceptions to this rule, such as Campaigns which take up 8 KB, and stored Email Messages use up the size of the contained e-mail, though all Custom Object records take up 2 KB. Note that this record size also applies even if the Custom Object uses large text area fields.

Tip

Salesforce Big Objects offer a different kind of storage solution, these objects are designed for the storage of billions of records, receiving device input, in Internet of Things (IoT) scenario for examples. Information is written on mass using bulk loading and later read frequently, or stated another way, written less and read often. Although not disclosed by Salesforce, the expectation is that the storage cost for these objects will be cheaper than equivalent records stored in Custom Objects. The Race Data object introduced later in this chapter could be considered a good candidate for this type of object for the FormulaForce application, since this information is uploaded after the race in bulk and used to analyze the race.

Columns versus rows

Given the calculation in the preceding section, you may want to consider whether your data model has multiple occurrences of data that have a known maximum value. In these cases, consider the option of creating multiple columns (or multiple sets of columns) instead of a new object that will use up additional storage. Enterprise Edition orgs currently support up to 500 fields per object. For example, in Formula 1 racing, it is well established that there are only three rounds of qualification before the race in order to determine the starting positions, where each driver competes for the fastest lap.

This could be modeled as a Qualification Lap child object to the Contestant object; however, in this case, it will only ever have a maximum of three records per contestant in it. A more optimal data storage design is a set of new fields in the Contestant object.

Perform the following steps in the packaging org to try out this process:

  1. Create three fields of type Number(6,3), for example, Qualification 1 Lap Time (Qualification1LapTime__c), on the Contestant object. Ensure that the Required checkbox is unchecked when creating these fields, since not all drivers make it through to the final qualification rounds. Note that here we have used numerals instead of words, for example QualificaitonOneLapTime__c, as this can help in situations where dynamic Apex is iterating over the fields.
  2. Create a roll-up summary field on the Race object, Poll Position Lap Time, utilize the MIN option when selecting Roll-Up Type, and select the Qualification 1 Lap Time field in Field to Aggregate, as shown in the following screenshot:
    Columns versus rows
  3. Finally, update the permission sets to grant read and write access to the new fields that you have just added in the Race Management permission set and read access within the Race Analytics permission set.

Keep in mind that you can also use Formula fields to add or apply further logic to data stored in columns, emulating what would have been filtered or aggregating queries over equivalent rows. There is also a benefit to reducing the number of SOQL and DML operations that your code needs to perform when taking this approach.

Visualizing your object model

It is an essential idea to build an Entity Relationship Diagram (ERD) of your object model; not only is this a good resource for you and your team, but it can also help your customers understand where the data that they are creating resides, and help them build reports and integration solutions. Salesforce provides an interactive tool known as Schema Builder (accessed via the button from the Objects page under Setup) that can help with this; it can also be used to create new objects and fields. At this stage in the book, the FormulaForce application data model should look something like this:

Visualizing your object model

Tip

If you are creating logging solutions in your application, keep in mind the storage usage for this type of data. For example, how does the user perform bulk deletion of the records? Should this be scheduled? Also, how do you communicate this information to them? A log object can be configured with workflow rules by the subscriber to perhaps e-mail users as critical log entries are inserted.

If your users are using Chatter, you may want to consider providing the facility (perhaps as an option through dynamic Apex, to avoid a package dependency) of using a Chatter post to notify the user. Chatter posts, comments, and track changes are not counted by Salesforce under storage usage. However, any files and photos you upload are counted against file storage.

Considerations for configuration data

Most applications need to provide some way to configure their functionality to allow administrators and users to tailor it to their needs. As we have seen in Chapter 2, Leveraging Platform Features, Salesforce provides a great deal of facilities for this for you and your users. However, what if the part of your application you want to provide configuration for is unique to your application domain, for example in a list of official fastest lap times for each track.

In our case, imagine we want to provide to our customers as part of the package the current approved list of fastest lap times for each track, so that they don't have to look this up themselves and enter them manually. However, you still want to allow users to manage fastest laps for tracks not known to your application.

Custom Settings and Custom Metadata Types are two platform features to consider for storing and managing configuration for your application before considering Custom Objects. Custom Metadata in many ways is a successor to both alternatives, though at this time there are still some features that may cause you to consider using other options.

The following table helps you decide which object type to use based on your configuration requirements:

Configuration Object Requirement

Custom Object

Custom Setting Object

Custom Metadata Type Object

Objects can be hidden from org administrators

No

Yes

Yes

Records can be included in your package

No

No

Yes

Packaged records can be protected from user edits and upgraded

N/A

N/A

Yes

Ability to edit fields on packaged records can controlled

N/A

N/A

Yes

Layout of the standard Salesforce UI can be defined and packaged

Yes

No

Yes

Object relationships are supported for more complex configuration

Yes

No

Yes

Apex access

CRUD

CRUD

Read **

Records can be defined at an org, user or profile level

No

Yes

No

Records can have custom validation applied via Validation Rules and/or Apex Triggers

Yes

No

No

Reduction in configuration management overhead

Rekey or use Data Loaders

Rekey or use Data Loaders

Install by default also use native Change Sets and Packages to manage customer specific configuration

Ability for partners and other developers to build extension packages that package specific forms of your configuration

No

No

Records can also be included extension packages

Note

When reading Custom Metadata Type records, SOQL can be used and it does not count towards the SOQL query governor, though the 50k row limit still applies. Custom Metadata Type records can be manipulated using the Salesforce SOAP Metadata API CRUD operations.

Though the Metadata SOAP API can be called via Apex, restrictions around HTTP callouts still apply. Restrictions around the frequency and when HTTP callouts can be made make this approach less desirable when scaling above 200 records. Also, maintaining referential integrity between calls is not supported, as there is no database transaction scope around the API calls. At the time of writing Salesforce have announced that native support for Metadata API is under development, although there is no commitment to deliver with their statement.

In our case, the desire to package track lap time configuration records and thus allow it to be upgraded fits well with Custom Metadata Types. There is also no need to update this configuration information programmatically from Apex, only read it.

The current inability to update Custom Metadata Type records is something that might be an issue for you if you wish to build a custom UI for your configuration, in our case the Standard Salesforce UI is sufficient.

Custom Metadata Type storage

From the Custom Metadata Types page under Setup you can both create Custom Metadata Type objects and manage the records they contain. Any records you create can be included in your package and are thus available to your Apex logic immediately after the installation of your package.

Perform the following steps to create the Track Lap Records MDT object.

  1. Create a Track Lap Records custom metadata type by clicking on New, and enter TrackLapRecords as the API name.
  2. From the Visibility field select All Apex code and APIs can use the type, and it is visible in Setup. This is done since we want to allow the administrator to record their own fastest lap times in addition to those we include. You would choose the option Only Apex code in the same managed package can see the type, if all records in this object are to be used only by your application logic, for example for internal configuration.
  3. The page for describing your new Custom Metadata Type object looks very similar to that used by Custom Object. As noted in the preceding table, you cannot define some features like Validation Rules and Custom Buttons, though in comparison to Custom Settings you can define your own layout. There are also more field types available.
    Custom Metadata Type storage

Note that the API name for Custom Metadata Type objects ends with _mdt and has different standard fields. We will use the DeveloperName field as a unique name for the race track on which the lap record was achieved. Later we will include records from this object in the package. The isProtected field is used to determine whether the recorded data can be edited by the administrator of the package.

Follow these steps to create some fields on the object.

  1. Create the following fields as described in the following table. Accept the default shown for the Field Manageability field.
  2. Add the Track Lap Records Custom Metadata Type object to the package.

    Object

    Field name and type

    TrackLapRecords__mdt

    DriverName__c Text(60)

     

    Time__c Number(5,3)

     

    Year__c Text(4)

You may have noticed the following option when creating the preceding fields:

Custom Metadata Type storage

This option only applies with respect to records included in the package. It determines which fields the package administrator can change for those records. For example, you might want to add a Notes text field to the object that the administrator can edit, but protect all other fields. For the fields that we added here, the default is important since we want package updates to update changes in new lap records on tracks known to the application.

Custom Metadata Type storage

Enter the following sample data. From the object definition page click on the Manage Track Lap Records to begin entering configuration data. Deselect the Protected checkbox when adding records.

Note

Protection: This determines if the record is visible in the customer org. Protected records are hidden from the user, but your own packaged Apex code can still query them. Use protected records for internal configuration.

Custom Metadata Type storage

Tip

You can also define a List View to make it easier for you to manage Custom Metadata Type records in the packaging org. You cannot initially edit the default All view, though you can create one with the same name; click on Create New View. This List View is not packaged.

Storage used by Custom Metadata Type records is not shown on the Storage Usage page. The calculation used is based on the maximum record size based on the field size and not the standard 2 KB used on Custom Objects. Records created by users can total up to 10 MB. Your packaged records also get their own 10 MB limit. You can calculate the storage used by reviewing the record size shown on the Custom Metadata Types page.

Custom Metadata Type storage

To add the records to the package, follow these steps:

  1. From the Package Detail page click Add Components.
  2. Select Track Lap Record from the dropdown and select all records.

When completing Step 2, the Add to Package page will look like the following:

Custom Metadata Type storage

Note

Trivia: In its pilot phase the Custom Metadata Type feature was known as Platform on Platform. The branding later changed, but at the time Salesforce felt that this described one of the potentials of this technology to start to build your own platform packages that added to new metadata types to the platform. As stated in the considerations table earlier, the ability for others to package your custom metadata type records is a realization of this vision.

Custom Settings storage

Custom settings are slightly different from Custom Objects with respect to data storage limits, in that they do not exist in the same storage area. Custom settings are ideal for data that is read often but written to infrequently. Salesforce caches data in these objects in something it calls the Application Cache and provides a means to query it quickly without query governor limits being applied. However, unlike Custom Objects, they do not support Apex Triggers or Validation Rules.

There are limits on the storage they can consume, per organization, per namespace. This means that if you create a custom setting and add it to your managed package, it gets its own storage limit. The storage limit for custom settings starts with 1 MB for a full licensed user and can go up to a maximum of 10 MB. You can see the current storage utilization from the Custom Settings page under Setup.

File storage

Salesforce has a growing number of ways to store file-based data, ranging from the historic Document tab, to the more sophisticated Content tab, to using the Files tab, not to mention Attachments, which can be applied to your Custom Object records if enabled. Each has its own pros and cons for end users and file size limits that are well defined in the Salesforce documentation. Going forward only Files will be supported by Salesforce and so use of this is recommended over other file storage options. For example, only the Files tab is supported in Lightning Experience.

From the perspective of application development, as with data storage, be aware of how much your application is generating on behalf of the user and give them a means of controlling and deleting that information. In some cases, consider whether the end user would be happy to have the option of recreating the file on demand (perhaps as a PDF) rather than always having the application to store it.

Record identification, uniqueness, and auto numbering

Every record in Salesforce has an Id field, and with a few exceptions, also a Name field or DeveloperName for Custom Metadata Type objects. The Id field is unique, but is not human readable, meaning it cannot be entered or, for most of us on this planet, easily remembered!

The Standard and Custom Objects default value for the Name field is to provide a means for the user to enter their own textual description for the record, such as the race name or the driver name. The Name field is not enforced as being unique. Being the primary means by which the user identifies records, this can be a problem and is something that the end user needs to avoid. This aspect of the platform can be particularly problematic with accounts and contacts hence AppExchange has a number of so-called "Deduplication" applications you can try.

Tip

The Database.merge and merge DML statements support the merging of accounts, leads, and contact records.

Unique and external ID fields

When adding fields, you can indicate that the values stored within them are unique and/or external identifiers. For unique fields, the platform will automatically enforce this rule regardless of how records are created or updated, rejecting records with no unique values. By utilizing fields designated as external ID fields, you can simplify the data-loading process for users; this will be discussed later in this chapter in more detail. Both of these field modifiers result in a custom index being created, which can help optimize query performance.

Tip

You can help users avoid creating duplicate records with the same name by ensuring that other identifying fields such as these are also added to the lookup layout as described in the previous chapter.

Let's add a Unique and External Id field to record the driver's Twitter handle. Perform the following steps in the packaging org to try this out:

  1. Create a new Text field, Twitter Handle (TwitterHandle__c), with a length of 15 on the Driver object, and check the Unique and External Id checkboxes.
  2. Utilize the Driver records entered in the previous chapters to update the fields and confirm that the system prevents duplicate Twitter handles. Lewis Hamilton's Twitter handle is LewisHamilton and Ruben's is rubarrichello.
  3. Update the permission sets that have read and write permissions for the new field to Race Management, and the read-only permission to Race Analytics.

Auto Number fields

The platform supports an auto sequence field type, which can be applied to the Name field during and after object creation (as long as the object has not been previously included as part of a prior package release upload). It can also be applied to a brand new field. The platform handles incrementing the sequence and ensures that there are no duplicates.

Apply Auto Number within the FormulaForce application to give a unique auto incrementing identifier to the Race Data records as they are inserted. Perform the following steps in the packaging org to try this out:

  1. Create a new Race Data (RaceData__c) object; for Record Name, enter Race Data Id, and select Auto Number from the Data Type field.
  2. In the Display Format field, enter RDID-{000000000} and 1 in the Starting Number. Finally, check the Allow Reports field.
  3. Add a Lookup field called Race (Race__c) to relate records in this object to the existing Race object. Select the Don't allow deletion of the lookup record that's part of a lookup relationship option to prevent the deletion of race records if race data exists. We will add further fields to this object in a later chapter.
  4. Create a tab for the Race Data object that we just created and add the tab to the Race Management and Race Analytics applications. By doing this, the tab and object will automatically be added to the package ready for the next upload.
  5. Create a test record to observe the Race Data Name field value.
    Auto Number fields
  6. Update the permission sets with the new object and fields, giving a read and write permission to Race Management and a read-only permission to Race Analytics.

While it is possible to add new custom fields to objects that have already been packaged and released to your customers, you cannot currently add new Auto Number fields to an object that has already been packaged, for example, the Driver object.

Apex tests creating test records that utilize Auto Number fields can be configured by an org setting to not increment the sequence number outside of the test, which would create gaps in the sequence from the end user's perspective. Access this setting in the subscriber org via the Options... button on the Apex Test Execution page under Setup as follows:

Auto Number fields

The Display Format determines the formatting but not the maximum sequence number. For example, if a format of SEQ{0000} is used, and the next sequence number created is 10,000, the platform will display it as SEQ10000, ignoring the format digits. The maximum of an Auto Number field is stated in the Salesforce documentation as being a maximum length of 30 characters, of which 10 are reserved for the prefix characters. It also states that the maximum starting number must be less than 1,000,000,000.

The platform does not guarantee that there will be no gaps in an auto number sequence field. Errors in creating records can create gaps as the number assigned during the insert process is not reused. Thus, set expectations accordingly with your users when using this feature.

Tip

One workaround to creating an unbroken sequence would be to create a Custom Object with the Name field that utilizes the Auto Number field type, for example, Job References. Then, create a relationship between this object and the object records to which you require the sequence applied, for example Jobs. Then, write an Apex Scheduled job that inserts records on a daily basis into the Job References object for each Jobs record that is currently without a Job Reference relationship. Then, run reports over the Job References object. To ensure that no Job records are deleted, thus creating gaps, you can also enable the lookup referential integrity feature described in the following sections.

Subscribers customizing the Auto Number Display Format

Be aware that Display Format cannot be customized once it is packaged and installed in the subscriber org. However, it is possible to create a custom formula field in the subscriber org to remove the prefix from the Name field value and reapply whatever prefix is needed. For example, the following formula will isolate the numeric portion of the Name field value and apply a new prefix specified in the formula (this could also be driven by a custom setting or conditional logic in the formula):

'MYID-' + MID(Name, 4, LEN(Name) + 4)

When this formula field is applied for a record whose Auto Number is RD-000000001, the formula would display as follows:

Subscribers customizing the Auto Number Display Format

Record relationships

A relationship is formed by a Lookup field being created from one object to another, often referred to as a parent and child relationship. There are two types of relationships in Salesforce: Master-Detail and Lookup.

Note

Custom Metadata Type objects only support Lookup relationships to other Custom Metadata Type objects or to other Custom Object or custom field metadata. Some features described in this section only apply to Custom Objects, such as lookup filters and referential integrity. Custom Setting objects do not support any form of record relationships.

In some aspects, they share similarities in how they are referenced when using SOQL and Apex and how they are input through the user interface (such as lookup filters described in the previous chapter). However, there are differences regarding limits and referential integrity features, and they are as follows:

  • Utilizing the Master-Detail form of relationship provides a powerful way to model containment, where one parent object record acts as a container for other child records; in our example, a race contains Contestants.
    • The platform will automatically cascade deletion of child records when the parent is deleted, and it will also enforce the need for a parent reference when the child records are created.
    • By default, the platform prevents users from moving the child records to another parent by editing the relationship field. However, you can disable this validation and permit this by selecting the Child records can be reparented to other parent records after they are created option.
    • With the use of Rollup Summary fields, it also becomes possible to build calculated fields based on values of the child record fields.
    • Salesforce, however, does recommend that this kind of parent-and-child relationship does not exceed 10,000 child records; otherwise, the platform will not support the cascade delete of child records.
    • You can define up to three levels of Master-Detail relationships.
  • Utilizing the Lookup type of relationship allows you to model connections between related records that are optional and may also have other relationships not necessarily in an ownership or containing aspects oftheir parents. Keep in mind the following points when using Lookup fields to define relationships:
    • Deletion of parent records will not result in a cascade delete of related child records; this can be enabled via Salesforce Support, though this setting will not be packaged.
    • Unlike with Master-Detail, you can elect for the platform to enforce referential integrity during the creation of the field by utilizing the Don't allow deletion of the lookup record that's part of a lookup relationship option.
    • Currently, the Rollup Summary fields are not supported when using a Lookup relationship.

Lookup fields of either kind are automatically indexed by the platform, making queries, in some cases, faster. We will focus more on indexes in a later chapter. The maximum number of relationship fields per object is 40.

Tip

While it is possible to add new custom fields to objects that have already been packaged and released to your customers, you cannot add a new Master-Detail relationship to an object that has already been packaged.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.208.12