diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 689655a..7e8f4f7 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -783,7 +783,60 @@ protected function doSaveFieldItems(ContentEntityInterface $entity, array $names
         elseif ($table_mapping->requiresDedicatedTableStorage($storage_definition)) {
           $dedicated_table_fields[] = $name;
         }
-      }
+        $is_new = $entity->isNew();
+        if (!$is_new) {
+          if ($entity->isDefaultRevision()) {
+            $this->database
+              ->update($this->baseTable)
+              ->fields((array) $record)
+              ->condition($this->idKey, $entity->id())
+              ->execute();
+            $return = SAVED_UPDATED;
+          }
+          else {
+            // @todo, should a different value be returned when saving an entity
+            // with $isDefaultRevision = FALSE?
+            $return = FALSE;
+          }
+          if ($this->revisionTable) {
+            $entity->{$this->revisionKey}->value = $this->saveRevision($entity);
+          }
+          if ($this->dataTable) {
+            $this->savePropertyData($entity);
+          }
+          if ($this->revisionDataTable) {
+            $this->savePropertyData($entity, $this->revisionDataTable);
+          }
+          if ($this->revisionTable) {
+            $entity->setNewRevision(FALSE);
+          }
+        }
+        else {
+          // Ensure the entity is still seen as new after assigning it an id,
+          // while storing its data.
+          $entity->enforceIsNew();
+          $insert_id = $this->database
+            ->insert($this->baseTable, array('return' => Database::RETURN_INSERT_ID))
+            ->fields((array) $record)
+            ->execute();
+          // Even if this is a new entity the ID key might have been set, in which
+          // case we should not override the provided ID. An ID key that is not set
+          // to any value is interpreted as NULL (or DEFAULT) and thus overridden.
+          $entity_id = $entity->id();
+          if (empty($entity_id)) {
+            $entity->{$this->idKey}->value = (string) $insert_id;
+          }
+          $return = SAVED_NEW;
+          if ($this->revisionTable) {
+            $entity->setNewRevision();
+            $entity->{$this->revisionKey}->value = $this->saveRevision($entity);
+          }
+          if ($this->dataTable) {
+            $this->savePropertyData($entity);
+          }
+          if ($this->revisionDataTable) {
+            $this->savePropertyData($entity, $this->revisionDataTable);
+          }
     }
 
     // Update shared table records if necessary.
@@ -943,14 +996,31 @@ protected function mapToStorageRecord(ContentEntityInterface $entity, $table_nam
         if (!empty($definition->getSchema()['columns'][$column_name]['serialize'])) {
           $value = serialize($value);
         }
-
-        // Do not set serial fields if we do not have a value. This supports all
-        // SQL database drivers.
-        // @see https://www.drupal.org/node/2279395
         $value = drupal_schema_get_field_value($definition->getSchema()['columns'][$column_name], $value);
-        if (!(empty($value) && $this->isColumnSerial($table_name, $schema_name))) {
-          $record->$schema_name = $value;
+
+        // Allow IDENTITY inserts (basically for D6 migration path)
+        // but most database engines will not allow an IDENTITY updates.
+        // MySQL's loose behaviour will swallow anything thrown at it
+        // but other engines are more strict in serial column handling.
+        if ($this->isColumnSerial($table_name, $schema_name)) {
+          $new = $entity->isNew();
+          // Do not add to storage record if the serial
+          // value is empty when creating and entity.
+          // (PostgreSQL)
+          // @see https://www.drupal.org/node/2279395
+          if ($new && empty($value)) {
+            continue;
+          }
+          // If this entity is not new, serial column
+          // is already populated and needs not to be set.
+          // (MS SQL Server)
+          // @see https://www.drupal.org/node/2342699
+          if (!$new) {
+            continue;
+          }
         }
+
+        $record->$schema_name = $value;
       }
     }
 
@@ -971,16 +1041,26 @@ protected function mapToStorageRecord(ContentEntityInterface $entity, $table_nam
    * @see \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::processBaseTable()
    * @see \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::processRevisionTable()
    */
-  protected function isColumnSerial($table_name, $schema_name) {
+  protected function isColumnSerial($table_name, $column) {
+    // Entities can only have a key, and this key must be serial. Also,
+    // there cannot be any other serial fields in an entity besides it's key.
+    // This behaviour is locked into SqlContentEntityStorageSchema.
+    // You actually define your entity key as 'integer' and it is
+    // SqlContentEntityStorageSchema::processIdentifierSchema that
+    // converts int to serial when generating the definitive schema
+    // used to populate database tables during their creation.
+    // There is no way to take a peek at the true schema from outside
+    // SqlContentEntityStorageSchema.
+    // @see https://www.drupal.org/node/2342699
     $result = FALSE;
 
     switch ($table_name) {
       case $this->baseTable:
-        $result = $schema_name == $this->idKey;
+        $result = $column == $this->idKey;
         break;
 
       case $this->revisionTable:
-        $result = $schema_name == $this->revisionKey;
+        $result = $column == $this->revisionKey;
         break;
     }
 
@@ -1027,13 +1107,14 @@ protected function saveRevision(ContentEntityInterface $entity) {
         ->execute();
       // Even if this is a new revision, the revision ID key might have been
       // set in which case we should not override the provided revision ID.
-      if (!isset($record->{$this->revisionKey})) {
-        $record->{$this->revisionKey} = $insert_id;
+      $revision_id = $entity->getRevisionId();
+      if (empty($revision_id)) {
+        $entity->{$this->revisionKey}->value = $insert_id;
       }
       if ($entity->isDefaultRevision()) {
         $this->database->update($this->entityType->getBaseTable())
-          ->fields(array($this->revisionKey => $record->{$this->revisionKey}))
-          ->condition($this->idKey, $record->{$this->idKey})
+          ->fields(array($this->revisionKey => $entity->getRevisionId()))
+          ->condition($this->idKey, $entity->id())
           ->execute();
       }
     }
@@ -1041,14 +1122,11 @@ protected function saveRevision(ContentEntityInterface $entity) {
       $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();
   }
 
   /**
