diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 150a18d64b68534244296e480de80c3460906c25..7edc4f630769531f50ab5ea39e4ed9bda8794506 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -824,10 +824,13 @@ protected function doSaveFieldItems(ContentEntityInterface $entity, array $names
       if ($update) {
         $default_revision = $entity->isDefaultRevision();
         if ($default_revision) {
+          // Remove the ID from the record to enable updates on SQL variants
+          // that prevent updating serial columns, for example, mssql.
+          unset($record->{$this->idKey});
           $this->database
             ->update($this->baseTable)
             ->fields((array) $record)
-            ->condition($this->idKey, $record->{$this->idKey})
+            ->condition($this->idKey, $entity->get($this->idKey)->value)
             ->execute();
         }
         if ($this->revisionTable) {
@@ -836,11 +839,15 @@ protected function doSaveFieldItems(ContentEntityInterface $entity, array $names
           }
           else {
             $record = $this->mapToStorageRecord($entity->getUntranslated(), $this->revisionTable);
+            // Remove the revision ID from the record to enable updates on SQL
+            // variants that prevent updating serial columns, for example,
+            // mssql.
+            unset($record->{$this->revisionKey});
             $entity->preSaveRevision($this, $record);
             $this->database
               ->update($this->revisionTable)
               ->fields((array) $record)
-              ->condition($this->revisionKey, $record->{$this->revisionKey})
+              ->condition($this->revisionKey, $entity->getRevisionId())
               ->execute();
           }
         }
@@ -1067,19 +1074,21 @@ protected function saveRevision(ContentEntityInterface $entity) {
           ->condition($this->idKey, $record->{$this->idKey})
           ->execute();
       }
+      // Make sure to update the new revision key for the entity.
+      $entity->{$this->revisionKey}->value = $record->{$this->revisionKey};
     }
     else {
+      // Remove the revision ID from the record to enable updates on SQL
+      // variants that prevent updating serial columns, for example,
+      // mssql.
+      unset($record->{$this->revisionKey});
       $this->database
         ->update($this->revisionTable)
         ->fields((array) $record)
-        ->condition($this->revisionKey, $record->{$this->revisionKey})
+        ->condition($this->revisionKey, $entity->getRevisionId())
         ->execute();
     }
-
-    // Make sure to update the new revision key for the entity.
-    $entity->{$this->revisionKey}->value = $record->{$this->revisionKey};
-
-    return $record->{$this->revisionKey};
+    return $entity->getRevisionId();
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Path/AliasStorage.php b/core/lib/Drupal/Core/Path/AliasStorage.php
index a02bc3534d0157ba61813f0dad1a9b8e567acdf5..b6898487197d0b2d9b67644918613fcedc9abb96 100644
--- a/core/lib/Drupal/Core/Path/AliasStorage.php
+++ b/core/lib/Drupal/Core/Path/AliasStorage.php
@@ -106,11 +106,11 @@ public function save($source, $alias, $langcode = LanguageInterface::LANGCODE_NO
         $this->catchException($e);
         $original = FALSE;
       }
-      $fields['pid'] = $pid;
       $query = $this->connection->update(static::TABLE)
         ->fields($fields)
         ->condition('pid', $pid);
       $pid = $query->execute();
+      $fields['pid'] = $pid;
       $fields['original'] = $original;
       $operation = 'update';
     }
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php
index 11841e1ec918781d46d6dc834b0ff86171af6ea0..826d1231988abc700bff885346f29c8e0d8185a7 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php
@@ -3,6 +3,7 @@
 namespace Drupal\KernelTests\Core\Entity;
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityStorageException;
 use Drupal\Core\Entity\RevisionLogInterface;
 use Drupal\Core\Entity\TypedData\EntityDataDefinition;
 use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface;
@@ -919,4 +920,33 @@ protected function doTestComputedProperties($entity_type) {
     $this->assertEqual($entity->field_test_text->processed, $target, format_string('%entity_type: Text is processed with the default filter.', ['%entity_type' => $entity_type]));
   }
 
+  /**
+   * Tests explicit entity ID assignment.
+   */
+  public function testEntityIdAssignment() {
+    $entity_type = 'entity_test';
+    /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
+    $storage = $this->container->get('entity_type.manager')->getStorage($entity_type);
+
+    // Check that an ID can be explicitly assigned on creation.
+    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
+    $entity = $this->createTestEntity($entity_type);
+    $entity_id = 3;
+    $entity->set('id', $entity_id);
+    $this->assertSame($entity_id, $entity->id());
+    $storage->save($entity);
+    $entity = $storage->loadUnchanged($entity->id());
+    $this->assertTrue($entity);
+
+    // Check that an explicitly-assigned ID is preserved on update.
+    $storage->save($entity);
+    $entity = $storage->loadUnchanged($entity->id());
+    $this->assertTrue($entity);
+
+    // Check that an ID cannot be explicitly assigned on update.
+    $this->setExpectedException(EntityStorageException::class);
+    $entity->set('id', $entity_id + 1);
+    $storage->save($entity);
+  }
+
 }