diff --git a/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
index 4fd6a32..bf7d5ef 100644
--- a/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
+++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
@@ -3,6 +3,7 @@
 namespace Drupal\Core\Entity\Sql;

 use Drupal\Core\Entity\ContentEntityTypeInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;

 /**
@@ -18,6 +19,34 @@ class DefaultTableMapping implements TableMappingInterface {
   protected $entityType;

   /**
+   * The base table of the entity.
+   *
+   * @var string
+   */
+  protected $baseTable;
+
+  /**
+   * The table that stores revisions, if the entity supports revisions.
+   *
+   * @var string
+   */
+  protected $revisionTable;
+
+  /**
+   * The table that stores properties, if the entity has multilingual support.
+   *
+   * @var string
+   */
+  protected $dataTable;
+
+  /**
+   * The table that stores revision field data if the entity supports revisions.
+   *
+   * @var string
+   */
+  protected $revisionDataTable;
+
+  /**
    * The field storage definitions of this mapping.
    *
    * @var \Drupal\Core\Field\FieldStorageDefinitionInterface[]
@@ -87,6 +116,162 @@ class DefaultTableMapping implements TableMappingInterface {
   public function __construct(ContentEntityTypeInterface $entity_type, array $storage_definitions) {
     $this->entityType = $entity_type;
     $this->fieldStorageDefinitions = $storage_definitions;
+
+    $this->initializeMapping();
+  }
+
+  /**
+   * Initialize the table mapping.
+   */
+  public function initializeMapping() {
+    $revisionable = $this->entityType->isRevisionable();
+    $translatable = $this->entityType->isTranslatable();
+
+    // @todo Remove table names from the entity type definition in
+    //   https://www.drupal.org/node/2232465.
+    $this->baseTable = $this->entityType->getBaseTable() ?: $this->entityType->id();
+    if ($revisionable) {
+      $this->revisionTable = $this->entityType->getRevisionTable() ?: $this->entityType->id() . '_revision';
+    }
+    if ($translatable) {
+      $this->dataTable = $this->entityType->getDataTable() ?: $this->entityType->id() . '_field_data';
+    }
+    if ($revisionable && $translatable) {
+      $this->revisionDataTable = $this->entityType->getRevisionDataTable() ?: $this->entityType->id() . '_field_revision';
+    }
+
+    $id_key = $this->entityType->getKey('id');
+    $revision_key = $this->entityType->getKey('revision');
+    $bundle_key = $this->entityType->getKey('bundle');
+    $uuid_key = $this->entityType->getKey('uuid');
+    $langcode_key = $this->entityType->getKey('langcode');
+
+    $shared_table_definitions = array_filter($this->fieldStorageDefinitions, function (FieldStorageDefinitionInterface $definition) {
+      return $this->allowsSharedTableStorage($definition);
+    });
+
+    $key_fields = array_values(array_filter([$id_key, $revision_key, $bundle_key, $uuid_key, $langcode_key]));
+    $all_fields = array_keys($shared_table_definitions);
+    $revisionable_fields = array_keys(array_filter($shared_table_definitions, function (FieldStorageDefinitionInterface $definition) {
+      return $definition->isRevisionable();
+    }));
+    // Make sure the key fields come first in the list of fields.
+    $all_fields = array_merge($key_fields, array_diff($all_fields, $key_fields));
+
+    $revisionable = $this->entityType->isRevisionable();
+    $revision_metadata_fields = $revisionable ? array_values($this->entityType->getRevisionMetadataKeys()) : [];
+
+    $translatable = $this->entityType->isTranslatable();
+    if (!$revisionable && !$translatable) {
+      // The base layout stores all the base field values in the base table.
+      $this->setFieldNames($this->baseTable, $all_fields);
+    }
+    elseif ($revisionable && !$translatable) {
+      // The revisionable layout stores all the base field values in the base
+      // table, except for revision metadata fields. Revisionable fields
+      // denormalized in the base table but also stored in the revision table
+      // together with the entity ID and the revision ID as identifiers.
+      $this->setFieldNames($this->baseTable, array_diff($all_fields, $revision_metadata_fields));
+      $revision_key_fields = [$id_key, $revision_key];
+      $this->setFieldNames($this->revisionTable, array_merge($revision_key_fields, $revisionable_fields));
+    }
+    elseif (!$revisionable && $translatable) {
+      // Multilingual layouts store key field values in the base table. The
+      // other base field values are stored in the data table, no matter
+      // whether they are translatable or not. The data table holds also a
+      // denormalized copy of the bundle field value to allow for more
+      // performant queries. This means that only the UUID is not stored on
+      // the data table.
+      $this
+        ->setFieldNames($this->baseTable, $key_fields)
+        ->setFieldNames($this->dataTable, array_values(array_diff($all_fields, [$uuid_key]));
+    }
+    elseif ($revisionable && $translatable) {
+      // The revisionable multilingual layout stores key field values in the
+      // base table, except for language, which is stored in the revision
+      // table along with revision metadata. The revision data table holds
+      // data field values for all the revisionable fields and the data table
+      // holds the data field values for all non-revisionable fields. The data
+      // field values of revisionable fields are denormalized in the data
+      // table, as well.
+      $this->setFieldNames($this->baseTable, array_values($key_fields));
+
+      // Like in the multilingual, non-revisionable case the UUID is not
+      // in the data table. Additionally, do not store revision metadata
+      // fields in the data table.
+      $data_fields = array_values(array_diff($all_fields, [$uuid_key], $revision_metadata_fields));
+      $this->setFieldNames($this->dataTable, $data_fields);
+
+      $revision_base_fields = array_merge([$id_key, $revision_key, $langcode_key], $revision_metadata_fields);
+      $this->setFieldNames($this->revisionTable, $revision_base_fields);
+
+      $revision_data_key_fields = [$id_key, $revision_key, $langcode_key];
+      $revision_data_fields = array_diff($revisionable_fields, $revision_metadata_fields, [$langcode_key]);
+      $this->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields));
+    }
+
+    // Add dedicated tables.
+    $dedicated_table_definitions = array_filter($this->fieldStorageDefinitions, function (FieldStorageDefinitionInterface $definition) {
+      return $this->requiresDedicatedTableStorage($definition);
+    });
+    $extra_columns = [
+      'bundle',
+      'deleted',
+      'entity_id',
+      'revision_id',
+      'langcode',
+      'delta',
+    ];
+    foreach ($dedicated_table_definitions as $field_name => $definition) {
+      $tables = [$this->getDedicatedDataTableName($definition)];
+      if ($revisionable && $definition->isRevisionable()) {
+        $tables[] = $this->getDedicatedRevisionTableName($definition);
+      }
+      foreach ($tables as $table_name) {
+        $this->setFieldNames($table_name, [$field_name]);
+        $this->setExtraColumns($table_name, $extra_columns);
+      }
+    }
+  }
+
+  /**
+   * Gets the base table name.
+   *
+   * @return string
+   *   The table name.
+   */
+  public function getBaseTable() {
+    return $this->baseTable;
+  }
+
+  /**
+   * Gets the revision table name.
+   *
+   * @return string|false
+   *   The table name or FALSE if it is not available.
+   */
+  public function getRevisionTable() {
+    return $this->revisionTable;
+  }
+
+  /**
+   * Gets the data table name.
+   *
+   * @return string|false
+   *   The table name or FALSE if it is not available.
+   */
+  public function getDataTable() {
+    return $this->dataTable;
+  }
+
+  /**
+   * Gets the revision data table name.
+   *
+   * @return string|false
+   *   The table name or FALSE if it is not available.
+   */
+  public function getRevisionDataTable() {
+    return $this->revisionDataTable;
   }

   /**
@@ -143,17 +328,13 @@ public function getFieldTableName($field_name) {
       // where field data is stored, otherwise the base table is responsible for
       // storing field data. Revision metadata is an exception as it's stored
       // only in the revision table.
-      // @todo The table mapping itself should know about entity tables. See
-      //   https://www.drupal.org/node/2274017.
-      /** @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $storage */
-      $storage = \Drupal::entityManager()->getStorage($this->entityType->id());
       $storage_definition = $this->fieldStorageDefinitions[$field_name];
-      $table_names = [
-        $storage->getDataTable(),
-        $storage->getBaseTable(),
-        $storage->getRevisionTable(),
+      $table_names = array_filter([
+        $this->dataTable,
+        $this->baseTable,
+        $this->revisionTable,
         $this->getDedicatedDataTableName($storage_definition),
-      ];
+      ]);

       // Collect field columns.
       $field_columns = [];
@@ -161,7 +342,7 @@ public function getFieldTableName($field_name) {
         $field_columns[] = $this->getFieldColumnName($storage_definition, $property_name);
       }

-      foreach (array_filter($table_names) as $table_name) {
+      foreach ($table_names as $table_name) {
         $columns = $this->getAllColumns($table_name);
         // We assume finding one field column belonging to the mapping is enough
         // to identify the field table.
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index d696a94..3361010 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -170,27 +170,19 @@ protected function initTableLayout() {
     // are correctly reflected in the table layout.
     $this->tableMapping = NULL;
     $this->revisionKey = NULL;
-    $this->revisionTable = NULL;
-    $this->dataTable = NULL;
-    $this->revisionDataTable = NULL;
-
-    // @todo Remove table names from the entity type definition in
-    //   https://www.drupal.org/node/2232465.
-    $this->baseTable = $this->entityType->getBaseTable() ?: $this->entityTypeId;
-    $revisionable = $this->entityType->isRevisionable();
-    if ($revisionable) {
+
+    $this->baseTable = $this->getTableMapping()->getBaseTable();
+    $this->revisionTable = $this->getTableMapping()->getRevisionTable();
+    $this->dataTable = $this->getTableMapping()->getDataTable();
+    $this->revisionDataTable = $this->getTableMapping()->getRevisionDataTable();
+
+    if ($this->entityType->isRevisionable()) {
       $this->revisionKey = $this->entityType->getKey('revision') ?: 'revision_id';
-      $this->revisionTable = $this->entityType->getRevisionTable() ?: $this->entityTypeId . '_revision';
     }
-    $translatable = $this->entityType->isTranslatable();
-    if ($translatable) {
-      $this->dataTable = $this->entityType->getDataTable() ?: $this->entityTypeId . '_field_data';
+    if ($translatable = $this->entityType->isTranslatable()) {
       $this->langcodeKey = $this->entityType->getKey('langcode');
       $this->defaultLangcodeKey = $this->entityType->getKey('default_langcode');
     }
-    if ($revisionable && $translatable) {
-      $this->revisionDataTable = $this->entityType->getRevisionDataTable() ?: $this->entityTypeId . '_field_revision';
-    }
   }

   /**
@@ -248,25 +240,6 @@ protected function getStorageSchema() {
   }

   /**
-   * Updates the wrapped entity type definition.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
-   *   The update entity type.
-   *
-   * @internal Only to be used internally by Entity API. Expected to be
-   *   removed by https://www.drupal.org/node/2274017.
-   */
-  public function setEntityType(EntityTypeInterface $entity_type) {
-    if ($this->entityType->id() == $entity_type->id()) {
-      $this->entityType = $entity_type;
-      $this->initTableLayout();
-    }
-    else {
-      throw new EntityStorageException("Unsupported entity type {$entity_type->id()}");
-    }
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function getTableMapping(array $storage_definitions = NULL) {
@@ -276,101 +249,10 @@ public function getTableMapping(array $storage_definitions = NULL) {
     // case, we can statically cache the computed table mapping. If a new set
     // of field storage definitions is passed, for instance when comparing old
     // and new storage schema, we compute the table mapping without caching.
-    // @todo Clean-up this in https://www.drupal.org/node/2274017 so we can
-    //   easily instantiate a new table mapping whenever needed.
     if (!isset($this->tableMapping) || $storage_definitions) {
       $definitions = $storage_definitions ?: $this->entityManager->getFieldStorageDefinitions($this->entityTypeId);
       $table_mapping = new DefaultTableMapping($this->entityType, $definitions);

-      $shared_table_definitions = array_filter($definitions, function (FieldStorageDefinitionInterface $definition) use ($table_mapping) {
-        return $table_mapping->allowsSharedTableStorage($definition);
-      });
-
-      $key_fields = array_values(array_filter([$this->idKey, $this->revisionKey, $this->bundleKey, $this->uuidKey, $this->langcodeKey]));
-      $all_fields = array_keys($shared_table_definitions);
-      $revisionable_fields = array_keys(array_filter($shared_table_definitions, function (FieldStorageDefinitionInterface $definition) {
-        return $definition->isRevisionable();
-      }));
-      // Make sure the key fields come first in the list of fields.
-      $all_fields = array_merge($key_fields, array_diff($all_fields, $key_fields));
-
-      // If the entity is revisionable, gather the fields that need to be put
-      // in the revision table.
-      $revisionable = $this->entityType->isRevisionable();
-      $revision_metadata_fields = $revisionable ? array_values($this->entityType->getRevisionMetadataKeys()) : [];
-
-      $translatable = $this->entityType->isTranslatable();
-      if (!$revisionable && !$translatable) {
-        // The base layout stores all the base field values in the base table.
-        $table_mapping->setFieldNames($this->baseTable, $all_fields);
-      }
-      elseif ($revisionable && !$translatable) {
-        // The revisionable layout stores all the base field values in the base
-        // table, except for revision metadata fields. Revisionable fields
-        // denormalized in the base table but also stored in the revision table
-        // together with the entity ID and the revision ID as identifiers.
-        $table_mapping->setFieldNames($this->baseTable, array_diff($all_fields, $revision_metadata_fields));
-        $revision_key_fields = [$this->idKey, $this->revisionKey];
-        $table_mapping->setFieldNames($this->revisionTable, array_merge($revision_key_fields, $revisionable_fields));
-      }
-      elseif (!$revisionable && $translatable) {
-        // Multilingual layouts store key field values in the base table. The
-        // other base field values are stored in the data table, no matter
-        // whether they are translatable or not. The data table holds also a
-        // denormalized copy of the bundle field value to allow for more
-        // performant queries. This means that only the UUID is not stored on
-        // the data table.
-        $table_mapping
-          ->setFieldNames($this->baseTable, $key_fields)
-          ->setFieldNames($this->dataTable, array_values(array_diff($all_fields, [$this->uuidKey])));
-      }
-      elseif ($revisionable && $translatable) {
-        // The revisionable multilingual layout stores key field values in the
-        // base table, except for language, which is stored in the revision
-        // table along with revision metadata. The revision data table holds
-        // data field values for all the revisionable fields and the data table
-        // holds the data field values for all non-revisionable fields. The data
-        // field values of revisionable fields are denormalized in the data
-        // table, as well.
-        $table_mapping->setFieldNames($this->baseTable, array_values($key_fields));
-
-        // Like in the multilingual, non-revisionable case the UUID is not
-        // in the data table. Additionally, do not store revision metadata
-        // fields in the data table.
-        $data_fields = array_values(array_diff($all_fields, [$this->uuidKey], $revision_metadata_fields));
-        $table_mapping->setFieldNames($this->dataTable, $data_fields);
-
-        $revision_base_fields = array_merge([$this->idKey, $this->revisionKey, $this->langcodeKey], $revision_metadata_fields);
-        $table_mapping->setFieldNames($this->revisionTable, $revision_base_fields);
-
-        $revision_data_key_fields = [$this->idKey, $this->revisionKey, $this->langcodeKey];
-        $revision_data_fields = array_diff($revisionable_fields, $revision_metadata_fields, [$this->langcodeKey]);
-        $table_mapping->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields));
-      }
-
-      // Add dedicated tables.
-      $dedicated_table_definitions = array_filter($definitions, function (FieldStorageDefinitionInterface $definition) use ($table_mapping) {
-        return $table_mapping->requiresDedicatedTableStorage($definition);
-      });
-      $extra_columns = [
-        'bundle',
-        'deleted',
-        'entity_id',
-        'revision_id',
-        'langcode',
-        'delta',
-      ];
-      foreach ($dedicated_table_definitions as $field_name => $definition) {
-        $tables = [$table_mapping->getDedicatedDataTableName($definition)];
-        if ($revisionable && $definition->isRevisionable()) {
-          $tables[] = $table_mapping->getDedicatedRevisionTableName($definition);
-        }
-        foreach ($tables as $table_name) {
-          $table_mapping->setFieldNames($table_name, [$field_name]);
-          $table_mapping->setExtraColumns($table_name, $extra_columns);
-        }
-      }
-
       // Cache the computed table mapping only if we are using our internal
       // storage definitions.
       if (!$storage_definitions) {
@@ -644,7 +526,7 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value
    *   A SelectQuery object for loading the entity.
    */
   protected function buildQuery($ids, $revision_id = FALSE) {
-    $query = $this->database->select($this->entityType->getBaseTable(), 'base');
+    $query = $this->database->select($this->baseTable, 'base');

     $query->addTag($this->entityTypeId . '_load_multiple');

@@ -719,7 +601,7 @@ public function delete(array $entities) {
   protected function doDeleteFieldItems($entities) {
     $ids = array_keys($entities);

-    $this->database->delete($this->entityType->getBaseTable())
+    $this->database->delete($this->baseTable)
       ->condition($this->idKey, $ids, 'IN')
       ->execute();

@@ -1040,7 +922,7 @@ protected function saveRevision(ContentEntityInterface $entity) {
         $record->{$this->revisionKey} = $insert_id;
       }
       if ($entity->isDefaultRevision()) {
-        $this->database->update($this->entityType->getBaseTable())
+        $this->database->update($this->baseTable)
           ->fields([$this->revisionKey => $record->{$this->revisionKey}])
           ->condition($this->idKey, $record->{$this->idKey})
           ->execute();
@@ -1399,12 +1281,6 @@ public function onEntityTypeDelete(EntityTypeInterface $entity_type) {
   public function onFieldStorageDefinitionCreate(FieldStorageDefinitionInterface $storage_definition) {
     // If we are adding a field stored in a shared table we need to recompute
     // the table mapping.
-    // @todo This does not belong here. Remove it once we are able to generate a
-    //   fresh table mapping in the schema handler. See
-    //   https://www.drupal.org/node/2274017.
-    if ($this->getTableMapping()->allowsSharedTableStorage($storage_definition)) {
-      $this->tableMapping = NULL;
-    }
     $this->wrapSchemaException(function () use ($storage_definition) {
       $this->getStorageSchema()->onFieldStorageDefinitionCreate($storage_definition);
     });
@@ -1632,16 +1508,7 @@ public function countFieldData($storage_definition, $as_bool = FALSE) {
     elseif ($table_mapping->allowsSharedTableStorage($storage_definition)) {
       // Ascertain the table this field is mapped too.
       $field_name = $storage_definition->getName();
-      try {
-        $table_name = $table_mapping->getFieldTableName($field_name);
-      }
-      catch (SqlContentEntityStorageException $e) {
-        // This may happen when changing field storage schema, since we are not
-        // able to use a table mapping matching the passed storage definition.
-        // @todo Revisit this once we are able to instantiate the table mapping
-        //   properly. See https://www.drupal.org/node/2274017.
-        $table_name = $this->dataTable ?: $this->baseTable;
-      }
+      $table_name = $table_mapping->getFieldTableName($field_name);
       $query = $this->database->select($table_name, 't');
       $or = $query->orConditionGroup();
       foreach (array_keys($storage_definition->getColumns()) as $property_name) {
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
index f9dd0c0..ed87047 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
@@ -353,23 +353,19 @@ public function onEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeI
   public function onEntityTypeDelete(EntityTypeInterface $entity_type) {
     $this->checkEntityType($entity_type);
     $schema_handler = $this->database->schema();
-    $actual_definition = $this->entityManager->getDefinition($entity_type->id());
-    // @todo Instead of switching the wrapped entity type, we should be able to
-    //   instantiate a new table mapping for each entity type definition. See
-    //   https://www.drupal.org/node/2274017.
-    $this->storage->setEntityType($entity_type);
+
+    $field_storage_definitions = $this->entityManager->getLastInstalledFieldStorageDefinitions($entity_type->id());
+    $this->originalDefinitions = $field_storage_definitions;
+    $table_mapping = new DefaultTableMapping($entity_type, $field_storage_definitions);

     // Delete entity tables.
-    foreach ($this->getEntitySchemaTables() as $table_name) {
+    foreach ($this->getEntitySchemaTables($table_mapping) as $table_name) {
       if ($schema_handler->tableExists($table_name)) {
         $schema_handler->dropTable($table_name);
       }
     }

     // Delete dedicated field tables.
-    $field_storage_definitions = $this->entityManager->getLastInstalledFieldStorageDefinitions($entity_type->id());
-    $this->originalDefinitions = $field_storage_definitions;
-    $table_mapping = $this->storage->getTableMapping($field_storage_definitions);
     foreach ($field_storage_definitions as $field_storage_definition) {
       // If we have a field having dedicated storage we need to drop it,
       // otherwise we just remove the related schema data.
@@ -382,8 +378,6 @@ public function onEntityTypeDelete(EntityTypeInterface $entity_type) {
     }
     $this->originalDefinitions = NULL;

-    $this->storage->setEntityType($actual_definition);
-
     // Delete the entity schema.
     $this->deleteEntitySchemaData($entity_type);
   }
@@ -414,17 +408,8 @@ public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $
     // Only configurable fields currently support purging, so prevent deletion
     // of ones we can't purge if they have existing data.
     // @todo Add purging to all fields: https://www.drupal.org/node/2282119.
-    try {
-      if (!($storage_definition instanceof FieldStorageConfigInterface) && $this->storage->countFieldData($storage_definition, TRUE)) {
-        throw new FieldStorageDefinitionUpdateForbiddenException('Unable to delete a field (' . $storage_definition->getName() . ' in ' . $storage_definition->getTargetEntityTypeId() . ' entity) with data that cannot be purged.');
-      }
-    }
-    catch (DatabaseException $e) {
-      // This may happen when changing field storage schema, since we are not
-      // able to use a table mapping matching the passed storage definition.
-      // @todo Revisit this once we are able to instantiate the table mapping
-      //   properly. See https://www.drupal.org/node/2274017.
-      return;
+    if (!($storage_definition instanceof FieldStorageConfigInterface) && $this->storage->countFieldData($storage_definition, TRUE)) {
+      throw new FieldStorageDefinitionUpdateForbiddenException('Unable to delete a field (' . $storage_definition->getName() . ' in ' . $storage_definition->getTargetEntityTypeId() . ' entity) with data that cannot be purged.');
     }

     // Retrieve a table mapping which contains the deleted field still.
@@ -502,15 +487,11 @@ protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $res
     $entity_type_id = $entity_type->id();

     if (!isset($this->schema[$entity_type_id]) || $reset) {
-      // Back up the storage definition and replace it with the passed one.
-      // @todo Instead of switching the wrapped entity type, we should be able
-      //   to instantiate a new table mapping for each entity type definition.
-      //   See https://www.drupal.org/node/2274017.
-      $actual_definition = $this->entityManager->getDefinition($entity_type_id);
-      $this->storage->setEntityType($entity_type);
+      $storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
+      $table_mapping = new DefaultTableMapping($entity_type, $storage_definitions);

       // Prepare basic information about the entity type.
-      $tables = $this->getEntitySchemaTables();
+      $tables = $this->getEntitySchemaTables($table_mapping);

       // Initialize the table schema.
       $schema[$tables['base_table']] = $this->initializeBaseTable($entity_type);
@@ -525,9 +506,7 @@ protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $res
       }

       // We need to act only on shared entity schema tables.
-      $table_mapping = $this->storage->getTableMapping();
       $table_names = array_diff($table_mapping->getTableNames(), $table_mapping->getDedicatedTableNames());
-      $storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
       foreach ($table_names as $table_name) {
         if (!isset($schema[$table_name])) {
           $schema[$table_name] = [];
@@ -576,9 +555,6 @@ protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $res
       }

       $this->schema[$entity_type_id] = $schema;
-
-      // Restore the actual definition.
-      $this->storage->setEntityType($actual_definition);
     }

     return $this->schema[$entity_type_id];
@@ -587,15 +563,18 @@ protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $res
   /**
    * Gets a list of entity type tables.
    *
+   * @param \Drupal\Core\Entity\Sql\TableMappingInterface $table_mapping
+   *   The SQL table mapping.
+   *
    * @return array
    *   A list of entity type tables, keyed by table key.
    */
-  protected function getEntitySchemaTables() {
+  protected function getEntitySchemaTables(TableMappingInterface $table_mapping) {
     return array_filter([
-      'base_table' => $this->storage->getBaseTable(),
-      'revision_table' => $this->storage->getRevisionTable(),
-      'data_table' => $this->storage->getDataTable(),
-      'revision_data_table' => $this->storage->getRevisionDataTable(),
+      'base_table' => $table_mapping->getBaseTable(),
+      'revision_table' => $table_mapping->getRevisionTable(),
+      'data_table' => $table_mapping->getDataTable(),
+      'revision_data_table' => $table_mapping->getRevisionDataTable(),
     ]);
   }

diff --git a/core/modules/views/src/EventSubscriber/ViewsEntitySchemaSubscriber.php b/core/modules/views/src/EventSubscriber/ViewsEntitySchemaSubscriber.php
index 6060ae4..993ee82 100644
--- a/core/modules/views/src/EventSubscriber/ViewsEntitySchemaSubscriber.php
+++ b/core/modules/views/src/EventSubscriber/ViewsEntitySchemaSubscriber.php
@@ -6,6 +6,7 @@
 use Drupal\Core\Entity\EntityTypeEventSubscriberTrait;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Entity\EntityTypeListenerInterface;
+use Drupal\Core\Entity\Sql\DefaultTableMapping;
 use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
 use Drupal\views\Views;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -312,11 +313,8 @@ protected function dataTableRename($all_views, $entity_type_id, $old_data_table,
    *   The base table.
    */
   protected function dataTableAddition($all_views, EntityTypeInterface $entity_type, $new_data_table, $base_table) {
-    /** @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $storage */
     $entity_type_id = $entity_type->id();
-    $storage = $this->entityManager->getStorage($entity_type_id);
-    $storage->setEntityType($entity_type);
-    $table_mapping = $storage->getTableMapping();
+    $table_mapping = new DefaultTableMapping($entity_type, $this->entityManager->getFieldStorageDefinitions($entity_type_id));
     $data_table_fields = $table_mapping->getFieldNames($new_data_table);
     $base_table_fields = $table_mapping->getFieldNames($base_table);

