diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index afddb228b9..5471fbccb8 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -541,6 +541,53 @@ protected function getTranslatedField($name, $langcode) {
   }
 
   /**
+   * Gets the value of a specific property of a field.
+   *
+   * Only the first delta can be accessed with this method.
+   *
+   * @param string $field_name
+   *   The name of the field.
+   * @param string $property
+   *   The field property, "value" for many field types.
+   * @param int $delta
+   *   Dield value offset for mutli value fields.
+   *
+   * @return mixed
+   */
+  public function getFieldValue($field_name, $property, $delta = 0) {
+    // Attempt to get the value from the values directly if the field is not
+    // initialized yet.
+    if (!isset($this->fields[$field_name])) {
+      $field_values = NULL;
+      if (isset($this->values[$field_name][$this->activeLangcode])) {
+        $field_values = $this->values[$field_name][$this->activeLangcode];
+      }
+      elseif ($this->values[$field_name][LanguageInterface::LANGCODE_DEFAULT]) {
+        $field_values = $this->values[$field_name][LanguageInterface::LANGCODE_DEFAULT];
+      }
+
+      if ($field_values !== NULL) {
+        // If there are field values, try to get the property value.
+        // Configurable/Multi-value fields are stored differently, try accessing
+        // with delta and property first, then without delta and last, if the
+        // value are a scalar, just return that.
+        if (isset($field_values[$delta][$property]) && is_array($field_values[$delta])) {
+          return $field_values[$delta][$property];
+        }
+        elseif (isset($field_values[$property]) && is_array($field_values)) {
+          return $field_values[$property];
+        }
+        elseif (!is_array($field_values)) {
+          return $field_values;
+        }
+      }
+    }
+
+    // Fall back to access the property through the field object.
+    return $this->get($field_name)->$property;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function set($name, $value, $notify = TRUE) {
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityDeleteForm.php b/core/lib/Drupal/Core/Entity/ContentEntityDeleteForm.php
index 9a70ef5bc7..d0b29fdfbc 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityDeleteForm.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityDeleteForm.php
@@ -61,7 +61,9 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
 
     // Make sure that deleting a translation does not delete the whole entity.
     if (!$entity->isDefaultTranslation()) {
-      $untranslated_entity = $entity->getUntranslated();
+      // Clone the entity before deleting, as other methods will need to access
+      // the label and other data of the deleted translation.
+      $untranslated_entity = clone $entity->getUntranslated();
       $untranslated_entity->removeTranslation($entity->language()->getId());
       $untranslated_entity->save();
       $form_state->setRedirectUrl($untranslated_entity->urlInfo('canonical'));
diff --git a/core/modules/user/src/Authentication/Provider/Cookie.php b/core/modules/user/src/Authentication/Provider/Cookie.php
index ebcdae7517..35a246940c 100644
--- a/core/modules/user/src/Authentication/Provider/Cookie.php
+++ b/core/modules/user/src/Authentication/Provider/Cookie.php
@@ -3,9 +3,7 @@
 namespace Drupal\user\Authentication\Provider;
 
 use Drupal\Core\Authentication\AuthenticationProviderInterface;
-use Drupal\Core\Database\Connection;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\Core\Session\UserSession;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Session\SessionConfigurationInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Session\SessionInterface;
@@ -23,23 +21,23 @@ class Cookie implements AuthenticationProviderInterface {
   protected $sessionConfiguration;
 
   /**
-   * The database connection.
+   * The entity type manager.
    *
-   * @var \Drupal\Core\Database\Connection
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
    */
-  protected $connection;
+  protected $entityTypeManager;
 
   /**
    * Constructs a new cookie authentication provider.
    *
    * @param \Drupal\Core\Session\SessionConfigurationInterface $session_configuration
    *   The session configuration.
-   * @param \Drupal\Core\Database\Connection $connection
-   *   The database connection.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
    */
-  public function __construct(SessionConfigurationInterface $session_configuration, Connection $connection) {
+  public function __construct(SessionConfigurationInterface $session_configuration, EntityTypeManagerInterface $entity_type_manager) {
     $this->sessionConfiguration = $session_configuration;
-    $this->connection = $connection;
+    $this->entityTypeManager = $entity_type_manager;
   }
 
   /**
@@ -53,41 +51,14 @@ public function applies(Request $request) {
    * {@inheritdoc}
    */
   public function authenticate(Request $request) {
-    return $this->getUserFromSession($request->getSession());
-  }
-
-  /**
-   * Returns the UserSession object for the given session.
-   *
-   * @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
-   *   The session.
-   *
-   * @return \Drupal\Core\Session\AccountInterface|null
-   *   The UserSession object for the current user, or NULL if this is an
-   *   anonymous session.
-   */
-  protected function getUserFromSession(SessionInterface $session) {
-    if ($uid = $session->get('uid')) {
-      // @todo Load the User entity in SessionHandler so we don't need queries.
-      // @see https://www.drupal.org/node/2345611
-      $values = $this->connection
-        ->query('SELECT * FROM {users_field_data} u WHERE u.uid = :uid AND u.default_langcode = 1', [':uid' => $uid])
-        ->fetchAssoc();
-
-      // Check if the user data was found and the user is active.
-      if (!empty($values) && $values['status'] == 1) {
-        // Add the user's roles.
-        $rids = $this->connection
-          ->query('SELECT roles_target_id FROM {user__roles} WHERE entity_id = :uid', [':uid' => $values['uid']])
-          ->fetchCol();
-        $values['roles'] = array_merge([AccountInterface::AUTHENTICATED_ROLE], $rids);
-
-        return new UserSession($values);
+    if ($uid = $request->getSession()->get('uid')) {
+      /** @var \Drupal\user\UserInterface $user */
+      if ($user = $this->entityTypeManager->getStorage('user')->load($uid)) {
+        if ($user->isActive()) {
+          return $user;
+        }
       }
     }
-
-    // This is an anonymous session.
-    return NULL;
   }
 
 }
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index 7529532581..893d4f3a67 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -152,9 +152,22 @@ public function getRoles($exclude_locked_roles = FALSE) {
       }
     }
 
-    foreach ($this->get('roles') as $role) {
-      if ($role->target_id) {
-        $roles[] = $role->target_id;
+    // Optimize for the case where the field object has not been initialized
+    // yet, directly access the values.
+    if (!isset($this->fields['roles'])) {
+      if (isset($this->values['roles'][LanguageInterface::LANGCODE_DEFAULT][0])) {
+        foreach ($this->values['roles'][LanguageInterface::LANGCODE_DEFAULT] as $values) {
+          if (isset($values['target_id'])) {
+            $roles[] = $values['target_id'];
+          }
+        }
+      }
+    }
+    else {
+      foreach ($this->get('roles') as $role) {
+        if ($role->target_id) {
+          $roles[] = $role->target_id;
+        }
       }
     }
 
@@ -242,7 +255,7 @@ public function getCreatedTime() {
    * {@inheritdoc}
    */
   public function getLastAccessedTime() {
-    return $this->get('access')->value;
+    return $this->getFieldValue('access', 'value');
   }
 
   /**
@@ -272,14 +285,14 @@ public function setLastLoginTime($timestamp) {
    * {@inheritdoc}
    */
   public function isActive() {
-    return $this->get('status')->value == 1;
+    return $this->getFieldValue('status', 'value') == 1;
   }
 
   /**
    * {@inheritdoc}
    */
   public function isBlocked() {
-    return $this->get('status')->value == 0;
+    return $this->getFieldValue('status', 'value') == 0;
   }
 
   /**
@@ -302,7 +315,7 @@ public function block() {
    * {@inheritdoc}
    */
   public function getTimeZone() {
-    return $this->get('timezone')->value;
+    return $this->getFieldValue('timezone', 'value');
   }
 
   /**
@@ -364,7 +377,7 @@ public function getUsername() {
    * {@inheritdoc}
    */
   public function getAccountName() {
-    return $this->get('name')->value ?: '';
+    return $this->getFieldValue('name', 'value') ?: '';
   }
 
   /**
diff --git a/core/modules/user/tests/src/Unit/Plugin/Core/Entity/UserTest.php b/core/modules/user/tests/src/Unit/Plugin/Core/Entity/UserTest.php
index 623203ee74..b101fb9d12 100644
--- a/core/modules/user/tests/src/Unit/Plugin/Core/Entity/UserTest.php
+++ b/core/modules/user/tests/src/Unit/Plugin/Core/Entity/UserTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\user\Unit\Plugin\Core\Entity;
 
+use Drupal\Core\Language\LanguageInterface;
 use Drupal\Tests\Core\Session\UserSessionTest;
 use Drupal\user\RoleInterface;
 
@@ -15,24 +16,28 @@ class UserTest extends UserSessionTest {
    * {@inheritdoc}
    */
   protected function createUserSession(array $rids = [], $authenticated = FALSE) {
+    $roles = [];
+    foreach ($rids as $rid) {
+      $roles[] = [
+        'target_id' => $rid,
+      ];
+    }
+    $values = ['roles' => [LanguageInterface::LANGCODE_DEFAULT => $roles]];
+
     $user = $this->getMockBuilder('Drupal\user\Entity\User')
       ->disableOriginalConstructor()
-      ->setMethods(['get', 'id'])
+      ->setMethods(['id'])
       ->getMock();
+
+    $reflect = new \ReflectionObject($user);
+    $property = $reflect->getProperty('values');
+    $property->setAccessible(TRUE);
+    $property->setValue($user, $values);
+
     $user->expects($this->any())
       ->method('id')
       // @todo Also test the uid = 1 handling.
       ->will($this->returnValue($authenticated ? 2 : 0));
-    $roles = [];
-    foreach ($rids as $rid) {
-      $roles[] = (object) [
-        'target_id' => $rid,
-      ];
-    }
-    $user->expects($this->any())
-      ->method('get')
-      ->with('roles')
-      ->will($this->returnValue($roles));
     return $user;
   }
 
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 61faa3b4f0..f54ad5e6b3 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -775,6 +775,7 @@ function _user_cancel($edit, $account, $method) {
   // regenerate it because batch API uses the session ID, we will regenerate it
   // in _user_cancel_session_regenerate().
   if ($account->id() == \Drupal::currentUser()->id()) {
+    \Drupal::request()->getSession()->remove('uid');
     \Drupal::currentUser()->setAccount(new AnonymousUserSession());
   }
 }
diff --git a/core/modules/user/user.services.yml b/core/modules/user/user.services.yml
index c273cb3443..9739c434ae 100644
--- a/core/modules/user/user.services.yml
+++ b/core/modules/user/user.services.yml
@@ -17,7 +17,7 @@ services:
       - { name: access_check, applies_to: _user_is_logged_in }
   user.authentication.cookie:
     class: Drupal\user\Authentication\Provider\Cookie
-    arguments: ['@session_configuration', '@database']
+    arguments: ['@session_configuration', '@entity_type.manager']
     tags:
       - { name: authentication_provider, provider_id: 'cookie', priority: 0, global: TRUE }
   user.data:
