Register and update an Entity

Important

Some or all of this functionality is available as part of a preview release. The content and the functionality are subject to change.

Important

This document includes several references to the ISA95 semantic model. Visit the ISA95 website and store to purchase the ISA95 standards.

Manufacturing data solutions come with several out-of-the-box entities for the Manufacturing Operations Domain. You can find the detailed schema of these entities in the Data Model documentation. This article explains how to register a new entity in Manufacturing data solutions, the expected responses during registration, and how to update these entities.

To register a new entity or update existing entities in Manufacturing data solutions, you must have the Manufacturing Admin role.

Register Entity

Manufacturing data solutions allow you to register new entities, enabling data ingestion against these entities later. To register an entity, perform the following steps:

Request URL

POST https://{serviceUrl}/mds/service/entities

Request Payload

The Manufacturing data solutions service determines the default data store for an entity based on the parameters specified in the "tags" field. Currently, the "tags" field supports the following properties:

  • ingestionRate: Specifies the frequency at which data is ingested. Valid values for the ingestion rate include Minutes, Hourly, Daily, Weekly, and Monthly.

  • ingestionFormat: Specifies the format in which data is ingested. Valid values for the ingestion format are Batch and Stream.

  • storageType: Specifies the type of storage used for the entity's data. Valid values for the storage type are hot and cold.

It's worth noting that null or empty values are accepted in the "tags" properties. In such cases, the default data store is marked as Cosmos.

The dtdlSchemaUrl is a mandatory field when dealing with custom entities. It allows you to specify the URL where the DTDL (Digital Twin Definition Language) for the entity is stored.

The isProperNoun is an optional column field that is used during data ingestion. It assists with semantic understanding of questions by relating the value to the entity.

To obtain the dtdlSchemaUrl, follow these steps:

  1. Create a blob container within an existing storage account or create a new storage account.

  2. To ensure that you have the necessary permissions to upload a blob, make sure that you have the Azure RBAC built-in role Storage Blob Data Contributor or higher.

  3. Upload the entity DTDL you want to register to the blob container.

  4. Generate a Shared Access Signature (SAS) token for the blob container. This SAS token provides secure access to the container and its contents.

  5. The generated SAS token produces a blob SAS URL.

    Screenshot showing steps for SAS token generation.

  6. Encode the URL using URLEncoding which can be used as the dtdlSchemaUrl in the request payload to register the custom entity.

    Screenshot showing steps for SAS URL generation.

{
    "name": "name of entity",
    "semanticRelevantFlag": true, // Whether entity needs to be a node on graph
    "tags": {
        "ingestionRate": "",
        "ingestionFormat": "",
        "storageType": ""
        // etc. Tags that we have for an entity now
    },
    "columns": [
        {
            "name": "name",
            "description": "description",
            "type": "String",
            "mandatory": false,
            "semanticRelevantFlag": true,
            "isProperNoun": false,
            "groupBy": false,
            "primaryKey": false
        },
        {
            "mappingTableForNormalization": "",
            "name": "name",
            "displayName": "",
            "description": "description",
            "type": "Enum",
            "mandatory": false,
            "semanticRelevantFlag": true,
            "isProperNoun": false,
            "primaryKey": false,
            "groupBy": false,
            "enumValues": [
                "Operational Location",
                "Description"
            ]
        }
    ],
    "dtdlSchemaUrl": "https%3A%2F%2Fl2storage.blob.core.windows.net%2Fcustomentity%2FEntity.json"
}
Sample Entity `Order`
{
    "name": "Order",
    "semanticRelevantFlag": true,
    "columns": [
        {
            "name": "orderId",
            "displayName": "orderId",
            "description": "A unique identification for an order",
            "type": "String",
            "mandatory": true,
            "semanticRelevantFlag": true,
            "isProperNoun": false,
            "primaryKey": true,
            "groupBy": false
        },
        {
            "name": "numberOfOrderLines",
            "displayName": "Number of Order Lines",
            "description": "The number of Order Line Items associated with the Order.",
            "type": "String",
            "mandatory": false,
            "semanticRelevantFlag": true,
            "isProperNoun": false,
            "primaryKey": false,
            "groupBy": false
        },
        {
            "name": "orderReceivedTimestamp",
            "displayName": "Order Received Timestamp",
            "description": "The timestamp that the Order was received from the Customer/Customer Account.",
            "type": "DateTime",
            "mandatory": false,
            "semanticRelevantFlag": true,
            "isProperNoun": false,
            "primaryKey": false,
            "groupBy": false
        },
        {
            "name": "totalOrderWeight",
            "displayName": "Total Order Weight",
            "description": "The total weight of the Order.",
            "type": "double",
            "mandatory": false,
            "semanticRelevantFlag": true,
            "isProperNoun": false,
            "primaryKey": false,
            "groupBy": false
        },
        {
            "name": "orderProcessingStatus",
            "displayName": "Order Processing Status",
            "description": "Order Processing Status",
            "type": "String",
            "mandatory": false,
            "semanticRelevantFlag": true,
            "isProperNoun": false,
            "primaryKey": false,
            "groupBy": false
        }
    ],
    "tags": {
        "ingestionFormat": "Batch",
        "ingestionRate": "Daily",
        "storageType": "Hot"
    },
    "dtdlSchemaUrl": "https%3A%2F%2Fl2storage.blob.core.windows.net%2Fcustomentity%2FOrder.json"
}

Response Payload

Headers

Operation-Location https%3a%2f%2f{serviceUrl}%2fmds%2fservice%2fentities%2fstatus%2fRegisterEntity%2fdc87115b6c4c4700bcd1bba5aa95a1a6

To check the progress of the entity registration, you can make a GET API call to the returned encoded URL after decoding it.

Sample Register Entity Response
[
    {
        "name": "Equipmentprt",
        "tags": {
            "entityDataType": "Undefined",
            "ingestionFormat": "Batch",
            "ingestionRate": "Weekly",
            "storage": "Cold",
            "dataSamplingRate": "Undefined"
        },
        "columns": [
            {
                "name": "ID",
                "displayName": "ID",
                "description": "A unique identification of a specific Equipment segment specification.",
                "type": "Alphanumeric",
                "mandatory": true,
                "semanticRelevantFlag": true,
                "isProperNoun": false
            },
            {
                "name": "description",
                "displayName": "Description",
                "description": "Contains additional information and descriptions of the Equipment segment specification definition.",
                "type": "String",
                "mandatory": false,
                "semanticRelevantFlag": true,
                "isProperNoun": false
            },
            {
                "name": "hierarchyScope",
                "displayName": "Hierarchy Scope",
                "description": "Identifies where the exchanged information fits within the role-based Physical Asset hierarchy. Optionally, hierarchy scope defines the scope of the Equipment class definition, such as the site or area where it's defined.",
                "type": "Enum",
                "mandatory": false,
                "semanticRelevantFlag": true,
                "isProperNoun": false
            },
            {
                "name": "operationalLocation",
                "displayName": "Operational location",
                "description": "Identifies the operational location of the Equipment resource(s) specified by this Equipment segment specification.",
                "type": "Alphanumeric",
                "mandatory": false,
                "semanticRelevantFlag": true,
                "isProperNoun": false
            },
            {
                "name": "operationalLocationType",
                "displayName": "Operational location type",
                "description": "Indicates whether the operational location attribute refers to an operational location object or contains a description of the operational location. Mandatory where an operational location attribute is specified. Defined values are operational location: operational location attribute references an operational location; description: operational location attribute contains a description of the operational location, such as a street address.",
                "type": "Enum",
                "mandatory": false,
                "semanticRelevantFlag": true,
                "isProperNoun": false
            },
            {
                "name": "equipmentUse",
                "displayName": "Equipment use",
                "description": "Defines the expected use of the Equipment class or equipment in the context of the process segment.",
                "type": "String",
                "mandatory": false,
                "semanticRelevantFlag": true,
                "isProperNoun": false
            },
            {
                "name": "quantity",
                "displayName": "Quantity",
                "description": "Specifies the Equipment resource required for the parent process segment.",
                "type": "float",
                "mandatory": false,
                "semanticRelevantFlag": true,
                "isProperNoun": false
            },
            {
                "name": "MESSystemRefID",
                "displayName": "MES system reference id",
                "description": "Manufacturing system Ref ID (MES Person Reference ID)",
                "type": "Alphanumeric",
                "mandatory": false,
                "semanticRelevantFlag": false,
                "isProperNoun": false
            }
        ],
        "storageInfo": {
            "defaultStore": "Cosmos",
            "adtModelId": "dtmi:digitaltwins:isa95:BaseModel;1"
        },
        "semanticRelevantFlag": true
    }
]

Expected responses during Entity registration

Error Message Code Error Description
Accepted 202 The request payload is valid and has successfully been sent for registration
Entity can't be null 400 The request payload must not be null
Entity name can’t be null or empty 400 In the request payload used for entity registration, "Name" property at root level can't be null or empty
Tags can't be null 400 In the request payload used for entity registration, "Tags" property can't be null as it's a mandatory field
DTDL Schema URI must not be null and it must be valid as Semantic Relevance is marked true 400 In the request payload used for entity registration, "semanticRelevantFlag" is marked as true. So DTDL Schema URI("dtdlSchemaUrl") must be defined and must contain a valid URL
Entity must contain at least one valid column 400 The request payload used for entity registration must have at least one valid Column
Column can't be null 400 In the request payload used for entity registration, Column property has to be defined
Column name can’t be null or empty 400 In the request payload used for entity registration, "Name" property inside Column property shouldn't be null or empty
Entity must contain at least one column with a primary key 400 The request payload used for entity registration must have at least one column with a primary key boolean flag marked as true
All Columns flagged as Primary must also be flagged as Mandatory 400 In the request payload used for entity registration, all columns that have "Primary" set to true must also have "Mandatory" set to true
At least one column must be flagged with Semantic Relevance as Entity's Semantic Relevance is marked true 400 In the request payload, if "semanticRelevantFlag" at root level is marked as true, then there must be at least one column whose "semanticRelevantFlag" is set to true
Type defined is Enum but Enum values aren't present 400 In the request payload, for one/some of the columns, "Type" defined is ENUM but "EnumValues" aren't present

Entity Update

Manufacturing data solutions offers Entity Update features to update or patch existing entities. Updating out of the box entities isn't allowed currently except for updating mapping table information. Entity registration creates an entity with default version of 1. When you run the update API, a new document for the entity gets created with an incremented version. The Patch API only updates the existing version of an entity. Following is the list of API supported for entity update.

Validate Entity Update

Manufacturing data solutions exposes an API to validate the update entity request payload before hitting the actual API. This API validates the request against the schema and returns the validation result. It returns all possible changes that happen to the entity and data if the request is valid. It also returns an error message if the request is invalid.

POST https://{serviceUrl}/mds/service/entities/validate

Sample Validate Update Entity Request
{
  "name": "Order",
  "semanticRelevantFlag": true,
  "columns": [
    {
      "name": "orderId",
      "displayName": "orderId",
      "description": "A unique identification for an order.",
      "type": "String",
      "mandatory": true,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": true,
      "groupBy": false
    },
    {
      "name": "numberOfOrderLines",
      "displayName": "Number of Order Lines",
      "description": "The number of Order Line Items associated with the Order.",
      "type": "Alphanumeric",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false
    },
    {
      "name": "orderReceivedTimestamp",
      "displayName": "Order Received Timestamp",
      "description": "The timestamp that the Order was received from the Customer/Customer Account.",
      "type": "DateTime",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false
    },
    {
      "name": "totalOrderCount",
      "displayName": "Total Order Count",
      "description": "The total count of the Order.",
      "type": "Integer",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false
    },
    {
      "name": "orderProcessingStatus",
      "displayName": "order Processing Status",
      "description": "order Processing Status",
      "type": "Alphanumeric",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false
    },
    {
      "name": "orderProcessingStatus1",
      "displayName": "order Processing Status1",
      "description": "order Processing Status1",
      "type": "Alphanumeric",
      "mandatory": false,
      "semanticRelevantFlag": false,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false
    }
  ],
  "Tags": {
    "ingestionFormat": "Batch",
    "ingestionRate": "Daily",
    "storageType": "Hot"
  },
  "dtdlSchemaUrl": "https://prtdls.blob.core.windows.net/entityblob/OrderV4.json"
}
Sample Validate Update Entity Response
{
  "entityName": "Order",
  "dtdlChangeRequired": true,
  "propertiesToBeAdded": [
    "orderOwner2"
  ],
  "propertiesToBeDeleted": [
    "orderOwner1"
  ],
  "relationshipsToBeAdded": [
    "include -> dtmi:digitaltwins:isa95:MaterialLot;1"
  ],
  "relationshipsToBeDeleted": [
    "contains -> dtmi:digitaltwins:isa95:MaterialLot;1"
  ]
}

Consider the following validations for entity updation:

  1. Entity name should be registered before updating the entity.
  2. Only addition/deletion of columns and relationships are allowed.
  3. Updating column/relationship properties aren't allowed.
  4. Addition/deletion of primary key columns isn't allowed as it impacts the data.
  5. Updating OOTB entity isn't allowed.
  6. Both columns and dtdl properties should be in sync.

Update Entity

A PUT request is used when you want to update to a new version of entity with all details. A typical update entity payload is as shown which is similar to the register entity payload.

PUT https://{serviceUrl}/mds/service/entities

Sample Update Entity Request
{
  "name": "Order",
  "semanticRelevantFlag": true,
  "columns": [
    {
      "name": "orderId",
      "displayName": "orderId",
      "description": "A unique identification for an order.",
      "type": "String",
      "mandatory": true,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": true,
      "groupBy": false
    },
    {
      "name": "numberOfOrderLines",
      "displayName": "Number of Order Lines",
      "description": "The number of Order Line Items associated with the Order.",
      "type": "Alphanumeric",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false
    },
    {
      "name": "orderReceivedTimestamp",
      "displayName": "Order Received Timestamp",
      "description": "The timestamp that the Order was received from the Customer/Customer Account.",
      "type": "DateTime",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false
    },
    {
      "name": "totalOrderCount",
      "displayName": "Total Order Count",
      "description": "The total count of the Order.",
      "type": "Integer",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false
    },
    {
      "name": "orderProcessingStatus",
      "displayName": "order Processing Status",
      "description": "order Processing Status",
      "type": "Alphanumeric",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false
    },
    {
      "name": "orderProcessingStatus1",
      "displayName": "order Processing Status1",
      "description": "order Processing Status1",
      "type": "Alphanumeric",
      "mandatory": false,
      "semanticRelevantFlag": false,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false
    }
  ],
  "Tags": {
    "ingestionFormat": "Batch",
    "ingestionRate": "Daily",
    "storageType": "Hot"
  },
  "dtdlSchemaUrl": "https://prtdls.blob.core.windows.net/entityblob/OrderV4.json"
}
Sample Update Entity Response
  1. When additions of columns/relationships are successful, response is 201 Created.
  2. When deletions of columns/relationships are successful, response is 202 Accepted and operation-location has link to the background job that is running to delete properties and relationships. Client can poll the job status using the link.

Patch Entity

You can patch an existing entity using the Patch API. Using this one can only modify existing columns of registered entity. Currently modification of mappingTableForNormalization column is only supported. A typical patch entity payload is as shown and client needs to send etag of entity along with payload in if-match header.

PATCH https://{serviceUrl}/mds/service/entities

Sample Patch Entity Request
{
  "name": "Order",
  "columns": [
    {
      "mappingTableForNormalization": "mappingTableName",
      "name": "orderId"
    }
  ]
}
Sample Patch Entity Response
{
  "name": "Order",
  "semanticRelevantFlag": true,
  "Columns": [
    {
      "mappingTableForNormalization": "mappingTableName",
      "displayName": "orderId",
      "description": "A unique identification for an order.",
      "type": "String",
      "mandatory": true,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": true,
      "groupBy": false,
      "name": "orderId"
    },
    {
      "mappingTableForNormalization": "",
      "displayName": "Number of Order Lines",
      "description": "The number of Order Line Items associated with the Order.",
      "type": "Alphanumeric",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false,
      "name": "numberOfOrderLines"
    },
    {
      "mappingTableForNormalization": "",
      "displayName": "Order Received Timestamp",
      "description": "The timestamp that the Order was received from the Customer/Customer Account.",
      "type": "DateTime",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false,
      "name": "orderReceivedTimestamp"
    },
    {
      "mappingTableForNormalization": "",
      "displayName": "Total Order Weight",
      "description": "The total weight of the Order.",
      "type": "Double",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false,
      "name": "totalOrderWeight"
    },
    {
      "mappingTableForNormalization": "",
      "displayName": "order Processing Status",
      "description": "order Processing Status",
      "type": "Alphanumeric",
      "mandatory": false,
      "semanticRelevantFlag": true,
      "isProperNoun": false,
      "primaryKey": false,
      "groupBy": false,
      "name": "orderProcessingStatus"
    }
  ],
  "Tags": {
    "ingestionFormat": "Batch",
    "ingestionRate": "Daily",
    "storageType": "Hot"
  },
  "DtdlSchema": {
    "@context": "dtmi:dtdl:context;2",
    "@id": "dtmi:digitaltwins:syndbtemp:Order;1",
    "@type": "Interface",
    "displayName": "Order",
    "description": "A document or commission to order products.",
    "comment": "According to Manufacturing.Order in Synapse Database Template",
    "contents": [
      {
        "@type": "Relationship",
        "name": "contains",
        "displayName": "Contains",
        "description": "This material lot is contained in this Order",
        "target": "dtmi:digitaltwins:isa95:MaterialLot;1"
      },
      {
        "@type": "Property",
        "name": "orderId",
        "displayName": "Order Id",
        "description": "The unique number that identifies an Order.",
        "schema": "string"
      },
      {
        "@type": "Property",
        "name": "numberOfOrderLines",
        "displayName": "Number of Order Lines",
        "description": "The number of Order Line Items associated with the Order.",
        "schema": "string"
      },
      {
        "@type": "Property",
        "name": "orderReceivedTimestamp",
        "displayName": "Order Received Timestamp",
        "description": "The timestamp that the Order was received from the Customer/Customer Account.",
        "schema": "dateTime"
      },
      {
        "@type": "Property",
        "name": "totalOrderWeight",
        "displayName": "Total Order Weight",
        "description": "The total weight of the Order.",
        "schema": "float"
      },
      {
        "@type": "Property",
        "name": "orderProcessingStatus",
        "displayName": "Order Processing Status",
        "description": "Order Processing Status.",
        "schema": "string"
      }
    ]
  },
  "Version": 1,
  "eTag": "sample-Etag",
}

Delete Entity

A DELETE request is used when you want to delete the custom entity.

DELETE https://{serviceUrl}/mds/service/entities/{Entity Name}

Response codes

Code Name Description
200 Accepted Successful deletion of entity
400 Bad request In case of deletion request for out of the box entity
401 Unauthorized Unable to authenticate the request
403 Forbidden Insufficient role access: (e.g. you do not have the right role or you are not added to the registration)
404 Not Found In case of delete request for entity which is not present
500 Server Error In case of any service specific errors