Manage Azure Digital Twins models

This article describes how to manage the models in your Azure Digital Twins instance. Management operations include upload, validation, retrieval, and deletion of models.

Prerequisites

To work with Azure Digital Twins in this article, you'll need an Azure Digital Twins instance and the required permissions for using it. If you already have an Azure Digital Twins instance set up, you can use that instance and skip to the next section. Otherwise, follow the instructions in Set up an instance and authentication. The instructions contain information to help you verify that you've completed each step successfully.

After you set up your instance, make a note of the instance's host name. You can find the host name in the Azure portal.

Developer interfaces

This article highlights how to complete different management operations using the .NET (C#) SDK. You can also craft these same management calls using the other language SDKs described in Azure Digital Twins APIs and SDKs.

Other developer interfaces that can be used to complete these operations include:

Visualization

Azure Digital Twins Explorer is a visual tool for exploring the data in your Azure Digital Twins graph. You can use the explorer to view, query, and edit your models, twins, and relationships.

To read about the Azure Digital Twins Explorer tool, see Azure Digital Twins Explorer. For detailed steps on how to use its features, see Use Azure Digital Twins Explorer.

Here's what the visualization looks like:

Screenshot of Azure Digital Twins Explorer showing a sample model graph.

Create models

You can create your own models from scratch, or use existing ontologies that are available for your industry.

Author models

Models for Azure Digital Twins are written in DTDL, and saved as JSON files. There's also a DTDL extension available for Visual Studio Code, which provides syntax validation and other features to make it easier to write DTDL documents.

Consider an example in which a hospital wants to digitally represent their rooms. Each room contains a smart soap dispenser for monitoring hand-washing, and sensors to monitor traffic through the room.

The first step towards the solution is to create models to represent aspects of the hospital. A patient room in this scenario might be described like this:

{
    "@id": "dtmi:com:contoso:PatientRoom;1",
    "@type": "Interface",
    "@context": "dtmi:dtdl:context;3",
    "displayName": "Patient Room",
    "contents": [
      {
        "@type": "Property",
        "name": "visitorCount",
        "schema": "double"
      },
      {
        "@type": "Property",
        "name": "handWashCount",
        "schema": "double"
      },
      {
        "@type": "Property",
        "name": "handWashPercentage",
        "schema": "double"
      },
      {
        "@type": "Relationship",
        "name": "hasDevices"
      }
    ]
  }

Note

This is a sample body for a JSON file in which a model is defined and saved, to be uploaded as part of a client project. The REST API call, on the other hand, takes an array of model definitions like the one above (which is mapped to a IEnumerable<string> in the .NET SDK). So to use this model in the REST API directly, surround it with brackets.

This model defines a name and a unique ID for the patient room, and properties to represent visitor count and hand-wash status. These counters will be updated from motion sensors and smart soap dispensers, and will be used together to calculate a handwash percentage property. The model also defines a relationship hasDevices, which will be used to connect any digital twins based on this Room model to the actual devices.

Note

There are some DTDL features that Azure Digital Twins doesn't currently support, including the writable attribute on properties and relationships, and minMultiplicity and maxMultiplicity for relationships. For more information, see Service-specific DTDL notes.

Following this method, you can define models for the hospital's wards, zones, or the hospital itself.

If your goal is to build a comprehensive model set that describes your industry domain, consider whether there's an existing industry ontology that you can use to make model authoring easier. The next section describes industry ontologies in more detail.

Use existing industry-standard ontologies

An ontology is a set of models that comprehensively describe a given domain, like manufacturing, building structures, IoT systems, smart cities, energy grids, web content, and more.

If your solution is for a certain industry that uses any sort of modeling standard, consider starting with a pre-existing set of models designed for your industry instead of designing your models from scratch. Microsoft has partnered with domain experts to create DTDL model ontologies based on industry standards, to help minimize reinvention and encourage consistency and simplicity across industry solutions. You can read more about these ontologies, including how to use them and what ontologies are available now, in What is an ontology?.

Validate syntax

After creating a model, it's recommended to validate your models offline before uploading them to your Azure Digital Twins instance.

To help you validate your models, a .NET client-side DTDL parsing library is provided on NuGet: DTDLParser. You can use the parser library directly in your C# code. You can also view sample use of the parser in the DTDLParserResolveSample in GitHub.

Upload models

Once models are created, you can upload them to the Azure Digital Twins instance.

When you're ready to upload a model, you can use the following code snippet for the .NET SDK:

// 'client' is an instance of DigitalTwinsClient
// Read model file into string (not part of SDK)
// fileName is the name of the JSON model file
string dtdl = File.ReadAllText(fileName);
await client.CreateModelsAsync(new[] { dtdl });

On upload, model files are validated by the service.

You'll usually need to upload more than one model to the service. There are several ways that you can upload many models at once in a single transaction. To help you pick a strategy, consider the size of your model set as you continue through the rest of this section.

Upload small model sets

For smaller model sets, you can upload multiple models at once using individual API calls. You can check the current limit for how many models can be uploaded in a single API call in the Azure Digital Twins limits.

If you're using the SDK, you can upload multiple model files with the CreateModels method like this:

var dtdlFiles = Directory.EnumerateFiles(sourceDirectory, "*.json");

var dtdlModels = new List<string>();
foreach (string fileName in dtdlFiles)
{
    // Read model file into string (not part of SDK)
    string dtdl = File.ReadAllText(fileName);
    dtdlModels.Add(dtdl);
}
await client.CreateModelsAsync(dtdlModels);

If you're using the REST APIs or Azure CLI, you can upload multiple models by placing multiple model definitions in a single JSON file to be uploaded together. In this case, the models should be placed in a JSON array within the file, like in the following example:

[
    {
      "@id": "dtmi:com:contoso:Planet;1",
      "@type": "Interface",
      "@context": "dtmi:dtdl:context;3"
    },
    {
      "@id": "dtmi:com:contoso:Moon;1",
      "@type": "Interface",
      "@context": "dtmi:dtdl:context;3"
    }
]

Upload large model sets with the Import Jobs API

For large model sets, you can use the Import Jobs API to upload many models at once in a single API call. The API can simultaneously accept up to the Azure Digital Twins limit for number of models in an instance, and it automatically reorders models if needed to resolve dependencies between them. This method requires the use of Azure Blob Storage, as well as write permissions in your Azure Digital Twins instance for models and bulk jobs.

Tip

The Import Jobs API also allows twins and relationships to be imported in the same call, to create all parts of a graph at once. For more about this process, see Upload models, twins, and relationships in bulk with the Import Jobs API.

To import models in bulk, you'll need to structure your models (and any other resources included in the bulk import job) as an NDJSON file. The Models section comes immediately after Header section, making it the first graph data section in the file. You can view an example import file and a sample project for creating these files in the Import Jobs API introduction.

Next, the file needs to be uploaded into an append blob in Azure Blob Storage. For instructions on how to create an Azure storage container, see Create a container. Then, upload the file using your preferred upload method (some options are the AzCopy command, the Azure CLI, or the Azure portal).

Once the NDJSON file has been uploaded to the container, get its URL within the blob container. You'll use this value later in the body of the bulk import API call.

Here's a screenshot showing the URL value of a blob file in the Azure portal:

Screenshot of the Azure portal showing the URL of a file in a storage container.

Then, the file can be used in an Import Jobs API call. You'll provide the blob storage URL of the input file, as well as a new blob storage URL to indicate where you'd like the output log to be stored when it's created by the service.

Retrieve models

You can list and retrieve models stored on your Azure Digital Twins instance.

Your options include:

  • Retrieve a single model
  • Retrieve all models
  • Retrieve metadata and dependencies for models

Here are some example calls:

// 'client' is a valid DigitalTwinsClient object

// Get a single model, metadata and data
Response<DigitalTwinsModelData> md1 = await client.GetModelAsync("<model-Id>");
DigitalTwinsModelData model1 = md1.Value;

// Get a list of the metadata of all available models; print their IDs
AsyncPageable<DigitalTwinsModelData> md2 = client.GetModelsAsync();
await foreach (DigitalTwinsModelData md in md2)
{
    Console.WriteLine($"Type ID: {md.Id}");
}

// Get models and metadata for a model ID, including all dependencies (models that it inherits from, components it references)
AsyncPageable<DigitalTwinsModelData> md3 = client.GetModelsAsync(new GetModelsOptions { IncludeModelDefinition = true });

The SDK calls to retrieve models all return DigitalTwinsModelData objects. DigitalTwinsModelData contains metadata about the model stored in the Azure Digital Twins instance, such as name, DTMI, and creation date of the model. The DigitalTwinsModelData object also optionally includes the model itself. Meaning that, depending on parameters, you can use the retrieve calls to either retrieve just metadata (which is useful in scenarios where you want to display a UI list of available tools, for example), or the entire model.

The RetrieveModelWithDependencies call returns not only the requested model, but also all models that the requested model depends on.

Models aren't necessarily returned in exactly the document form they were uploaded in. Azure Digital Twins only guarantees that the return form will be semantically equivalent.

Update models

This section describes considerations and strategies for updating your models.

Before updating: Think in the context of your entire solution

Before making updates to your models, it's recommended to think holistically about your entire solution and the impact of the model changes you're about to make. Models in an Azure Digital Twins solution are often interconnected, so it's important to be aware of cascading changes where updating one model requires updating several others. Updating models will impact the twins that use the models, and can also affect ingress and processing code, client applications, and automated reports.

Here are some recommendations to help you manage your model transitions smoothly:

  • Instead of thinking of models as separate entities, consider evolving your entire model set when appropriate to keep models and their relationships up-to-date together.
  • Treat models like source code and manage them in source control. Apply the same rigor and attention to models and model changes that you apply to other code in your solution.

When you're ready to continue with the process of updating your models, the rest of this section describes the strategies you can use to implement the updates.

Strategies for updating models

Once a model is uploaded to your Azure Digital Twins instance, the model interface is immutable, which means there's no traditional "editing" of models. Azure Digital Twins also doesn't allow reupload of the same exact model while a matching model is already present in the instance.

Instead, if you want to make changes to a model—such as updating displayName or description, or adding and removing properties—you'll need to replace the original model.

There are two strategies to choose from when replacing a model:

  • Strategy 1: Upload new model version: Upload the model, with a new version number, and update your twins to use that new model. Both the new and old versions of the model will exist in your instance until you delete one.
    • Use this strategy when you want to update only some of your twins that use the model, or when you want to make sure twins stay conformant with their models and writable through the model transition.
  • Strategy 2: Delete old model and reupload: Delete the original model and upload the new model with the same name and ID (DTMI value) in its place. Completely replaces the old model with the new one.
    • Use this strategy when you want to update all twins that use this model at once, in addition to all code reacting to the models. If your model update contains a breaking change with the model update, twins will be nonconformant with their models for a short time while you're transitioning them from the old model to the new one, meaning that they won't be able to take any updates until the new model is uploaded and the twins conform to it.

Note

Making breaking changes to your models is discouraged outside of development.

Continue to the next sections to read more about each strategy option in detail.

Strategy 1: Upload new model version

This option involves creating a new version of the model and uploading it to your instance.

This operation doesn't overwrite earlier versions of the model, so multiple versions of the model will coexist in your instance until you remove them. Since the new model version and the old model version coexist, twins can use either the new version of the model or the older version, meaning that uploading a new version of a model doesn't automatically affect existing twins. The existing twins will remain as instances of the old model version, and you can update these twins to the new model version by patching them.

To use this strategy, follow the steps below.

1. Create and upload new model version

To create a new version of an existing model, start with the DTDL of the original model. Update, add, or remove the fields you want to change.

Next, mark this model as a newer version of the model by updating the id field of the model. The last section of the model ID, after the ;, represents the model number. To indicate that this model is now a more-updated version, increment the number at the end of the id value to any number greater than the current version number.

For example, if your previous model ID looked like this:

"@id": "dtmi:com:contoso:PatientRoom;1",

Version 2 of this model might look like this:

"@id": "dtmi:com:contoso:PatientRoom;2",

Then, upload the new version of the model to your instance.

This version of the model will then be available in your instance to use for digital twins. It doesn't overwrite earlier versions of the model, so multiple versions of the model now coexist in your instance.

2. Update graph elements as needed

Next, update the twins and relationships in your instance to use the new model version instead of the old.

You can use the following instructions to update twins and update relationships. The patch operation to update a twin's model will look something like this:

[
  {
    "op": "replace",
    "path": "/$metadata/$model",
    "value": "dtmi:example:foo;1"
  }
]

Important

When updating twins, use the same patch to update both the model ID (to the new model version) and any fields that must be altered on the twin to make it conform to the new model.

You may also need to update relationships and other models in your instance that reference this model, to make them refer to the new model version. You'll need to do another model update operation to achieve this purpose, so return to the beginning of this section and repeat the process for any more models that need updating.

3. (Optional) Decommission or delete old model version

If you won't be using the old model version anymore, you can decommission the older model. This action allows the model to keep existing in the instance, but it can't be used to create new digital twins.

You can also delete the old model completely if you don't want it in the instance anymore at all.

The sections linked above contain example code and considerations for decommissioning and deleting models.

Strategy 2: Delete old model and reupload

Instead of incrementing the version of a model, you can delete a model completely and reupload an edited model to the instance.

Azure Digital Twins doesn't remember the old model was ever uploaded, so this action will be like uploading an entirely new model. Twins that use the model will automatically switch over to the new definition once it's available. Depending on how the new definition differs from the old one, these twins may have properties and relationships that match the deleted definition and aren't valid with the new one, so you may need to patch them to make sure they remain valid.

To use this strategy, follow the steps below.

1. Delete old model

Since Azure Digital Twins doesn't allow two models with the same ID, start by deleting the original model from your instance.

Note

If you have other models that depend on this model (through inheritance or components), you'll need to remove those references before you can delete the model. You can update those dependent models first to temporarily remove the references, or delete the dependent models and reupload them in a later step.

Use the following instructions to delete your original model. This action will leave your twins that were using that model temporarily "orphaned," as they're now using a model that no longer exists. This state will be repaired in the next step when you reupload the updated model.

2. Create and upload new model

Start with the DTDL of the original model. Update, add, or remove the fields you want to change.

Then, upload the model to the instance, as though it were a new model being uploaded for the first time.

3. Update graph elements as needed

Now that your new model has been uploaded in place of the old one, the twins in your graph will automatically begin to use the new model definition once the caching in your instance expires and resets. This process may take 10-15 minutes or longer, depending on the size of your graph. After that, new and changed properties on your model should be accessible, and removed properties won't be accessible anymore.

Note

If you removed other dependent models earlier in order to delete the original model, reupload them now after the cache has reset. If you updated the dependent models to temporarily remove references to the original model, you can update them again to put the reference back.

Next, update the twins and relationships in your instance so their properties match the properties defined by the new model. Before this step is completed, the twins that don't match their model can still be read, but cannot be written to. For more information on the state of twins without a valid model, see Twins without models.

There are two ways to update twins and relationships for the new model so that they're writable again:

  • Patch the twins and relationships as needed so they fit the new model. You can use the following instructions to update twins and update relationships.
    • If you've added properties: Updating twins and relationships to have the new values isn't required, since twins missing the new values will still be valid twins. You can patch them however you want to add values for the new properties.
    • If you've removed properties: It's required to patch twins to remove the properties that are now invalid with the new model.
    • If you've updated properties: It's required to patch twins to update the values of changed properties to be valid with the new model.
  • Delete twins and relationships that use the model, and recreate them. You can use the following instructions to delete twins and recreate twins, and delete relationships and recreate relationships.
    • You might want to do this operation if you're making many changes to the model, and it will be difficult to update the existing twins to match it. However, recreation can be complicated if you have many twins that are interconnected by many relationships.

Remove models

Models can be removed from the service in one of two ways:

  • Decommissioning: Once a model is decommissioned, you can no longer use it to create new digital twins. Existing digital twins that already use this model aren't affected, so you can still update them with things like property changes and adding or deleting relationships.
  • Deletion: This operation will completely remove the model from the solution. Any twins that were using this model are no longer associated with any valid model, so they're treated as though they don't have a model at all. You can still read these twins, but you can't make any updates on them until they're reassigned to a different model.

These operations are separate features and they don't impact each other, although they may be used together to remove a model gradually.

Note

If you want to delete all models, twins, and relationships in an instance at once, use the Delete Jobs API.

Decommissioning

To decommission a model, you can use the DecommissionModel method from the SDK:

// 'client' is a valid DigitalTwinsClient
await client.DecommissionModelAsync(dtmiOfPlanetInterface);
// Write some code that deletes or transitions digital twins
//...

You can also decommission a model using the REST API call DigitalTwinModels Update. The decommissioned property is the only property that can be replaced with this API call. The JSON Patch document will look something like this:

[
  {
    "op": "replace",
    "path": "/decommissioned",
    "value": true
  }
]

A model's decommissioning status is included in the ModelData records returned by the model retrieval APIs.

Deletion

You can delete all models in your instance at once, or you can do it on an individual basis.

For an example of how to delete all models at the same time, see the End-to-end samples for Azure Digital Twins repository in GitHub. The CommandLoop.cs file contains a CommandDeleteAllModels function with code to delete all of the models in the instance.

To delete an individual model, follow the instructions and considerations from the rest of this section.

Before deletion: Deletion requirements

Generally, models can be deleted at any time.

The exception is models that other models depend on, either with an extends relationship or as a component. For example, if a ConferenceRoom model extends a Room model, and has a ACUnit model as a component, you can't delete Room or ACUnit until ConferenceRoom removes those respective references.

You can do so by updating the dependent model to remove the dependencies, or deleting the dependent model completely.

During deletion: Deletion process

Even if a model meets the requirements to delete it immediately, you may want to go through a few steps first to avoid unintended consequences for the twins left behind. Here are some steps that can help you manage the process:

  1. First, decommission the model
  2. Wait a few minutes, to make sure the service has processed any last-minute twin creation requests sent before the decommission
  3. Query twins by model to see all twins that are using the now-decommissioned model
  4. Delete the twins if you no longer need them, or patch them to a new model if needed. You can also choose to leave them alone, in which case they'll become twins without models once the model is deleted. See the next section for the implications of this state.
  5. Wait for another few minutes to make sure the changes have percolated through
  6. Delete the model

To delete a model, you can use the DeleteModel SDK call:

// 'client' is a valid DigitalTwinsClient
await client.DeleteModelAsync(IDToDelete);

You can also delete a model with the DigitalTwinModels Delete REST API call.

After deletion: Twins without models

Once a model is deleted, any digital twins that were using the model are now considered to be without a model. There's no query that can give you a list of all the twins in this state—although you can still query the twins by the deleted model to know what twins are affected.

Here's an overview of what you can and can't do with twins that don't have a model.

Things you can do:

  • Query the twin
  • Read properties
  • Read outgoing relationships
  • Add and delete incoming relationships (as in, other twins can still form relationships to this twin)
    • The target in the relationship definition can still reflect the DTMI of the deleted model. A relationship with no defined target can also work here.
  • Delete relationships
  • Delete the twin

Things you can't do:

  • Edit outgoing relationships (as in, relationships from this twin to other twins)
  • Edit properties

After deletion: Reuploading a model

After a model has been deleted, you may decide later to upload a new model with the same ID as the one you deleted. Here's what happens in that case.

  • From the solution store's perspective, this operation is the same as uploading an entirely new model. The service doesn't remember the old one was ever uploaded.
  • If there are any remaining twins in the graph referencing the deleted model, they're no longer orphaned; this model ID is valid again with the new definition. However, if the new definition for the model is different than the model definition that was deleted, these twins may have properties and relationships that match the deleted definition and aren't valid with the new one.

Azure Digital Twins doesn't prevent this state, so be careful to patch twins appropriately to make sure they remain valid through the model definition switch.

Convert v2 models to v3

Azure Digital Twins supports DTDL versions 2 and 3 (shortened in the documentation to v2 and v3, respectively). V3 is the recommended choice based on its expanded capabilities. This section explains how to update an existing DTDL v2 model to DTDL v3.

  1. Update the context. The main feature that identifies a model as v2 or v3 is the @context field on the interface. To convert a model from v2 to v3, change the dtmi:dtdl:context;2 context value to dtmi:dtdl:context;3. For many models, this will be the only required change.
    1. Value in v2: "@context": "dtmi:dtdl:context;2"
    2. Value in v3: "@context": "dtmi:dtdl:context;3".
  2. If needed, update semantic types. In DTDL v2, semantic types are natively supported. In DTDL v3, they are included with the QuantitativeTypes feature extension. So, if your v2 model used semantic types, you'll need to add the feature extension when converting the model to v3. To do this, first change the @context field on the interface from a single value to an array of values, then add the value dtmi:dtdl:extension:quantitativeTypes;1.
    1. Value in v2: "@context": "dtmi:dtdl:context;2"
    2. Value in v3: "@context": ["dtmi:dtdl:context;3", "dtmi:dtdl:extension:quantitativeTypes;1"]
  3. If needed, consider size limits. V2 and v3 have different size limits, so if your interface is very large, you may want to review the limits in the differences between DTDL v2 and v3.

After these changes, a former DTDL v2 model has been converted to a DTDL v3 model.

You might also want to consider new capabilities of DTDL v3, such as array-type properties, version relaxation, and additional feature extensions, to see if any of them would be beneficial additions. For a complete list of differences between DTDL v2 and v3, see Changes from Version 2 in the DTDL v3 Language Description.

Next steps

See how to create and manage digital twins based on your models: