diff --git a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
index 13959d5..70f52b7 100644
--- a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
@@ -164,17 +164,19 @@ protected function invokeHook($hook, EntityInterface $entity) {
    *   Associative array of query results, keyed on the entity ID.
    */
   protected function postLoad(array &$queried_entities) {
-    $entity_class = $this->entityInfo['class'];
-    $entity_class::postLoad($this, $queried_entities);
-    // Call hook_entity_load().
-    foreach (\Drupal::moduleHandler()->getImplementations('entity_load') as $module) {
-      $function = $module . '_entity_load';
-      $function($queried_entities, $this->entityType);
-    }
-    // Call hook_TYPE_load().
-    foreach (\Drupal::moduleHandler()->getImplementations($this->entityType . '_load') as $module) {
-      $function = $module . '_' . $this->entityType . '_load';
-      $function($queried_entities);
+    if (!empty($queried_entities)) {
+      $entity_class = $this->entityInfo['class'];
+      $entity_class::postLoad($this, $queried_entities);
+      // Call hook_entity_load().
+      foreach (\Drupal::moduleHandler()->getImplementations('entity_load') as $module) {
+        $function = $module . '_entity_load';
+        $function($queried_entities, $this->entityType);
+      }
+      // Call hook_TYPE_load().
+      foreach (\Drupal::moduleHandler()->getImplementations($this->entityType . '_load') as $module) {
+        $function = $module . '_' . $this->entityType . '_load';
+        $function($queried_entities);
+      }
     }
   }
 
diff --git a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
index 5251054..727a46b 100644
--- a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
+++ b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
@@ -7,11 +7,11 @@
 
 namespace Drupal\Core\Entity;
 
+use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Entity\Query\QueryInterface;
+use Drupal\Core\Field\PrepareCacheInterface;
 use Drupal\Core\Language\Language;
-use Drupal\Component\Utility\NestedArray;
-use Drupal\Component\Uuid\Uuid;
 use Drupal\field\FieldInfo;
 use Drupal\field\FieldUpdateForbiddenException;
 use Drupal\field\FieldInterface;
@@ -66,7 +66,23 @@ class FieldableDatabaseStorageController extends FieldableEntityStorageControlle
    *
    * @var boolean
    */
-  protected $cache;
+  protected $staticCache;
+
+  /**
+   * Whether this entity type should use the persistent cache.
+   *
+   * Set by entity info.
+   *
+   * @var boolean
+   */
+  protected $persistentCache;
+
+  /**
+   * Holds statically cached entities.
+   *
+   * @var array
+   */
+  protected $entities = array();
 
   /**
    * Active database connection.
@@ -83,6 +99,13 @@ class FieldableDatabaseStorageController extends FieldableEntityStorageControlle
   protected $fieldInfo;
 
   /**
+   * Cache backend.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cacheBackend;
+
+  /**
    * The entity bundle key.
    *
    * @var string|bool
@@ -104,7 +127,8 @@ public static function createInstance(ContainerInterface $container, $entity_typ
       $entity_type,
       $entity_info,
       $container->get('database'),
-      $container->get('field.info')
+      $container->get('field.info'),
+      $container->get('cache.entity')
     );
   }
 
@@ -119,15 +143,22 @@ public static function createInstance(ContainerInterface $container, $entity_typ
    *   The database connection to be used.
    * @param \Drupal\field\FieldInfo $field_info
    *   The field info service.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
+   *   Cache backend instance to use.
    */
-  public function __construct($entity_type, array $entity_info, Connection $database, FieldInfo $field_info) {
+  public function __construct($entity_type, array $entity_info, Connection $database, FieldInfo $field_info, CacheBackendInterface $cache) {
     parent::__construct($entity_type, $entity_info);
 
     $this->database = $database;
     $this->fieldInfo = $field_info;
+    $this->cacheBackend = $cache;
     $this->bundleKey = !empty($this->entityInfo['entity_keys']['bundle']) ? $this->entityInfo['entity_keys']['bundle'] : FALSE;
     $this->entityClass = $this->entityInfo['class'];
 
+    // Check if the entity type supports caching of loaded entities.
+    $this->staticCache = !empty($this->entityInfo['static_cache']);
+    $this->persistentCache = $this->entityInfo['field_cache'];
+
     // Check if the entity type supports IDs.
     if (isset($this->entityInfo['entity_keys']['id'])) {
       $this->idKey = $this->entityInfo['entity_keys']['id'];
@@ -202,47 +233,26 @@ public function create(array $values) {
    * {@inheritdoc}
    */
   public function loadMultiple(array $ids = NULL) {
-    $entities = array();
-
     // Create a new variable which is either a prepared version of the $ids
     // array for later comparison with the entity cache, or FALSE if no $ids
     // were passed. The $ids array is reduced as items are loaded from cache,
     // and we need to know if it's empty for this reason to avoid querying the
     // database when all requested entities are loaded from cache.
     $passed_ids = !empty($ids) ? array_flip($ids) : FALSE;
+
     // Try to load entities from the static cache, if the entity type supports
-    // static caching.
-    if ($this->cache && $ids) {
-      $entities += $this->cacheGet($ids);
-      // If any entities were loaded, remove them from the ids still to load.
-      if ($passed_ids) {
-        $ids = array_keys(array_diff_key($passed_ids, $entities));
-      }
-    }
+    // static caching. This will remove ID's that were loaded from $ids.
+    $entities_from_static_cache = $this->getFromStaticCache($ids);
 
-    // Load any remaining entities from the database. This is the case if $ids
-    // is set to NULL (so we load all entities) or if there are any ids left to
-    // load.
-    if ($ids === NULL || $ids) {
-      // Build and execute the query.
-      $query_result = $this->buildQuery($ids)->execute();
-      $queried_entities = $query_result->fetchAllAssoc($this->idKey);
-    }
+    $entities = $this->doLoadMultiple($ids);
 
     // Pass all entities loaded from the database through $this->postLoad(),
-    // which attaches fields (if supported by the entity type) and calls the
-    // entity type specific load callback, for example hook_node_load().
-    if (!empty($queried_entities)) {
-      $this->postLoad($queried_entities);
-      $entities += $queried_entities;
-    }
+    // to invoke the load hooks and postLoad() method on the entity class.
+    $this->postLoad($entities);
 
-    if ($this->cache) {
-      // Add entities to the cache.
-      if (!empty($queried_entities)) {
-        $this->cacheSet($queried_entities);
-      }
-    }
+    $this->setStaticCache($entities);
+
+    $entities += $entities_from_static_cache;
 
     // Ensure that the returned array is ordered the same as the original
     // $ids array if this was passed in and remove any invalid ids.
@@ -258,6 +268,58 @@ public function loadMultiple(array $ids = NULL) {
     return $entities;
   }
 
+  protected function doLoadMultiple($ids) {
+    if (is_array($ids) && empty($ids)) {
+      return array();
+    }
+
+    // Load remaining entities from the persistent cache.
+    $entities_from_cache = $this->loadMultipleFromCache($ids);
+
+    // Load any remaining entities from the database. This is the case if $ids
+    // is set to NULL (so we load all entities) or if there are any ids left to
+    // load.
+    $entities_from_storage = $this->loadMultipleFromStorage($ids);
+
+    $this->setPersistentCache($entities_from_storage);
+
+    return $entities_from_cache + $entities_from_storage;
+  }
+
+  protected function loadMultipleFromStorage($ids) {
+
+    $entities = array();
+
+    if ($ids === NULL || $ids) {
+      // Build and execute the query.
+      $query_result = $this->buildQuery($ids)->execute();
+      $records = $query_result->fetchAllAssoc($this->idKey);
+
+      // Map the loaded records into entity objects and according fields.
+      if ($records) {
+        $entities = $this->mapFromStorageRecords($records);
+
+        // Attach field values.
+        if ($this->entityInfo['fieldable']) {
+          $this->loadFieldItems($entities);
+        }
+      }
+    }
+
+    return $entities;
+  }
+
+  protected function loadMultipleFromCache($ids) {
+    if (!$this->persistentCache) {
+      return array();
+    }
+
+    $ids = !empty($ids) ? $ids : array();
+
+    // Load remaining entities from the persistent cache.
+    return $this->getFromPersistentCache($ids);
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -272,7 +334,7 @@ public function load($id) {
    * @param array $records
    *   Associative array of query results, keyed on the entity ID.
    *
-   * @return array
+   * @return \Drupal\Core\Entity\EntityInterface[]
    *   An array of entity objects implementing the EntityInterface.
    */
   protected function mapFromStorageRecords(array $records) {
@@ -386,15 +448,20 @@ protected function attachPropertyData(array &$entities) {
   public function loadRevision($revision_id) {
     // Build and execute the query.
     $query_result = $this->buildQuery(array(), $revision_id)->execute();
-    $queried_entities = $query_result->fetchAllAssoc($this->idKey);
+    if ($records = $query_result->fetchAllAssoc($this->idKey)) {
+      // Map the record to an entity.
+      $entities = $this->mapFromStorageRecords($records);
+
+      // Attach field values.
+      if ($this->entityInfo['fieldable']) {
+        $this->loadFieldItems($entities);
+      }
 
-    // Pass the loaded entities from the database through $this->postLoad(),
-    // which attaches fields (if supported by the entity type) and calls the
-    // entity type specific load callback, for example hook_node_load().
-    if (!empty($queried_entities)) {
-      $this->postLoad($queried_entities);
+      // Pass all entities loaded from the database through $this->postLoad(),
+      // to invoke the load hooks and postLoad() method on the entity class.
+      $this->postLoad($entities);
+      return reset($entities);
     }
-    return reset($queried_entities);
   }
 
   /**
@@ -523,32 +590,6 @@ protected function buildQuery($ids, $revision_id = FALSE) {
   }
 
   /**
-   * Attaches data to entities upon loading.
-   *
-   * This will attach fields, if the entity is fieldable. It calls
-   * hook_entity_load() for modules which need to add data to all entities.
-   * It also calls hook_TYPE_load() on the loaded entities. For example
-   * hook_node_load() or hook_user_load(). If your hook_TYPE_load()
-   * expects special parameters apart from the queried entities, you can set
-   * $this->hookLoadArguments prior to calling the method.
-   * See Drupal\node\NodeStorageController::attachLoad() for an example.
-   *
-   * @param $queried_entities
-   *   Associative array of query results, keyed on the entity ID.
-   */
-  protected function postLoad(array &$queried_entities) {
-    // Map the loaded records into entity objects and according fields.
-    $queried_entities = $this->mapFromStorageRecords($queried_entities);
-
-    // Attach field values.
-    if ($this->entityInfo['fieldable']) {
-      $this->loadFieldItems($queried_entities);
-    }
-
-    parent::postLoad($queried_entities);
-  }
-
-  /**
    * Implements \Drupal\Core\Entity\EntityStorageControllerInterface::delete().
    */
   public function delete(array $entities) {
@@ -857,9 +898,26 @@ public function getQueryServiceName() {
   }
 
   /**
-   * {@inheritdoc}
+   * Loads values of configurable fields for a group of entities.
+   *
+   * Loads all fields for each entity object in a group of a single entity type.
+   * The loaded field values are added directly to the entity objects.
+   *
+   * @param \Drupal\Core\Entity\ContentEntityInterface[] $entities
+   *   An array of entities keyed by entity ID.
    */
-  protected function doLoadFieldItems($entities, $age) {
+  protected function loadFieldItems(array $entities) {
+    if (empty($entities) || empty($this->entityInfo['fieldable'])) {
+      return;
+    }
+
+    $age = static::FIELD_LOAD_CURRENT;
+    foreach ($entities as $entity) {
+      if (!$entity->isDefaultRevision()) {
+        $age = static::FIELD_LOAD_REVISION;
+        break;
+      }
+    }
     $load_current = $age == static::FIELD_LOAD_CURRENT;
 
     // Collect entities ids, bundles and languages.
@@ -926,9 +984,14 @@ protected function doLoadFieldItems($entities, $age) {
   }
 
   /**
-   * {@inheritdoc}
+   * Saves values of configurable fields for an entity.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity.
+   * @param bool $update
+   *   TRUE if the entity is being updated, FALSE if it is being inserted.
    */
-  protected function doSaveFieldItems(EntityInterface $entity, $update) {
+  protected function saveFieldItems(EntityInterface $entity, $update = TRUE) {
     $vid = $entity->getRevisionId();
     $id = $entity->id();
     $bundle = $entity->bundle();
@@ -1011,9 +1074,12 @@ protected function doSaveFieldItems(EntityInterface $entity, $update) {
   }
 
   /**
-   * {@inheritdoc}
+   * Deletes values of configurable fields for all revisions of an entity.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity.
    */
-  protected function doDeleteFieldItems(EntityInterface $entity) {
+  protected function deleteFieldItems(EntityInterface $entity) {
     foreach ($this->fieldInfo->getBundleInstances($entity->entityType(), $entity->bundle()) as $instance) {
       $field = $instance->getField();
       $table_name = static::_fieldTableName($field);
@@ -1028,9 +1094,12 @@ protected function doDeleteFieldItems(EntityInterface $entity) {
   }
 
   /**
-   * {@inheritdoc}
+   * Deletes values of configurable fields for a single revision of an entity.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity. It must have a revision ID.
    */
-  protected function doDeleteFieldItemsRevision(EntityInterface $entity) {
+  protected function deleteFieldItemsRevision(EntityInterface $entity) {
     $vid = $entity->getRevisionId();
     if (isset($vid)) {
       foreach ($this->fieldInfo->getBundleInstances($entity->entityType(), $entity->bundle()) as $instance) {
@@ -1506,4 +1575,150 @@ static public function _fieldColumnName(FieldInterface $field, $column) {
     return in_array($column, Field::getReservedColumns()) ? $column : $field->getName() . '_' . $column;
   }
 
+  /**
+   * Gets entities from the static cache.
+   *
+   * @param array &$ids
+   *   If not empty, return entities that match these IDs. ID's that were found
+   *   will be removed from the list.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface[]
+   *   Array of entities from the entity cache.
+   */
+  protected function getFromStaticCache(&$ids) {
+    $entities = array();
+
+    if ($this->staticCache && $ids) {
+      $entities = array();
+      // Load any available entities from the internal cache.
+      if (!empty($this->entities)) {
+        foreach ($ids as $index => $id) {
+          if (isset($this->entities[$id])) {
+            $entities[$id] = $this->entities[$id];
+            // Remove the ID from the list.
+            unset($ids[$index]);
+          }
+        }
+      }
+    }
+    return $entities;
+  }
+
+  /**
+   * Stores entities in the static entity cache.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface[] $entities
+   *   Entities to store in the cache.
+   */
+  protected function setStaticCache(array $entities) {
+    if ($this->staticCache) {
+      $this->entities += $entities;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getFromPersistentCache(&$ids) {
+    $entities = array();
+    // Build the list of cache entries to retrieve.
+    $cids = array();
+    foreach ($ids as $id) {
+      $cids[] = $this->buildCacheId($id);
+    }
+    if ($cache = $this->cacheBackend->getMultiple($cids)) {
+      // Create entity objects based on the loaded values from the cache.
+      foreach ($ids as $index => $id) {
+        $cid = $this->buildCacheId($id);
+        if (isset($cache[$cid])) {
+          $values = $cache[$cid]->data['values'];
+          $translations = $cache[$cid]->data['translations'];
+          $bundle = $this->bundleKey ? $cache[$cid]->data['bundle'] : FALSE;
+          $entities[$id] = new $this->entityClass($values, $this->entityType, $bundle, $translations);
+          unset($ids[$index]);
+        }
+      }
+    }
+    return $entities;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setPersistentCache($entities) {
+    if (!$this->persistentCache) {
+      return;
+    }
+
+    foreach ($entities as $id => $entity) {
+      $data = array(
+        'id' => $entity->id(),
+        'bundle' => $entity->bundle(),
+        'translations' => array_keys($entity->getTranslationLanguages()),
+        'values' => array(),
+      );
+      $default_langcode = $entity->getUntranslated()->language()->id;
+      foreach ($entity->getTranslationLanguages() as $langcode => $language) {
+        $translation = $entity->getTranslation($langcode);
+
+        // Make sure the default language is valid.
+        if ($default_langcode == $langcode) {
+          $langcode = Language::LANGCODE_DEFAULT;
+        }
+
+        foreach ($translation as $field_name => $items) {
+          if (!$items->isEmpty()) {
+            foreach ($items as $delta => $item) {
+              // If the field item needs to be prepare the cache data, call
+              // the corresponding method, otherwise use the values as cache
+              // data.
+              if ($item instanceof PrepareCacheInterface) {
+                $data['values'][$field_name][$langcode][$delta] = $item->getCacheData();
+              }
+              else {
+                $data['values'][$field_name][$langcode][$delta] = $item->getValue();
+              }
+            }
+          }
+        }
+      }
+      $this->cacheBackend->set($this->buildCacheId($id), $data, CacheBackendInterface::CACHE_PERMANENT, array($this->entityType . '_values' => TRUE));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function resetCache(array $ids = NULL) {
+    if ($ids) {
+      $cids = array();
+      foreach ($ids as $id) {
+        unset($this->entities[$id]);
+        $cids[] = $this->buildCacheId($id);
+      }
+      if ($this->persistentCache) {
+        $this->cacheBackend->deleteMultiple($cids);
+      }
+    }
+    else {
+      $this->entities = array();
+      if ($this->persistentCache) {
+        $this->cacheBackend->deleteTags(array($this->entityType . '_values' => TRUE));
+      }
+    }
+  }
+
+  /**
+   * Returns the cache ID for the passed in entity ID.
+   *
+   * @param int $id
+   *   Entity ID for which the cache ID should be built.
+   *
+   * @return string
+   *   Cache ID that can be passed to the cache backend.
+   */
+  protected function buildCacheId($id) {
+    return "values:{$this->entityType}:$id";
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php b/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php
index b89625d..cb58ec7 100644
--- a/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php
+++ b/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php
@@ -7,216 +7,12 @@
 
 namespace Drupal\Core\Entity;
 
-use Drupal\Core\Field\PrepareCacheInterface;
 use Drupal\field\FieldInterface;
 use Drupal\field\FieldInstanceInterface;
-use Drupal\Core\Field\ConfigFieldItemListInterface;
-use Symfony\Component\DependencyInjection\Container;
 
 abstract class FieldableEntityStorageControllerBase extends EntityStorageControllerBase implements FieldableEntityStorageControllerInterface {
 
   /**
-   * Loads values of configurable fields for a group of entities.
-   *
-   * Loads all fields for each entity object in a group of a single entity type.
-   * The loaded field values are added directly to the entity objects.
-   *
-   * This method is a wrapper that handles the field data cache. Subclasses
-   * need to implement the doLoadFieldItems() method with the actual storage
-   * logic.
-   *
-   * @param array $entities
-   *   An array of entities keyed by entity ID.
-   */
-  protected function loadFieldItems(array $entities) {
-    if (empty($entities)) {
-      return;
-    }
-
-    $age = static::FIELD_LOAD_CURRENT;
-    foreach ($entities as $entity) {
-      if (!$entity->isDefaultRevision()) {
-        $age = static::FIELD_LOAD_REVISION;
-        break;
-      }
-    }
-
-    // Only the most current revision of non-deleted fields for cacheable entity
-    // types can be cached.
-    $load_current = $age == static::FIELD_LOAD_CURRENT;
-    $info = entity_get_info($this->entityType);
-    $use_cache = $load_current && $info['field_cache'];
-
-    // Assume all entities will need to be queried. Entities found in the cache
-    // will be removed from the list.
-    $queried_entities = $entities;
-
-    // Fetch available entities from cache, if applicable.
-    if ($use_cache) {
-      // Build the list of cache entries to retrieve.
-      $cids = array();
-      foreach ($entities as $id => $entity) {
-        $cids[] = "field:{$this->entityType}:$id";
-      }
-      $cache = cache('field')->getMultiple($cids);
-      // Put the cached field values back into the entities and remove them from
-      // the list of entities to query.
-      foreach ($entities as $id => $entity) {
-        $cid = "field:{$this->entityType}:$id";
-        if (isset($cache[$cid])) {
-          unset($queried_entities[$id]);
-          foreach ($cache[$cid]->data as $langcode => $values) {
-            $translation = $entity->getTranslation($langcode);
-            // We do not need to worry about field translatability here, the
-            // translation object will manage that automatically.
-            foreach ($values as $field_name => $items) {
-              $translation->$field_name = $items;
-            }
-          }
-        }
-      }
-    }
-
-    // Fetch other entities from their storage location.
-    if ($queried_entities) {
-      // Let the storage controller actually load the values.
-      $this->doLoadFieldItems($queried_entities, $age);
-
-      // Build cache data.
-      // @todo: Improve this logic to avoid instantiating field objects once
-      // the field logic is improved to not do that anyway.
-      if ($use_cache) {
-        foreach ($queried_entities as $id => $entity) {
-          $data = array();
-          foreach ($entity->getTranslationLanguages() as $langcode => $language) {
-            $translation = $entity->getTranslation($langcode);
-            foreach ($translation as $field_name => $items) {
-              if ($items instanceof ConfigFieldItemListInterface && !$items->isEmpty()) {
-                foreach ($items as $delta => $item) {
-                  // If the field item needs to prepare the cache data, call the
-                  // corresponding method, otherwise use the values as cache
-                  // data.
-                  if ($item instanceof PrepareCacheInterface) {
-                    $data[$langcode][$field_name][$delta] = $item->getCacheData();
-                  }
-                  else {
-                    $data[$langcode][$field_name][$delta] = $item->getValue();
-                  }
-                }
-              }
-            }
-          }
-          $cid = "field:{$this->entityType}:$id";
-          cache('field')->set($cid, $data);
-        }
-      }
-    }
-  }
-
-  /**
-   * Saves values of configurable fields for an entity.
-   *
-   * This method is a wrapper that handles the field data cache. Subclasses
-   * need to implement the doSaveFieldItems() method with the actual storage
-   * logic.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity.
-   * @param bool $update
-   *   TRUE if the entity is being updated, FALSE if it is being inserted.
-   */
-  protected function saveFieldItems(EntityInterface $entity, $update = TRUE) {
-    $this->doSaveFieldItems($entity, $update);
-
-    if ($update) {
-      $entity_info = $entity->entityInfo();
-      if ($entity_info['field_cache']) {
-        cache('field')->delete('field:' . $entity->entityType() . ':' . $entity->id());
-      }
-    }
-  }
-
-  /**
-   * Deletes values of configurable fields for all revisions of an entity.
-   *
-   * This method is a wrapper that handles the field data cache. Subclasses
-   * need to implement the doDeleteFieldItems() method with the actual storage
-   * logic.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity.
-   */
-  protected function deleteFieldItems(EntityInterface $entity) {
-    $this->doDeleteFieldItems($entity);
-
-    $entity_info = $entity->entityInfo();
-    if ($entity_info['field_cache']) {
-      cache('field')->delete('field:' . $entity->entityType() . ':' . $entity->id());
-    }
-  }
-
-  /**
-   * Deletes values of configurable fields for a single revision of an entity.
-   *
-   * This method is a wrapper that handles the field data cache. Subclasses
-   * need to implement the doDeleteFieldItemsRevision() method with the actual
-   * storage logic.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity. It must have a revision ID attribute.
-   */
-  protected function deleteFieldItemsRevision(EntityInterface $entity) {
-    $this->doDeleteFieldItemsRevision($entity);
-  }
-
-  /**
-   * Loads values of configurable fields for a group of entities.
-   *
-   * This is the method that holds the actual storage logic.
-   *
-   * @param array $entities
-   *   An array of entities keyed by entity ID.
-   * @param int $age
-   *   EntityStorageControllerInterface::FIELD_LOAD_CURRENT to load the most
-   *   recent revision for all fields, or
-   *   EntityStorageControllerInterface::FIELD_LOAD_REVISION to load the version
-   *   indicated by each entity.
-   */
-  abstract protected function doLoadFieldItems($entities, $age);
-
-  /**
-   * Saves values of configurable fields for an entity.
-   *
-   * This is the method that holds the actual storage logic.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity.
-   * @param bool $update
-   *   TRUE if the entity is being updated, FALSE if it is being inserted.
-   */
-  abstract protected function doSaveFieldItems(EntityInterface $entity, $update);
-
-  /**
-   * Deletes values of configurable fields for all revisions of an entity.
-   *
-   * This is the method that holds the actual storage logic.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity.
-   */
-  abstract protected function doDeleteFieldItems(EntityInterface $entity);
-
-  /**
-   * Deletes values of configurable fields for a single revision of an entity.
-   *
-   * This is the method that holds the actual storage logic.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity.
-   */
-  abstract protected function doDeleteFieldItemsRevision(EntityInterface $entity);
-
-  /**
    * {@inheritdoc}
    */
   public function onFieldCreate(FieldInterface $field) { }
diff --git a/core/lib/Drupal/Core/Field/ConfigEntityReferenceItemBase.php b/core/lib/Drupal/Core/Field/ConfigEntityReferenceItemBase.php
index 61e6a5e..9be33ee 100644
--- a/core/lib/Drupal/Core/Field/ConfigEntityReferenceItemBase.php
+++ b/core/lib/Drupal/Core/Field/ConfigEntityReferenceItemBase.php
@@ -23,7 +23,7 @@ class ConfigEntityReferenceItemBase extends EntityReferenceItem {
   public function isEmpty() {
     // Avoid loading the entity by first checking the 'target_id'.
     $target_id = $this->target_id;
-    if (!empty($target_id)) {
+    if ($target_id !== NULL && $target_id !== '') {
       return FALSE;
     }
     // Allow auto-create entities.
diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
index e23af78..967e492 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
@@ -39,12 +39,12 @@ protected function buildQuery($ids, $revision_id = FALSE) {
   /**
    * {@inheritdoc}
    */
-  protected function postLoad(array &$queried_entities) {
+  protected function mapFromStorageRecords(array $records) {
     // Prepare standard comment fields.
-    foreach ($queried_entities as &$record) {
+    foreach ($records as $record) {
       $record->name = $record->uid ? $record->registered_name : $record->name;
     }
-    parent::postLoad($queried_entities);
+    return parent::mapFromStorageRecords($records);
   }
 
   /**
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
index 8f77373..814429e 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
@@ -235,7 +235,7 @@ function testFieldAttachPrepareViewMultiple() {
   function testFieldAttachCache() {
     // Initialize random values and a test entity.
     $entity_init = entity_create('entity_test', array('type' => $this->instance->bundle));
-    $langcode = Language::LANGCODE_NOT_SPECIFIED;
+    $langcode = Language::LANGCODE_DEFAULT;
     $values = $this->_generateTestFieldValues($this->field->getCardinality());
 
     // Non-cacheable entity type.
@@ -269,15 +269,15 @@ function testFieldAttachCache() {
     $entity = clone($entity_init);
     $entity->{$this->field_name_2} = $values;
     $entity->save();
-    $cid = "field:$entity_type:" . $entity->id();
+    $cid = "values:$entity_type:" . $entity->id();
     $this->assertFalse(cache('field')->get($cid), 'Cached: no cache entry on insert');
 
     // Load, and check that a cache entry is present with the expected values.
     $controller = $this->container->get('entity.manager')->getStorageController($entity->entityType());
     $controller->resetCache();
     $controller->load($entity->id());
-    $cache = cache('field')->get($cid);
-    $this->assertEqual($cache->data[$langcode][$this->field_name_2], $values, 'Cached: correct cache entry on load');
+    $cache = cache('entity')->get($cid);
+    $this->assertEqual($cache->data['values'][$this->field_name_2][$langcode], $values, 'Cached: correct cache entry on load');
 
     // Update with different values, and check that the cache entry is wiped.
     $values = $this->_generateTestFieldValues($this->field_2->getCardinality());
@@ -287,13 +287,13 @@ function testFieldAttachCache() {
     ));
     $entity->{$this->field_name_2} = $values;
     $entity->save();
-    $this->assertFalse(cache('field')->get($cid), 'Cached: no cache entry on update');
+    $this->assertFalse(cache('entity')->get($cid), 'Cached: no cache entry on update');
 
     // Load, and check that a cache entry is present with the expected values.
     $controller->resetCache();
     $controller->load($entity->id());
-    $cache = cache('field')->get($cid);
-    $this->assertEqual($cache->data[$langcode][$this->field_name_2], $values, 'Cached: correct cache entry on load');
+    $cache = cache('entity')->get($cid);
+    $this->assertEqual($cache->data['values'][$this->field_name_2][$langcode], $values, 'Cached: correct cache entry on load');
 
     // Create a new revision, and check that the cache entry is wiped.
     $entity = entity_create($entity_type, array(
@@ -309,12 +309,12 @@ function testFieldAttachCache() {
     // Load, and check that a cache entry is present with the expected values.
     $controller->resetCache();
     $controller->load($entity->id());
-    $cache = cache('field')->get($cid);
-    $this->assertEqual($cache->data[$langcode][$this->field_name_2], $values, 'Cached: correct cache entry on load');
+    $cache = cache('entity')->get($cid);
+    $this->assertEqual($cache->data['values'][$this->field_name_2][$langcode], $values, 'Cached: correct cache entry on load');
 
     // Delete, and check that the cache entry is wiped.
     $entity->delete();
-    $this->assertFalse(cache('field')->get($cid), 'Cached: no cache entry after delete');
+    $this->assertFalse(cache('entity')->get($cid), 'Cached: no cache entry after delete');
   }
 
   /**
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php
index d24042a..9751712 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php
@@ -82,6 +82,7 @@ function testDisableFilterModule() {
       'filters[filter_test_replace][status]' => 1,
     );
     $this->drupalPostForm('admin/config/content/formats/manage/' . $format_id, $edit, t('Save configuration'));
+    \Drupal::entityManager()->getStorageController('node')->resetCache(array($node->id()));
 
     // Verify that filter_test_replace filter replaced the content.
     $this->drupalGet('node/' . $node->id());
diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php
index d581147..b9ed58f 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php
@@ -61,11 +61,7 @@ function testUpdateAccess() {
     $this->assertResponse(200);
 
     // Access the update page as user 1.
-    $user1 = user_load(1);
-    $user1->pass_raw = user_password();
-    $user1->pass = $this->container->get('password')->hash(trim($user1->pass_raw));
-    db_query("UPDATE {users} SET pass = :pass WHERE uid = :uid", array(':pass' => $user1->getPassword(), ':uid' => $user1->id()));
-    $this->drupalLogin($user1);
+    $this->drupalLogin($this->root_user);
     $this->drupalGet($this->update_url, array('external' => TRUE));
     $this->assertResponse(200);
   }
diff --git a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
index 49d9f78..43e26f8 100644
--- a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
@@ -126,38 +126,36 @@ function testProcessedCache() {
     // Load the entity and check that the field cache contains the expected
     // data.
     $entity = entity_load($entity_type, $entity->id());
-    $cache = cache('field')->get("field:$entity_type:" . $entity->id());
-    $this->assertEqual($cache->data, array(
-      Language::LANGCODE_NOT_SPECIFIED => array(
-        'summary_field' => array(
-          0 => array(
-            'value' => $value,
-            'summary' => $summary,
-            'format' => 'plain_text',
-            'processed' => $value,
-            'summary_processed' => $summary,
-          ),
+    $cache = cache('entity')->get("values:$entity_type:" . $entity->id());
+    $this->assertEqual($cache->data['values']['summary_field'], array(
+      Language::LANGCODE_DEFAULT => array(
+        0 => array(
+          'value' => $value,
+          'summary' => $summary,
+          'format' => 'plain_text',
+          'processed' => $value,
+          'summary_processed' => $summary,
         ),
       ),
     ));
 
     // Inject fake processed values into the cache to make sure that these are
     // used as-is and not re-calculated when the entity is loaded.
-    $data = array(
-      Language::LANGCODE_NOT_SPECIFIED => array(
-        'summary_field' => array(
-          0 => array(
-            'value' => $value,
-            'summary' => $summary,
-            'format' => 'plain_text',
-            'processed' => 'Cached processed value',
-            'summary_processed' => 'Cached summary processed value',
-          ),
+    $data = $cache->data;
+    $data['values']['summary_field'] = array(
+      Language::LANGCODE_DEFAULT => array(
+        0 => array(
+          'value' => $value,
+          'summary' => $summary,
+          'format' => 'plain_text',
+          'processed' => 'Cached processed value',
+          'summary_processed' => 'Cached summary processed value',
         ),
       ),
     );
-    cache('field')->set("field:$entity_type:" . $entity->id(), $data);
-    $entity = entity_load($entity_type, $entity->id(), TRUE);
+    \Drupal::entityManager()->getStorageController($entity_type)->resetCache();
+    cache('entity')->set("values:$entity_type:" . $entity->id(), $data);
+    $entity = entity_load($entity_type, $entity->id());
     $this->assertEqual($entity->summary_field->processed, 'Cached processed value');
     $this->assertEqual($entity->summary_field->summary_processed, 'Cached summary processed value');
 
diff --git a/core/modules/user/lib/Drupal/user/UserStorageController.php b/core/modules/user/lib/Drupal/user/UserStorageController.php
index 23b2d27..328480f 100644
--- a/core/modules/user/lib/Drupal/user/UserStorageController.php
+++ b/core/modules/user/lib/Drupal/user/UserStorageController.php
@@ -8,6 +8,7 @@
 namespace Drupal\user;
 
 use Drupal\Component\Uuid\UuidInterface;
+use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Password\PasswordInterface;
 use Drupal\Core\Database\Connection;
@@ -49,15 +50,15 @@ class UserStorageController extends FieldableDatabaseStorageController implement
    *   The database connection to be used.
    * @param \Drupal\field\FieldInfo $field_info
    *   The field info service.
-   * @param \Drupal\Component\Uuid\UuidInterface $uuid_service
-   *   The UUID Service.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
+   *   Cache backend instance to use.
    * @param \Drupal\Core\Password\PasswordInterface $password
    *   The password hashing service.
    * @param \Drupal\user\UserDataInterface $user_data
    *   The user data service.
    */
-  public function __construct($entity_type, $entity_info, Connection $database, FieldInfo $field_info, UuidInterface $uuid_service, PasswordInterface $password, UserDataInterface $user_data) {
-    parent::__construct($entity_type, $entity_info, $database, $field_info, $uuid_service);
+  public function __construct($entity_type, $entity_info, Connection $database, FieldInfo $field_info, CacheBackendInterface $cache, PasswordInterface $password, UserDataInterface $user_data) {
+    parent::__construct($entity_type, $entity_info, $database, $field_info, $cache);
 
     $this->password = $password;
     $this->userData = $user_data;
@@ -72,7 +73,7 @@ public static function createInstance(ContainerInterface $container, $entity_typ
       $entity_info,
       $container->get('database'),
       $container->get('field.info'),
-      $container->get('uuid'),
+      $container->get('cache.entity'),
       $container->get('password'),
       $container->get('user.data')
     );
@@ -81,23 +82,20 @@ public static function createInstance(ContainerInterface $container, $entity_typ
   /**
    * {@inheritdoc}
    */
-  function postLoad(array &$queried_users) {
-    foreach ($queried_users as $key => $record) {
-      $queried_users[$key]->roles = array();
+  function mapFromStorageRecords(array $records) {
+    foreach ($records as $key => $record) {
+      $records[$key]->roles = array();
       if ($record->uid) {
-        $queried_users[$record->uid]->roles[] = DRUPAL_AUTHENTICATED_RID;
+        $records[$record->uid]->roles[] = DRUPAL_AUTHENTICATED_RID;
       }
       else {
-        $queried_users[$record->uid]->roles[] = DRUPAL_ANONYMOUS_RID;
+        $records[$record->uid]->roles[] = DRUPAL_ANONYMOUS_RID;
       }
     }
 
     // Add any additional roles from the database.
-    $this->addRoles($queried_users);
-
-    // Call the default postLoad() method. This will add fields and call
-    // hook_user_load().
-    parent::postLoad($queried_users);
+    $this->addRoles($records);
+    return parent::mapFromStorageRecords($records);
   }
 
   /**
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 6744e9e..3b364e4 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -978,6 +978,7 @@ function user_login_finalize(UserInterface $account) {
     ->fields(array('login' => $user->getLastLoginTime()))
     ->condition('uid', $user->id())
     ->execute();
+  \Drupal::entityManager()->getStorageController('user')->resetCache(array($account->id()));
 
   // Regenerate the session ID to prevent against session fixation attacks.
   // This is called before hook_user in case one of those functions fails
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
old mode 100644
new mode 100755
