diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index e1c15fe..4640148 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -16,6 +16,7 @@
 use Drupal\Core\Lock\DatabaseLockBackend;
 use Drupal\Core\Lock\LockBackendInterface;
 use Drupal\user\Plugin\Core\Entity\User;
+use Drupal\Core\Entity\EntityBCDecorator;
 
 /**
  * @file
@@ -2055,7 +2056,9 @@ function drupal_anonymous_user() {
       DRUPAL_ANONYMOUS_RID => DRUPAL_ANONYMOUS_RID,
     ),
   );
-  return new User($values, 'user');
+  // @todo: This is really ugly but not sure how to change it.
+  $definitions = array();
+  return new EntityBCDecorator(new User($values, 'user'), $definitions);
 }
 
 /**
diff --git a/core/includes/errors.inc b/core/includes/errors.inc
index 5fc4b7d..7bd6629 100644
--- a/core/includes/errors.inc
+++ b/core/includes/errors.inc
@@ -153,6 +153,7 @@ function _drupal_render_exception_safe($exception) {
  *   TRUE if an error should be displayed.
  */
 function error_displayable($error = NULL) {
+  return TRUE;
   $error_level = config('system.logging')->get('error_level');
   $updating = (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update');
   $all_errors_displayed = ($error_level == ERROR_REPORTING_DISPLAY_ALL) ||
diff --git a/core/includes/session.inc b/core/includes/session.inc
index 31e67a6..07a8480 100644
--- a/core/includes/session.inc
+++ b/core/includes/session.inc
@@ -80,7 +80,13 @@ function _drupal_session_read($sid) {
   // cookies (eg. web crawlers).
   $insecure_session_name = substr(session_name(), 1);
   if (!isset($_COOKIE[session_name()]) && !isset($_COOKIE[$insecure_session_name])) {
-    $user = drupal_anonymous_user();
+    $user = (object)array(
+      'uid' => 0,
+      'hostname' => ip_address(),
+      'roles' => array(
+        DRUPAL_ANONYMOUS_RID => DRUPAL_ANONYMOUS_RID,
+      ),
+    );
     return '';
   }
 
@@ -113,14 +119,26 @@ function _drupal_session_read($sid) {
   elseif ($user) {
     // The user is anonymous or blocked. Only preserve two fields from the
     // {sessions} table.
-    $account = drupal_anonymous_user();
+    $account = (object)array(
+      'uid' => 0,
+      'hostname' => ip_address(),
+      'roles' => array(
+        DRUPAL_ANONYMOUS_RID => DRUPAL_ANONYMOUS_RID,
+      ),
+    );
     $account->session = $user->session;
     $account->timestamp = $user->timestamp;
     $user = $account;
   }
   else {
     // The session has expired.
-    $user = drupal_anonymous_user();
+    $user = (object)array(
+      'uid' => 0,
+      'hostname' => ip_address(),
+      'roles' => array(
+        DRUPAL_ANONYMOUS_RID => DRUPAL_ANONYMOUS_RID,
+      ),
+    );
     $user->session = '';
   }
 
@@ -255,7 +273,13 @@ function drupal_session_initialize() {
     // processes (like drupal_get_token()) needs to know the future
     // session ID in advance.
     $GLOBALS['lazy_session'] = TRUE;
-    $user = drupal_anonymous_user();
+    $user =  (object) array(
+      'uid' => 0,
+      'hostname' => ip_address(),
+      'roles' => array(
+        DRUPAL_ANONYMOUS_RID => DRUPAL_ANONYMOUS_RID,
+      ),
+    );
     // Less random sessions (which are much faster to generate) are used for
     // anonymous users than are generated in drupal_session_regenerate() when
     // a user becomes authenticated.
@@ -433,7 +457,13 @@ function _drupal_session_destroy($sid) {
   // Reset $_SESSION and $user to prevent a new session from being started
   // in drupal_session_commit().
   $_SESSION = array();
-  $user = drupal_anonymous_user();
+  $user = (object) array(
+    'uid' => 0,
+    'hostname' => ip_address(),
+    'roles' => array(
+      DRUPAL_ANONYMOUS_RID => DRUPAL_ANONYMOUS_RID,
+    ),
+  );
 
   // Unset the session cookies.
   _drupal_session_delete_cookie(session_name());
diff --git a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
index 08be87c..d3a58cf 100644
--- a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
+++ b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
@@ -90,6 +90,16 @@ public function &__get($name) {
       return $this->decorated->values[$name];
     }
 
+    // @todo: The EntityBCDecorator tries to be too intelligent and returns
+    //   a string but we actually want an array for roles.
+    if ($name == 'roles') {
+      $roles = array();
+      foreach ($this->getOriginalEntity()->roles as $role) {
+        $roles[] = $role->value;
+      }
+      return $roles;
+    }
+
     // We access the protected 'values' and 'fields' properties of the decorated
     // entity via the magic getter - which returns them by reference for us. We
     // do so, as providing references to these arrays would make $entity->values
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index dd87b29..8b572e2 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1611,7 +1611,7 @@ function comment_prepare_author(Comment $comment) {
   if (!$account) {
     $account = entity_create('user', array('uid' => 0, 'name' => $comment->name->value, 'homepage' => $comment->homepage->value));
   }
-  return $account;
+  return $account->getBCEntity();
 }
 
 /**
diff --git a/core/modules/comment/comment.tokens.inc b/core/modules/comment/comment.tokens.inc
index 715b63d..f5afcab 100644
--- a/core/modules/comment/comment.tokens.inc
+++ b/core/modules/comment/comment.tokens.inc
@@ -216,7 +216,7 @@ function comment_tokens($type, $tokens, array $data = array(), array $options =
     }
 
     if (($author_tokens = token_find_with_prefix($tokens, 'author')) && $account = $comment->uid->entity) {
-      $replacements += token_generate('user', $author_tokens, array('user' => $account), $options);
+      $replacements += token_generate('user', $author_tokens, array('user' => $account->getBCEntity()), $options);
     }
   }
   elseif ($type == 'node' & !empty($data['node'])) {
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php
index 7907464..1388d13 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php
@@ -50,7 +50,8 @@ function testCommentLinks() {
 
     // Remove additional user permissions from $this->web_user added by setUp(),
     // since this test is limited to anonymous and authenticated roles only.
-    entity_delete_multiple('user_role', array(key($this->web_user->roles)));
+    $roles = $this->web_user->roles;
+    entity_delete_multiple('user_role', array(reset($roles)));
 
     // Matrix of possible environmental conditions and configuration settings.
     // See setEnvironment() for details.
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php b/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php
index cee642e..eb257dc 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php
@@ -88,7 +88,7 @@ function testConfigLocaleUserOverride() {
     ));
 
     $user_config_context = config_context_enter('Drupal\user\UserConfigContext');
-    $user_config_context->setAccount($account);
+    $user_config_context->setAccount($account->getOriginalEntity());
     $config = config('config_test.system');
     $this->assertIdentical($config->get('foo'), 'fr bar');
     // Ensure the non-overriden value is still the same.
@@ -111,7 +111,7 @@ function testConfigLocaleUserOverride() {
     ));
 
     $config_factory = drupal_container()->get('config.factory');
-    $config_factory->enterContext($user_config_context->setAccount($account));
+    $config_factory->enterContext($user_config_context->setAccount($account->getOriginalEntity()));
     // Should not have to re-initialize the configuration object to get new
     // overrides as the new context will have a different uuid.
     $config = config('config_test.system');
@@ -127,7 +127,7 @@ function testConfigLocaleUserOverride() {
     ));
     // Create a new user config context to stack on top of the existign one.
     $en_user_config_context = config_context_enter('Drupal\user\UserConfigContext');
-    $en_user_config_context->setAccount($account);
+    $en_user_config_context->setAccount($account->getOriginalEntity());
     $config = config('config_test.system');
     $this->assertIdentical($config->get('foo'), 'en bar');
 
@@ -178,7 +178,7 @@ function testConfigLocaleUserAndGlobalOverride() {
     ));
 
     $user_config_context = config_context_enter('Drupal\user\UserConfigContext');
-    $user_config_context->setAccount($account);
+    $user_config_context->setAccount($account->getOriginalEntity());
     $config = config('config_test.system');
     $this->assertIdentical($config->get('foo'), 'fr bar');
     // Ensure the value overriden from global $conf works.
diff --git a/core/modules/contact/lib/Drupal/contact/MessageFormController.php b/core/modules/contact/lib/Drupal/contact/MessageFormController.php
index c4352cf..b3a9ed8 100644
--- a/core/modules/contact/lib/Drupal/contact/MessageFormController.php
+++ b/core/modules/contact/lib/Drupal/contact/MessageFormController.php
@@ -167,7 +167,7 @@ public function save(array $form, array &$form_state) {
       $to = implode(', ', $category->recipients);
       $recipient_langcode = language_default()->langcode;
     }
-    elseif ($message->recipient instanceof User) {
+    elseif ($message->recipient && $message->recipient->getOriginalEntity() instanceof User) {
       // Send to the user in the user's preferred language.
       $to = $message->recipient->mail;
       $recipient_langcode = user_preferred_langcode($message->recipient);
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
index 05b0cad..96d1b8d 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
@@ -242,7 +242,7 @@ function testPrivateFileComment() {
     $user = $this->drupalCreateUser(array('access comments'));
 
     // Grant the admin user required comment permissions.
-    user_role_grant_permissions(key($this->admin_user->roles), array('administer comment fields'));
+    user_role_grant_permissions($this->admin_user->roles[1], array('administer comment fields'));
 
     // Revoke access comments permission from anon user, grant post to
     // authenticated.
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 4c7392b..edd56d5 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -2527,7 +2527,7 @@ function node_access($op, $node, $account = NULL, $langcode = NULL) {
   // Make sure that if an account is passed, that it is a fully loaded user
   // object.
   if ($account && !($account instanceof User)) {
-    $account = user_load($account->uid);
+    $account = entity_load('user', $account->uid);
   }
 
   $method = $op . 'Access';
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 5cca38a..a6684c3 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -480,7 +480,7 @@ protected function drupalCreateUser(array $permissions = array(), $name = NULL)
     $edit['pass']   = user_password();
     $edit['status'] = 1;
     if ($rid) {
-      $edit['roles'] = array($rid => $rid);
+      $edit['roles'] = array($rid);
     }
 
     $account = entity_create('user', $edit);
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
index 0642032..773cd18 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
@@ -82,7 +82,7 @@ function testEntityAccess() {
       'update' => FALSE,
       'delete' => FALSE,
       'view' => FALSE,
-    ), $entity, $custom_user);
+    ), $entity, $custom_user->getOriginalEntity());
   }
 
   /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php
index 1a8947c..6269bed 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php
@@ -7,7 +7,8 @@
 
 namespace Drupal\system\Tests\Entity;
 
-use Drupal\user\Plugin\Core\Entity\User;
+use Drupal\Core\Entity\EntityInterface;
+
 
 /**
  * Tests the basic Entity API.
@@ -50,10 +51,10 @@ public function testCRUD() {
    *
    * @param string $entity_type
    *   The entity type to run the tests with.
-   * @param \Drupal\user\Plugin\Core\Entity\User $user1
+   * @param \Drupal\Core\Entity\EntityInterface $user1
    *   The user to run the tests with.
    */
-  protected function assertCRUD($entity_type, User $user1) {
+  protected function assertCRUD($entity_type, EntityInterface $user1) {
     // Create some test entities.
     $entity = entity_create($entity_type, array('name' => 'test', 'user_id' => $user1->uid));
     $entity->save();
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
index 3c5679b..7cfc95c 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
@@ -117,19 +117,19 @@ protected function assertReadWrite($entity_type) {
     $this->assertTrue($entity->user_id[0] instanceof FieldItemInterface, format_string('%entity_type: Field item implements interface', array('%entity_type' => $entity_type)));
 
     $this->assertEqual($this->entity_user->uid, $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type)));
 
     // Change the assigned user by entity.
     $new_user = $this->createUser();
     $entity->user_id->entity = $new_user;
     $this->assertEqual($new_user->uid, $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($new_user->name, $entity->user_id->entity->name, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($new_user->name, $entity->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type)));
 
     // Change the assigned user by id.
     $new_user = $this->createUser();
     $entity->user_id->target_id = $new_user->uid;
     $this->assertEqual($new_user->uid, $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($new_user->name, $entity->user_id->entity->name, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($new_user->name, $entity->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type)));
 
     // Try unsetting a field.
     $entity->name->value = NULL;
@@ -217,7 +217,7 @@ protected function assertReadWrite($entity_type) {
     ));
     $this->assertEqual($this->entity_name, $entity->name->value, format_string('%entity_type: Name value can be read.', array('%entity_type' => $entity_type)));
     $this->assertEqual($this->entity_user->uid, $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type)));
     $this->assertEqual($this->entity_field_text, $entity->field_test_text->value, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type)));
 
     // Test copying field values.
@@ -328,7 +328,7 @@ protected function assertSave($entity_type) {
     $this->assertEqual(LANGUAGE_NOT_SPECIFIED, $entity->langcode->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
     $this->assertEqual(language_load(LANGUAGE_NOT_SPECIFIED), $entity->langcode->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
     $this->assertEqual($this->entity_user->uid, $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type)));
     $this->assertEqual($this->entity_field_text, $entity->field_test_text->value, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type)));
   }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
index b747e79..1209e7b 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
@@ -51,7 +51,7 @@ protected function createUser($values = array(), $permissions = array()) {
       ));
       $role->save();
       user_role_grant_permissions($role->id(), $permissions);
-      $values['roles'][$role->id()] = $role->id();
+      $values['roles'][] = $role->id();
     }
 
     $account = entity_create('user', $values + array(
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php
index 09e7a7a..4116b4e 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php
@@ -70,12 +70,12 @@ function testFieldAccess() {
     $values = array('name' => 'test');
     $account = entity_create('user', $values);
 
-    $this->assertFalse($entity->field_test_text->access('view', $account), 'Access to the field was denied.');
+    $this->assertFalse($entity->field_test_text->access('view', $account->getOriginalEntity()), 'Access to the field was denied.');
 
     $entity->field_test_text = 'access alter value';
-    $this->assertFalse($entity->field_test_text->access('view', $account), 'Access to the field was denied.');
+    $this->assertFalse($entity->field_test_text->access('view', $account->getOriginalEntity()), 'Access to the field was denied.');
 
     $entity->field_test_text = 'standard value';
-    $this->assertTrue($entity->field_test_text->access('view', $account), 'Access to the field was granted.');
+    $this->assertTrue($entity->field_test_text->access('view', $account->getOriginalEntity()), 'Access to the field was granted.');
   }
 }
diff --git a/core/modules/update/update.install b/core/modules/update/update.install
index 2d4ec4b..3fea641 100644
--- a/core/modules/update/update.install
+++ b/core/modules/update/update.install
@@ -72,7 +72,7 @@ function update_uninstall() {
   variable_del('update_last_check');
   variable_del('update_last_email_notification');
 
-  $queue = queue('update_fetch_tasks');
+  $queue = Drupal::queue('update_fetch_tasks');
   $queue->deleteQueue();
 }
 
diff --git a/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php b/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php
index fb7cbbb..4217f70 100644
--- a/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php
+++ b/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\user\Plugin\Core\Entity;
 
-use Drupal\Core\Entity\Entity;
+use Drupal\Core\Entity\EntityNG;
 use Drupal\Component\Annotation\Plugin;
 use Drupal\Core\Annotation\Translation;
 
@@ -38,7 +38,7 @@
  *   }
  * )
  */
-class User extends Entity {
+class User extends EntityNG {
 
   /**
    * The user ID.
@@ -59,7 +59,7 @@ class User extends Entity {
    *
    * @var string
    */
-  public $name = '';
+  public $name;
 
   /**
    * The user's password (hashed).
@@ -73,7 +73,7 @@ class User extends Entity {
    *
    * @var string
    */
-  public $mail = '';
+  public $mail;
 
   /**
    * The user's default theme.
@@ -109,7 +109,7 @@ class User extends Entity {
    *
    * @var integer
    */
-  public $access = 0;
+  public $access;
 
   /**
    * The timestamp when the user last logged in. A value of 0 means the user has
@@ -117,14 +117,14 @@ class User extends Entity {
    *
    * @var integer
    */
-  public $login = 0;
+  public $login;
 
   /**
    * Whether the user is active (1) or blocked (0).
    *
    * @var integer
    */
-  public $status = 1;
+  public $status;
 
   /**
    * The user's timezone.
@@ -138,40 +138,84 @@ class User extends Entity {
    *
    * @var string
    */
-  public $langcode = LANGUAGE_NOT_SPECIFIED;
+  public $langcode;
 
   /**
    * The user's preferred langcode for receiving emails and viewing the site.
    *
    * @var string
    */
-  public $preferred_langcode = LANGUAGE_NOT_SPECIFIED;
+  public $preferred_langcode;
 
   /**
    * The user's preferred langcode for viewing administration pages.
    *
    * @var string
    */
-  public $preferred_admin_langcode = LANGUAGE_NOT_SPECIFIED;
+  public $preferred_admin_langcode;
 
   /**
    * The email address used for initial account creation.
    *
    * @var string
    */
-  public $init = '';
+  public $init;
 
   /**
    * The user's roles.
    *
    * @var array
    */
-  public $roles = array();
+  public $roles;
+
+    /**
+   * The plain data values of the contained properties.
+   *
+   * Define default values.
+   *
+   * @var array
+   */
+  protected $values = array(
+    'langcode' => array(LANGUAGE_DEFAULT => array(0 => array('value' => LANGUAGE_NOT_SPECIFIED))),
+    'preferred_langcode' => array(LANGUAGE_DEFAULT => array(0 => array('value' => LANGUAGE_NOT_SPECIFIED))),
+    'admin_preffered_langcode' => array(LANGUAGE_DEFAULT => array(0 => array('value' => LANGUAGE_NOT_SPECIFIED))),
+    'name' => array(LANGUAGE_DEFAULT => array(0 => array('value' => ''))),
+    'mail' => array(LANGUAGE_DEFAULT => array(0 => array('value' => ''))),
+    'init' => array(LANGUAGE_DEFAULT => array(0 => array('value' => ''))),
+    'access' => array(LANGUAGE_DEFAULT => array(0 => array('value' => 0))),
+    'login' => array(LANGUAGE_DEFAULT => array(0 => array('value' => 0))),
+    'status' => array(LANGUAGE_DEFAULT => array(0 => array('value' => 1))),
+  );
 
   /**
    * Implements Drupal\Core\Entity\EntityInterface::id().
    */
   public function id() {
-    return $this->uid;
+    return $this->get('uid')->value;
+  }
+
+  protected function init() {
+    parent::init();
+    unset($this->access);
+    unset($this->created);
+    unset($this->init);
+    unset($this->login);
+    unset($this->mail);
+    unset($this->name);
+    unset($this->pass);
+    unset($this->preferred_admin_langcode);
+    unset($this->preferred_langcode);
+    unset($this->roles);
+    unset($this->signature);
+    unset($this->signature_format);
+    unset($this->status);
+    unset($this->theme);
+    unset($this->timezone);
+    unset($this->uid);
+    unset($this->uuid);
+  }
+
+  public function &__get($name) {
+    return parent::__get($name);
   }
 }
diff --git a/core/modules/user/lib/Drupal/user/ProfileFormController.php b/core/modules/user/lib/Drupal/user/ProfileFormController.php
index c2b139d..bc36fbd 100644
--- a/core/modules/user/lib/Drupal/user/ProfileFormController.php
+++ b/core/modules/user/lib/Drupal/user/ProfileFormController.php
@@ -30,6 +30,15 @@ protected function actions(array $form, array &$form_state) {
   }
 
   /**
+   * Overrides Drupal\Core\Entity\EntityFormController::buildEntity().
+   */
+  public function buildEntity(array $form, array &$form_state) {
+    // Change the roles array to a list of enabled roles.
+    $form_state['values']['roles'] = array_keys(array_filter($form_state['values']['roles']));
+    return parent::buildEntity($form, $form_state);
+  }
+
+  /**
    * Overrides Drupal\Core\Entity\EntityFormController::submit().
    */
   public function submit(array $form, array &$form_state) {
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php b/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php
index 3b83b52..0769fff 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php
@@ -60,8 +60,8 @@ function testUserAdmin() {
 
     // Filter the users by role. Grab the system-generated role name for User C.
     $roles = $user_c->roles;
-    unset($roles[DRUPAL_AUTHENTICATED_RID]);
-    $edit['role'] = key($roles);
+    unset($roles[array_search(DRUPAL_AUTHENTICATED_RID, $roles)]);
+    $edit['role'] = reset($roles);
     $this->drupalPost('admin/people', $edit, t('Refine'));
 
     // Check if the correct users show up when filtered by role.
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
index 2455b10..3fc3b4b 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
@@ -28,8 +28,8 @@ function setUp() {
 
     // Find the new role ID.
     $all_rids = $this->admin_user->roles;
-    unset($all_rids[DRUPAL_AUTHENTICATED_RID]);
-    $this->rid = key($all_rids);
+    unset($all_rids[array_search(DRUPAL_AUTHENTICATED_RID, $all_rids)]);
+    $this->rid = reset($all_rids);
   }
 
   /**
diff --git a/core/modules/user/lib/Drupal/user/UserAccessController.php b/core/modules/user/lib/Drupal/user/UserAccessController.php
index 13b8c6b..aac9da0 100644
--- a/core/modules/user/lib/Drupal/user/UserAccessController.php
+++ b/core/modules/user/lib/Drupal/user/UserAccessController.php
@@ -20,7 +20,7 @@ class UserAccessController extends EntityAccessController {
    * Implements EntityAccessControllerInterface::viewAccess().
    */
   public function viewAccess(EntityInterface $entity, $langcode = LANGUAGE_DEFAULT, User $account = NULL) {
-    $uid = $entity->uid;
+    $uid = $entity->uid->value;
     if (!$account) {
       $account = $GLOBALS['user'];
     }
@@ -33,7 +33,7 @@ public function viewAccess(EntityInterface $entity, $langcode = LANGUAGE_DEFAULT
       }
       elseif (user_access('access user profiles', $account)) {
         // Only allow view access if the account is active.
-        return $entity->status;
+        return $entity->status->value;
       }
     }
     return FALSE;
@@ -55,7 +55,7 @@ public function updateAccess(EntityInterface $entity, $langcode = LANGUAGE_DEFAU
     }
     // Users can always edit their own account. Users with the 'administer
     // users' permission can edit any account except the anonymous account.
-    return (($account->uid == $entity->uid) || user_access('administer users', $account)) && $entity->uid > 0;
+    return (($account->uid == $entity->uid->value) || user_access('administer users', $account)) && $entity->uid->value > 0;
   }
 
   /**
@@ -68,7 +68,7 @@ public function deleteAccess(EntityInterface $entity, $langcode = LANGUAGE_DEFAU
     // Users with 'cancel account' permission can cancel their own account,
     // users with 'administer users' permission can cancel any account except
     // the anonymous account.
-    return ((($account->uid == $entity->uid) && user_access('cancel account', $account)) || user_access('administer users', $account)) && $entity->uid > 0;
+    return ((($account->uid == $entity->uid->value) && user_access('cancel account', $account)) || user_access('administer users', $account)) && $entity->uid->value > 0;
   }
 
 }
diff --git a/core/modules/user/lib/Drupal/user/UserStorageController.php b/core/modules/user/lib/Drupal/user/UserStorageController.php
index 3d8e981..20978c8 100644
--- a/core/modules/user/lib/Drupal/user/UserStorageController.php
+++ b/core/modules/user/lib/Drupal/user/UserStorageController.php
@@ -9,7 +9,7 @@
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityMalformedException;
-use Drupal\Core\Entity\DatabaseStorageController;
+use Drupal\Core\Entity\DatabaseStorageControllerNG;
 
 /**
  * Controller class for users.
@@ -17,7 +17,7 @@
  * This extends the Drupal\Core\Entity\DatabaseStorageController class, adding
  * required special handling for user objects.
  */
-class UserStorageController extends DatabaseStorageController {
+class UserStorageController extends DatabaseStorageControllerNG {
 
   /**
    * Overrides Drupal\Core\Entity\DatabaseStorageController::attachLoad().
@@ -52,19 +52,25 @@ public function create(array $values) {
       $values['created'] = REQUEST_TIME;
     }
     // Users always have the authenticated user role.
-    $values['roles'][DRUPAL_AUTHENTICATED_RID] = DRUPAL_AUTHENTICATED_RID;
+    $values['roles'][] = DRUPAL_AUTHENTICATED_RID;
 
-    return parent::create($values);
+    return parent::create($values)->getBCEntity();
   }
 
   /**
    * Overrides Drupal\Core\Entity\DatabaseStorageController::save().
    */
   public function save(EntityInterface $entity) {
-    if (empty($entity->uid)) {
-      $entity->uid = db_next_id(db_query('SELECT MAX(uid) FROM {users}')->fetchField());
+    if (!$entity->uid->value) {
+      $entity->uid->value = db_next_id(db_query('SELECT MAX(uid) FROM {users}')->fetchField());
       $entity->enforceIsNew();
     }
+
+    // There are some cases that pre-set ->original for performance. Make sure
+    // original is not a BC decorator.
+    if ($entity->original instanceof \Drupal\Core\Entity\EntityBCDecorator) {
+      $entity->original = $entity->original->getOriginalEntity();
+    }
     parent::save($entity);
   }
 
@@ -73,11 +79,11 @@ public function save(EntityInterface $entity) {
    */
   protected function preSave(EntityInterface $entity) {
     // Update the user password if it has changed.
-    if ($entity->isNew() || (!empty($entity->pass) && $entity->pass != $entity->original->pass)) {
+    if ($entity->isNew() || ($entity->pass->value && $entity->pass->value != $entity->original->pass->value)) {
       // Allow alternate password hashing schemes.
-      $entity->pass = drupal_container()->get('password')->hash(trim($entity->pass));
+      $entity->pass->value = drupal_container()->get('password')->hash(trim($entity->pass->value));
       // Abort if the hashing failed and returned FALSE.
-      if (!$entity->pass) {
+      if (!$entity->pass->value) {
         throw new EntityMalformedException('The entity does not have a password.');
       }
     }
@@ -85,14 +91,14 @@ protected function preSave(EntityInterface $entity) {
     if (!$entity->isNew()) {
       // If the password is empty, that means it was not changed, so use the
       // original password.
-      if (empty($entity->pass)) {
-        $entity->pass = $entity->original->pass;
+      if (empty($entity->pass->value)) {
+        $entity->pass->value = $entity->original->pass->value;
       }
     }
 
     // Prepare user roles.
     if (isset($entity->roles)) {
-      $entity->roles = array_filter($entity->roles);
+      //$entity->roles = array_filter($entity->roles);
     }
 
     // Store account cancellation information.
@@ -111,28 +117,28 @@ protected function postSave(EntityInterface $entity, $update) {
     if ($update) {
       // If the password has been changed, delete all open sessions for the
       // user and recreate the current one.
-      if ($entity->pass != $entity->original->pass) {
-        drupal_session_destroy_uid($entity->uid);
-        if ($entity->uid == $GLOBALS['user']->uid) {
+      if ($entity->pass->value != $entity->original->pass->value) {
+        drupal_session_destroy_uid($entity->id());
+        if ($entity->uid->value == $GLOBALS['user']->uid) {
           drupal_session_regenerate();
         }
       }
 
       // Remove roles that are no longer enabled for the user.
-      $entity->roles = array_filter($entity->roles);
+      //$entity->roles = array_filter($entity->roles);
 
       // Reload user roles if provided.
-      if ($entity->roles != $entity->original->roles) {
+      if ($entity->roles->getValue() != $entity->original->roles->getValue()) {
         db_delete('users_roles')
-          ->condition('uid', $entity->uid)
+          ->condition('uid', $entity->id())
           ->execute();
 
         $query = db_insert('users_roles')->fields(array('uid', 'rid'));
-        foreach (array_keys($entity->roles) as $rid) {
-          if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
+        foreach ($entity->roles as $role) {
+          if (!in_array($role->value, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
             $query->values(array(
-              'uid' => $entity->uid,
-              'rid' => $rid,
+              'uid' => $entity->id(),
+              'rid' => $role->value,
             ));
           }
         }
@@ -140,26 +146,26 @@ protected function postSave(EntityInterface $entity, $update) {
       }
 
       // If the user was blocked, delete the user's sessions to force a logout.
-      if ($entity->original->status != $entity->status && $entity->status == 0) {
-        drupal_session_destroy_uid($entity->uid);
+      if ($entity->original->status->value != $entity->status->value && $entity->status->value == 0) {
+        drupal_session_destroy_uid($entity->id());
       }
 
       // Send emails after we have the new user object.
-      if ($entity->status != $entity->original->status) {
+      if ($entity->status->value != $entity->original->status->value) {
         // The user's status is changing; conditionally send notification email.
-        $op = $entity->status == 1 ? 'status_activated' : 'status_blocked';
-        _user_mail_notify($op, $entity);
+        $op = $entity->status->value == 1 ? 'status_activated' : 'status_blocked';
+        _user_mail_notify($op, $entity->getBCEntity());
       }
     }
     else {
       // Save user roles.
       if (count($entity->roles) > 1) {
         $query = db_insert('users_roles')->fields(array('uid', 'rid'));
-        foreach (array_keys($entity->roles) as $rid) {
-          if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
+        foreach ($entity->roles as $role) {
+          if (!in_array($role->value, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
             $query->values(array(
-              'uid' => $entity->uid,
-              'rid' => $rid,
+              'uid' => $entity->id(),
+              'rid' => $role->value,
             ));
           }
         }
@@ -177,4 +183,123 @@ protected function postDelete($entities) {
       ->execute();
     drupal_container()->get('user.data')->delete(NULL, array_keys($entities));
   }
+
+  /**
+   * Overrides \Drupal\Core\Entity\DataBaseStorageControllerNG::invokeHook().
+   */
+  protected function invokeHook($hook, EntityInterface $entity) {
+    $function = 'field_attach_' . $hook;
+    // @todo: field_attach_delete_revision() is named the wrong way round,
+    // consider renaming it.
+    if ($function == 'field_attach_revision_delete') {
+      $function = 'field_attach_delete_revision';
+    }
+    if (!empty($this->entityInfo['fieldable']) && function_exists($function)) {
+      $function($entity->getBCEntity());
+    }
+
+    // Invoke the hook.
+    module_invoke_all($this->entityType . '_' . $hook, $entity->getBCEntity());
+    // Invoke the respective entity-level hook.
+    module_invoke_all('entity_' . $hook, $entity->getBCEntity(), $this->entityType);
+  }
+
+  /**
+   * Overrides \Drupal\Core\Entity\DataBaseStorageControllerNG::baseFieldDefinitions().
+   */
+  public function baseFieldDefinitions() {
+    $properties['uid'] = array(
+      'label' => t('User ID'),
+      'description' => t('The user ID.'),
+      'type' => 'integer_field',
+      'read-only' => TRUE,
+    );
+    $properties['uuid'] = array(
+      'label' => t('UUID'),
+      'description' => t('The user UUID.'),
+      'type' => 'string_field',
+      'read-only' => TRUE,
+    );
+    $properties['langcode'] = array(
+      'label' => t('Language code'),
+      'description' => t('The user language code.'),
+      'type' => 'language_field',
+    );
+    $properties['preferred_langcode'] = array(
+      'label' => t('Language code'),
+      'description' => t("The user's preferred langcode for receiving emails and viewing the site."),
+      'type' => 'language_field',
+    );
+    $properties['preferred_admin_langcode'] = array(
+      'label' => t('Language code'),
+      'description' => t("The user's preferred langcode for viewing administration pages."),
+      'type' => 'language_field',
+    );
+    $properties['name'] = array(
+      'label' => t('Name'),
+      'description' => t('The name of this user'),
+      'type' => 'string_field',
+    );
+    $properties['pass'] = array(
+      'label' => t('Name'),
+      'description' => t('The password of this user (hashed)'),
+      'type' => 'string_field',
+    );
+    $properties['mail'] = array(
+      'label' => t('Name'),
+      'description' => t('The e-mail of this user'),
+      'type' => 'string_field',
+    );
+    $properties['signature'] = array(
+      'label' => t('Name'),
+      'description' => t('The signature of this user'),
+      'type' => 'string_field',
+    );
+    $properties['signature_format'] = array(
+      'label' => t('Name'),
+      'description' => t('The signature format of this user'),
+      'type' => 'string_field',
+    );
+    $properties['theme'] = array(
+      'label' => t('Theme'),
+      'description' => t('The default theme of this user'),
+      'type' => 'string_field',
+    );
+    $properties['timezone'] = array(
+      'label' => t('Timeone'),
+      'description' => t('The timezone of this user'),
+      'type' => 'string_field',
+    );
+    $properties['status'] = array(
+      'label' => t('User status'),
+      'description' => t('Whether the user is active (1) or blocked (0).'),
+      'type' => 'boolean_field',
+    );
+    $properties['created'] = array(
+      'label' => t('Created'),
+      'description' => t('The time that the node was created.'),
+      'type' => 'integer_field',
+    );
+    $properties['access'] = array(
+      'label' => t('Last access'),
+      'description' => t('The time that the user last accessed the site.'),
+      'type' => 'integer_field',
+    );
+    $properties['login'] = array(
+      'label' => t('Last login'),
+      'description' => t('The time that the user last logged in.'),
+      'type' => 'integer_field',
+    );
+    $properties['init'] = array(
+      'label' => t('Init'),
+      'description' => t('The email address used for initial account creation.'),
+      'type' => 'string_field',
+    );
+    $properties['roles'] = array(
+      'label' => t('Roles'),
+      'description' => t('The roles the user has.'),
+      'type' => 'string_field',
+    );
+    return $properties;
+  }
 }
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index bdf5862..54aec69 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -156,7 +156,7 @@ function user_entity_bundle_info() {
  */
 function user_uri($user) {
   return array(
-    'path' => 'user/' . $user->uid,
+    'path' => 'user/' . $user->id(),
   );
 }
 
@@ -177,7 +177,7 @@ function user_uri($user) {
  * @see user_format_name()
  */
 function user_label($entity_type, $entity) {
-  return user_format_name($entity);
+  return user_format_name($entity->getBCEntity());
 }
 
 /**
@@ -293,7 +293,12 @@ function user_field_extra_fields() {
  * @see \Drupal\Core\Entity\Query\QueryInterface
  */
 function user_load_multiple(array $uids = NULL, $reset = FALSE) {
-  return entity_load_multiple('user', $uids, $reset);
+  $entities = entity_load_multiple('user', $uids, $reset);
+  // Return BC-entities.
+  foreach ($entities as $id => $entity) {
+    $entities[$id] = $entity->getBCEntity();
+  }
+  return $entities;
 }
 
 /**
@@ -321,7 +326,8 @@ function user_load_multiple(array $uids = NULL, $reset = FALSE) {
  * @see user_load_multiple()
  */
 function user_load($uid, $reset = FALSE) {
-  return entity_load('user', $uid, $reset);
+  $user = entity_load('user', $uid, $reset);
+  return $user ? $user->getBCEntity() : FALSE;
 }
 
 /**
@@ -337,7 +343,7 @@ function user_load($uid, $reset = FALSE) {
  */
 function user_load_by_mail($mail) {
   $users = entity_load_multiple_by_properties('user', array('mail' => $mail));
-  return reset($users);
+  return $users ? reset($users)->getBCEntity() : FALSE;
 }
 
 /**
@@ -353,7 +359,7 @@ function user_load_by_mail($mail) {
  */
 function user_load_by_name($name) {
   $users = entity_load_multiple_by_properties('user', array('name' => $name));
-  return reset($users);
+  return $users ? reset($users)->getBCEntity() : FALSE;
 }
 
 /**
@@ -434,7 +440,7 @@ function user_role_permissions($roles) {
 
   $role_permissions = $fetch = array();
 
-  foreach ($roles as $rid => $name) {
+  foreach ($roles as $rid) {
     if (isset($cache[$rid])) {
       $role_permissions[$rid] = $cache[$rid];
     }
@@ -485,6 +491,9 @@ function user_access($string, $account = NULL) {
     $account = $user;
   }
 
+  // Make sure we are working with the BC decorator.
+  $account = $account instanceof User ? $account->getBCEntity() : $account;
+
   // User #1 has all privileges:
   if ($account->uid == 1) {
     return TRUE;
@@ -623,7 +632,7 @@ function user_search_execute($keys = NULL, $conditions = NULL) {
 /**
  * Implements hook_user_view().
  */
-function user_user_view(User $account, EntityDisplay $display) {
+function user_user_view(EntityInterface $account, EntityDisplay $display) {
   if ($display->getComponent('member_for')) {
     $account->content['member_for'] = array(
       '#type' => 'item',
@@ -1736,7 +1745,7 @@ function user_mail($key, &$message, $params) {
   // allows the configuration objects to be localized for the user's language if
   // the locale module is enabled.
   $user_config_context = config_context_enter('Drupal\user\UserConfigContext');
-  $user_config_context->setAccount($params['account']);
+  $user_config_context->setAccount($params['account']->getOriginalEntity());
   $mail_config = config('user.mail');
 
    // We do not sanitize the token replacement, since the output of this
@@ -2335,6 +2344,7 @@ function theme_user_signature($variables) {
  */
 function user_preferred_langcode($account, $type = NULL, $default = NULL) {
   $language_list = language_list();
+  $account = $account->getBCEntity();
   if (isset($type)) {
     $preferred_langcode = $account->{'preferred_' . $type . '_langcode'};
   }
diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc
index 140b767..4e57868 100644
--- a/core/modules/user/user.pages.inc
+++ b/core/modules/user/user.pages.inc
@@ -67,7 +67,7 @@ function user_pass_submit($form, &$form_state) {
 
   $account = $form_state['values']['account'];
   // Mail one time login URL and instructions using current language.
-  $mail = _user_mail_notify('password_reset', $account, $language_interface->langcode);
+  $mail = _user_mail_notify('password_reset', $account->getBCEntity(), $language_interface->langcode);
   if (!empty($mail)) {
     watchdog('user', 'Password reset instructions mailed to %name at %email.', array('%name' => $account->name, '%email' => $account->mail));
     drupal_set_message(t('Further instructions have been sent to your e-mail address.'));
diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php
index b4c5118..fcbddcb 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php
@@ -37,11 +37,12 @@ protected function setUp() {
 
     $this->admin_user = $this->drupalCreateUser(array('access all views'));
     $this->web_user = $this->drupalCreateUser();
-    $this->web_role = current($this->web_user->roles);
+    $this->web_role = $this->web_user->roles[0];
 
     $this->normal_role = $this->drupalCreateRole(array());
     $this->normal_user = $this->drupalCreateUser(array('views_test_data test permission'));
-    $this->normal_user->roles[$this->normal_role] = $this->normal_role;
+    // @todo: How to add a new item to the roles field list. 
+    $this->normal_user->getOriginalEntity()->roles[2]->value = $this->normal_role;
     // @todo when all the plugin information is cached make a reset function and
     // call it here.
   }
