diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
index 3ccc88d..abb0a20 100644
--- a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
+++ b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
@@ -145,7 +145,7 @@ protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
     // activate compatibility mode.
     $queried_entities = $this->mapFromStorageRecords($queried_entities, $load_revision);
 
-    // Attach fields.
+    // Activate backward-compatibility mode to attach fields.
     if ($this->entityInfo['fieldable']) {
       // Prepare BC compatible entities for field API.
       $bc_entities = array();
@@ -436,7 +436,9 @@ protected function mapToStorageRecord(EntityInterface $entity) {
   protected function mapToRevisionStorageRecord(EntityInterface $entity) {
     $record = new \stdClass();
     foreach ($this->entityInfo['schema_fields_sql']['revision_table'] as $name) {
-      $record->$name = $entity->$name->value;
+      if (isset($entity->$name->value)) {
+        $record->$name = $entity->$name->value;
+      }
     }
     return $record;
   }
diff --git a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
index 8f5e521..2815954 100644
--- a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
+++ b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
@@ -72,19 +72,36 @@ public function &__get($name) {
       // avoid them becoming out of sync.
       unset($this->decorated->fields[$name]);
     }
-    // Allow accessing field values in entity default languages other than
-    // LANGUAGE_DEFAULT by mapping the values to LANGUAGE_DEFAULT.
-    $langcode = $this->decorated->language()->langcode;
-    if ($langcode != LANGUAGE_DEFAULT && isset($this->decorated->values[$name]) && is_array($this->decorated->values[$name])) {
-      if (isset($this->decorated->values[$name][LANGUAGE_DEFAULT]) && !isset($this->decorated->values[$name][$langcode])) {
-        $this->decorated->values[$name][$langcode] = &$this->decorated->values[$name][LANGUAGE_DEFAULT];
+    // When accessing values for entity properties that have been converted to
+    // an entity field, provide direct access to the plain value. This makes it
+    // possible to use the BC-decorator with properties; e.g., $node->title.
+    if (!field_info_field($name) && $this->decorated->getPropertyDefinition($name)) {
+      // In case the entity field is being created with a non-array value, let
+      // the field object unify the field value structure.
+      if (isset($this->decorated->values[$name][LANGUAGE_DEFAULT]) && !is_array($this->decorated->values[$name][LANGUAGE_DEFAULT])) {
+        $this->decorated->values[$name][LANGUAGE_DEFAULT] = $this->decorated->get($name)->getValue();
+        unset($this->decorated->fields[$name]);
       }
-    }
 
-    if (!isset($this->decorated->values[$name])) {
-      $this->decorated->values[$name] = NULL;
+      if (!isset($this->decorated->values[$name][LANGUAGE_DEFAULT][0]['value'])) {
+        $this->decorated->values[$name][LANGUAGE_DEFAULT][0]['value'] = NULL;
+      }
+      return $this->decorated->values[$name][LANGUAGE_DEFAULT][0]['value'];
+    }
+    else {
+      // Allow accessing field values in entity default languages other than
+      // LANGUAGE_DEFAULT by mapping the values to LANGUAGE_DEFAULT.
+      $langcode = $this->decorated->language()->langcode;
+      if ($langcode != LANGUAGE_DEFAULT && isset($this->decorated->values[$name]) && is_array($this->decorated->values[$name])) {
+        if (isset($this->decorated->values[$name][LANGUAGE_DEFAULT]) && !isset($this->decorated->values[$name][$langcode])) {
+          $this->decorated->values[$name][$langcode] = &$this->decorated->values[$name][LANGUAGE_DEFAULT];
+        }
+      }
+      if (!isset($this->decorated->values[$name])) {
+        $this->decorated->values[$name] = NULL;
+      }
+      return $this->decorated->values[$name];
     }
-    return $this->decorated->values[$name];
   }
 
   /**
@@ -93,17 +110,25 @@ public function &__get($name) {
    * Directly writes to the plain field values, as done by Drupal 7.
    */
   public function __set($name, $value) {
-    if (is_array($value) && $definition = $this->decorated->getPropertyDefinition($name)) {
-      // If field API sets a value with a langcode in entity language, move it
-      // to LANGUAGE_DEFAULT.
-      foreach ($value as $langcode => $data) {
-        if ($langcode != LANGUAGE_DEFAULT && $langcode == $this->decorated->language()->langcode) {
-          $value[LANGUAGE_DEFAULT] = $data;
-          unset($value[$langcode]);
+    // When updating values for entity properties that have been converted to
+    // an entity field, directly write to the plain value. This makes it
+    // possible to use the BC-decorator with properties; e.g., $node->title.
+    if (!field_info_field($name) && $this->decorated->getPropertyDefinition($name)) {
+      $this->decorated->values[$name][LANGUAGE_DEFAULT][0]['value'] = $value;
+    }
+    else {
+      if (is_array($value) && $definition = $this->decorated->getPropertyDefinition($name)) {
+        // If field API sets a value with a langcode in entity language, move it
+        // to LANGUAGE_DEFAULT.
+        foreach ($value as $langcode => $data) {
+          if ($langcode != LANGUAGE_DEFAULT && $langcode == $this->decorated->language()->langcode) {
+            $value[LANGUAGE_DEFAULT] = $data;
+            unset($value[$langcode]);
+          }
         }
       }
+      $this->decorated->values[$name] = $value;
     }
-    $this->decorated->values[$name] = $value;
     unset($this->decorated->fields[$name]);
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php
index ef133e1..8fa048d 100644
--- a/core/lib/Drupal/Core/Entity/EntityNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityNG.php
@@ -471,6 +471,12 @@ public function createDuplicate() {
       $uuid = new Uuid();
       $duplicate->{$entity_info['entity_keys']['uuid']}->value = $uuid->generate();
     }
+
+    // Check whether the entity type supports revisions and initialize it if so.
+    if (!empty($entity_info['entity_keys']['revision'])) {
+      $duplicate->{$entity_info['entity_keys']['revision']}->value = NULL;
+    }
+
     return $duplicate;
   }
 
@@ -504,4 +510,5 @@ public function label($langcode = NULL) {
     }
     return $label;
   }
+
 }
diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
index 4c91741..b5bc6d4 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
@@ -57,7 +57,7 @@ protected function attachLoad(&$records, $load_revision = FALSE) {
   public function create(array $values) {
     // We have to determine the bundle first.
     if (empty($values['node_type']) && !empty($values['nid'])) {
-      $node = node_load($values['nid']);
+      $node = node_load(is_object($values['nid']) ? $values['nid']->value : $values['nid']);
       $values['node_type'] = 'comment_node_' . $node->type;
     }
     $comment = new $this->entityClass(array(), $this->entityType, $values['node_type']);
diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php
index d855384..138597b 100644
--- a/core/modules/node/lib/Drupal/node/NodeStorageController.php
+++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\node;
 
-use Drupal\Core\Entity\DatabaseStorageController;
+use Drupal\Core\Entity\DatabaseStorageControllerNG;
 use Drupal\Core\Entity\EntityInterface;
 
 /**
@@ -16,31 +16,40 @@
  * This extends the Drupal\Core\Entity\DatabaseStorageController class, adding
  * required special handling for node entities.
  */
-class NodeStorageController extends DatabaseStorageController {
+class NodeStorageController extends DatabaseStorageControllerNG {
 
   /**
    * Overrides Drupal\Core\Entity\DatabaseStorageController::create().
    */
   public function create(array $values) {
-    $node = parent::create($values);
-
-    // Set the created time to now.
-    if (empty($node->created)) {
-      $node->created = REQUEST_TIME;
+    // @todo Handle this through property defaults.
+    if (empty($values['created'])) {
+      $values['created'] = REQUEST_TIME;
     }
-
-    return $node;
+    return parent::create($values);
   }
 
   /**
-   * Overrides Drupal\Core\Entity\DatabaseStorageController::attachLoad().
+   * Overrides Drupal\Core\Entity\DatabaseStorageControllerNG::attachLoad().
    */
-  protected function attachLoad(&$nodes, $load_revision = FALSE) {
+  protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
+    $queried_entities = $this->mapFromStorageRecords($queried_entities, $load_revision);
+
     // Create an array of nodes for each content type and pass this to the
-    // object type specific callback.
+    // object type specific callback. To preserve backward-compatibility we
+    // pass on BC decorators to node-specific hooks, while we pass on the
+    // regular entity objects else.
     $typed_nodes = array();
-    foreach ($nodes as $id => $entity) {
-      $typed_nodes[$entity->type][$id] = $entity;
+    foreach ($queried_entities as $id => $entity) {
+      $nodes[$id] = $entity->getBCEntity();
+      $typed_nodes[$entity->bundle()][$id] = $nodes[$id];
+    }
+
+    if ($load_revision) {
+      field_attach_load_revision($this->entityType, $nodes);
+    }
+    else {
+      field_attach_load($this->entityType, $nodes);
     }
 
     // Call object type specific callbacks on each typed array of nodes.
@@ -55,7 +64,19 @@ protected function attachLoad(&$nodes, $load_revision = FALSE) {
     // hook_node_load(), containing a list of node types that were loaded.
     $argument = array_keys($typed_nodes);
     $this->hookLoadArguments = array($argument);
-    parent::attachLoad($nodes, $load_revision);
+
+    // Call hook_entity_load().
+    foreach (module_implements('entity_load') as $module) {
+      $function = $module . '_entity_load';
+      $function($queried_entities, $this->entityType);
+    }
+    // Call hook_TYPE_load(). The first argument for hook_TYPE_load() are
+    // always the queried entities, followed by additional arguments set in
+    // $this->hookLoadArguments.
+    $args = array_merge(array($nodes), $this->hookLoadArguments);
+    foreach (module_implements($this->entityType . '_load') as $module) {
+      call_user_func_array($module . '_' . $this->entityType . '_load', $args);
+    }
   }
 
   /**
@@ -78,15 +99,31 @@ protected function buildQuery($ids, $revision_id = FALSE) {
    */
   protected function invokeHook($hook, EntityInterface $node) {
     if ($hook == 'insert' || $hook == 'update') {
-      node_invoke($node, $hook);
+      node_invoke($node->getBCEntity(), $hook);
     }
     else if ($hook == 'predelete') {
       // 'delete' is triggered in 'predelete' is here to preserve hook ordering
       // from Drupal 7.
-      node_invoke($node, 'delete');
+      node_invoke($node->getBCEntity(), 'delete');
     }
 
-    parent::invokeHook($hook, $node);
+    // Inline parent::invokeHook() to pass on BC-entities to node-specific
+    // hooks.
+
+    $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($node->getBCEntity());
+    }
+
+    // Invoke the hook.
+    module_invoke_all($this->entityType . '_' . $hook, $node->getBCEntity());
+    // Invoke the respective entity-level hook.
+    module_invoke_all('entity_' . $hook, $node, $this->entityType);
   }
 
   /**
@@ -111,10 +148,10 @@ protected function preSaveRevision(\stdClass $record, EntityInterface $entity) {
       // @todo: Make the {node_revision}.log column nullable so that we can
       // remove this check.
       if (!isset($record->log)) {
-        $record->log = '';
+        $record->log->value = '';
       }
     }
-    elseif (!isset($record->log) || $record->log === '') {
+    elseif (!isset($record->log) || $record->log->value === '') {
       // If we are updating an existing node without adding a new revision, we
       // need to make sure $node->log is unset whenever it is empty. As long as
       // $node->log is unset, drupal_write_record() will not attempt to update
@@ -125,29 +162,30 @@ protected function preSaveRevision(\stdClass $record, EntityInterface $entity) {
     }
 
     if ($entity->isNewRevision()) {
-      $record->timestamp = REQUEST_TIME;
-      $record->uid = isset($record->revision_uid) ? $record->revision_uid : $GLOBALS['user']->uid;
+      $record->timestamp->value = REQUEST_TIME;
+      $record->uid->value = isset($record->revision_uid) ? $record->revision_uid->value : $GLOBALS['user']->uid;
     }
   }
 
   /**
    * Overrides Drupal\Core\Entity\DatabaseStorageController::postSave().
    */
-  function postSave(EntityInterface $node, $update) {
+  public function postSave(EntityInterface $node, $update) {
     // Update the node access table for this node, but only if it is the
     // default revision. There's no need to delete existing records if the node
     // is new.
     if ($node->isDefaultRevision()) {
-      node_access_acquire_grants($node, $update);
+      node_access_acquire_grants($node->getBCEntity(), $update);
     }
   }
+
   /**
    * Overrides Drupal\Core\Entity\DatabaseStorageController::preDelete().
    */
-  function preDelete($entities) {
+  public function preDelete($entities) {
     if (module_exists('search')) {
       foreach ($entities as $id => $entity) {
-        search_reindex($entity->nid, 'node');
+        search_reindex($entity->nid->value, 'node');
       }
     }
   }
@@ -163,4 +201,105 @@ protected function postDelete($nodes) {
       ->condition('nid', $ids, 'IN')
       ->execute();
   }
+
+  /**
+   * Overrides \Drupal\Core\Entity\DataBaseStorageControllerNG::basePropertyDefinitions().
+   */
+  public function baseFieldDefinitions() {
+    $properties['nid'] = array(
+      'label' => t('Node ID'),
+      'description' => t('The node ID.'),
+      'type' => 'integer_field',
+      'read-only' => TRUE,
+    );
+    $properties['uuid'] = array(
+      'label' => t('UUID'),
+      'description' => t('The node UUID.'),
+      'type' => 'string_field',
+      'read-only' => TRUE,
+    );
+    $properties['vid'] = array(
+      'label' => t('Revision ID'),
+      'description' => t('The node revision ID.'),
+      'type' => 'integer_field',
+      'read-only' => TRUE,
+    );
+    $properties['type'] = array(
+      'label' => t('Type'),
+      'description' => t('The node type.'),
+      'type' => 'string_field',
+      'read-only' => TRUE,
+    );
+    $properties['langcode'] = array(
+      'label' => t('Language code'),
+      'description' => t('The node language code.'),
+      'type' => 'language_field',
+    );
+    $properties['title'] = array(
+      'label' => t('Title'),
+      'description' => t('The title of this node, always treated as non-markup plain text.'),
+      'type' => 'string_field',
+    );
+    $properties['uid'] = array(
+      'label' => t('User ID'),
+      'description' => t('The user ID of the node author.'),
+      'type' => 'entityreference_field',
+      'settings' => array('entity type' => 'user'),
+    );
+    $properties['status'] = array(
+      'label' => t('Publishing status'),
+      'description' => t('A boolean indicating whether the node is published.'),
+      'type' => 'boolean_field',
+    );
+    $properties['created'] = array(
+      'label' => t('Created'),
+      'description' => t('The time that the node was created.'),
+      'type' => 'integer_field',
+    );
+    $properties['changed'] = array(
+      'label' => t('Changed'),
+      'description' => t('The time that the node was last edited.'),
+      'type' => 'integer_field',
+    );
+    $properties['comment'] = array(
+      'label' => t('Comment'),
+      'description' => t('Whether comments are allowed on this node: 0 = no, 1 = closed (read only), 2 = open (read/write).'),
+      'type' => 'integer_field',
+    );
+    $properties['promote'] = array(
+      'label' => t('Promote'),
+      'description' => t('A boolean indicating whether the node should be displayed on the front page.'),
+      'type' => 'boolean_field',
+    );
+    $properties['sticky'] = array(
+      'label' => t('Sticky'),
+      'description' => t('A boolean indicating whether the node should be displayed at the top of lists in which it appears.'),
+      'type' => 'boolean_field',
+    );
+    $properties['tnid'] = array(
+      'label' => t('Translation set ID'),
+      'description' => t('The translation set id for this node, which equals the node id of the source post in each set.'),
+      'type' => 'integer_field',
+    );
+    $properties['translate'] = array(
+      'label' => t('Translate'),
+      'description' => t('A boolean indicating whether this translation page needs to be updated.'),
+      'type' => 'boolean_field',
+    );
+    $properties['revision_timestamp'] = array(
+      'label' => t('Revision timestamp'),
+      'description' => t('The time that the current revision was created.'),
+      'type' => 'integer_field',
+      'queryable' => FALSE,
+    );
+    $properties['revision_uid'] = array(
+      'label' => t('Revision user ID'),
+      'description' => t('The user ID of the author of the current revision.'),
+      'type' => 'entityreference_field',
+      'settings' => array('entity type' => 'user'),
+      'queryable' => FALSE,
+    );
+    return $properties;
+  }
+
 }
diff --git a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
index 6cf9fac..29fc133 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
@@ -7,232 +7,14 @@
 
 namespace Drupal\node\Plugin\Core\Entity;
 
-use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\Core\Entity\Entity;
-use Drupal\Core\Annotation\Plugin;
-use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Entity\EntityBCDecorator;
 
 /**
- * Defines the node entity class.
+ * Extends the EntityBCDecorator for nodes.
  *
- * @Plugin(
- *   id = "node",
- *   label = @Translation("Content"),
- *   bundle_label = @Translation("Content type"),
- *   module = "node",
- *   controller_class = "Drupal\node\NodeStorageController",
- *   render_controller_class = "Drupal\node\NodeRenderController",
- *   form_controller_class = {
- *     "default" = "Drupal\node\NodeFormController"
- *   },
- *   translation_controller_class = "Drupal\node\NodeTranslationController",
- *   base_table = "node",
- *   revision_table = "node_revision",
- *   uri_callback = "node_uri",
- *   fieldable = TRUE,
- *   entity_keys = {
- *     "id" = "nid",
- *     "revision" = "vid",
- *     "bundle" = "type",
- *     "label" = "title",
- *     "uuid" = "uuid"
- *   },
- *   bundle_keys = {
- *     "bundle" = "type"
- *   },
- *   view_modes = {
- *     "full" = {
- *       "label" = "Full content",
- *       "custom_settings" = FALSE
- *     },
- *     "teaser" = {
- *       "label" = "Teaser",
- *       "custom_settings" = TRUE
- *     },
- *     "rss" = {
- *       "label" = "RSS",
- *       "custom_settings" = FALSE
- *     }
- *   }
- * )
+ * We extend the EntityBCDecorator only to allow BC-nodes to be passed to
+ * type-hinted functions.
  */
-class Node extends Entity implements ContentEntityInterface {
-
-  /**
-   * The node ID.
-   *
-   * @var integer
-   */
-  public $nid;
-
-  /**
-   * The node revision ID.
-   *
-   * @var integer
-   */
-  public $vid;
-
-  /**
-   * Indicates whether this is the default node revision.
-   *
-   * The default revision of a node is the one loaded when no specific revision
-   * has been specified. Only default revisions are saved to the node table.
-   *
-   * @var boolean
-   */
-  public $isDefaultRevision = TRUE;
-
-  /**
-   * The node UUID.
-   *
-   * @var string
-   */
-  public $uuid;
-
-  /**
-   * The node content type (bundle).
-   *
-   * @var string
-   */
-  public $type;
-
-  /**
-   * The node language code.
-   *
-   * @var string
-   */
-  public $langcode = LANGUAGE_NOT_SPECIFIED;
-
-  /**
-   * The node title.
-   *
-   * @var string
-   */
-  public $title;
-
-  /**
-   * The node owner's user ID.
-   *
-   * @var integer
-   */
-  public $uid;
-
-  /**
-   * The node published status indicator.
-   *
-   * Unpublished nodes are only visible to their authors and to administrators.
-   * The value is either NODE_PUBLISHED or NODE_NOT_PUBLISHED.
-   *
-   * @var integer
-   */
-  public $status;
-
-  /**
-   * The node creation timestamp.
-   *
-   * @var integer
-   */
-  public $created;
-
-  /**
-   * The node modification timestamp.
-   *
-   * @var integer
-   */
-  public $changed;
-
-  /**
-   * The node comment status indicator.
-   *
-   * COMMENT_NODE_HIDDEN => no comments
-   * COMMENT_NODE_CLOSED => comments are read-only
-   * COMMENT_NODE_OPEN => open (read/write)
-   *
-   * @var integer
-   */
-  public $comment;
-
-  /**
-   * The node promotion status.
-   *
-   * Promoted nodes should be displayed on the front page of the site. The value
-   * is either NODE_PROMOTED or NODE_NOT_PROMOTED.
-   *
-   * @var integer
-   */
-  public $promote;
-
-  /**
-   * The node sticky status.
-   *
-   * Sticky nodes should be displayed at the top of lists in which they appear.
-   * The value is either NODE_STICKY or NODE_NOT_STICKY.
-   *
-   * @var integer
-   */
-  public $sticky;
-
-  /**
-   * The node translation set ID.
-   *
-   * Translations sets are based on the ID of the node containing the source
-   * text for the translation set.
-   *
-   * @var integer
-   */
-  public $tnid;
-
-  /**
-   * The node translation status.
-   *
-   * If the translation page needs to be updated, the value is 1; otherwise 0.
-   *
-   * @var integer
-   */
-  public $translate;
-
-  /**
-   * The node revision creation timestamp.
-   *
-   * @var integer
-   */
-  public $revision_timestamp;
-
-  /**
-   * The node revision author's user ID.
-   *
-   * @var integer
-   */
-  public $revision_uid;
-
-  /**
-   * Implements Drupal\Core\Entity\EntityInterface::id().
-   */
-  public function id() {
-    return $this->nid;
-  }
-
-  /**
-   * Implements Drupal\Core\Entity\EntityInterface::bundle().
-   */
-  public function bundle() {
-    return $this->type;
-  }
-
-  /**
-   * Overrides Drupal\Core\Entity\Entity::createDuplicate().
-   */
-  public function createDuplicate() {
-    $duplicate = parent::createDuplicate();
-    $duplicate->vid = NULL;
-    return $duplicate;
-  }
-
-  /**
-   * Overrides Drupal\Core\Entity\Entity::getRevisionId().
-   */
-  public function getRevisionId() {
-    return $this->vid;
-  }
+class Node extends EntityBCDecorator {
 
 }
diff --git a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/NodeNG.php b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/NodeNG.php
new file mode 100644
index 0000000..d261ac6
--- /dev/null
+++ b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/NodeNG.php
@@ -0,0 +1,270 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\node\Plugin\Core\Entity\NodeNG.
+ */
+
+namespace Drupal\node\Plugin\Core\Entity;
+
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\EntityNG;
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Defines the node entity class.
+ *
+ * @see \Drupal\Core\Entity\EntityNG
+ *
+ * @Plugin(
+ *   id = "node",
+ *   label = @Translation("Content"),
+ *   bundle_label = @Translation("Content type"),
+ *   module = "node",
+ *   controller_class = "Drupal\node\NodeStorageController",
+ *   render_controller_class = "Drupal\node\NodeRenderController",
+ *   form_controller_class = {
+ *     "default" = "Drupal\node\NodeFormController"
+ *   },
+ *   translation_controller_class = "Drupal\node\NodeTranslationController",
+ *   base_table = "node",
+ *   revision_table = "node_revision",
+ *   uri_callback = "node_uri",
+ *   fieldable = TRUE,
+ *   entity_keys = {
+ *     "id" = "nid",
+ *     "revision" = "vid",
+ *     "bundle" = "type",
+ *     "label" = "title",
+ *     "uuid" = "uuid"
+ *   },
+ *   bundle_keys = {
+ *     "bundle" = "type"
+ *   },
+ *   view_modes = {
+ *     "full" = {
+ *       "label" = "Full content",
+ *       "custom_settings" = FALSE
+ *     },
+ *     "teaser" = {
+ *       "label" = "Teaser",
+ *       "custom_settings" = TRUE
+ *     },
+ *     "rss" = {
+ *       "label" = "RSS",
+ *       "custom_settings" = FALSE
+ *     }
+ *   }
+ * )
+ */
+class NodeNG extends EntityNG implements ContentEntityInterface {
+
+  /**
+   * The node ID.
+   *
+   * @var integer
+   */
+  public $nid;
+
+  /**
+   * The node revision ID.
+   *
+   * @var integer
+   */
+  public $vid;
+
+  /**
+   * Indicates whether this is the default node revision.
+   *
+   * The default revision of a node is the one loaded when no specific revision
+   * has been specified. Only default revisions are saved to the node table.
+   *
+   * @var boolean
+   */
+  public $isDefaultRevision;
+
+  /**
+   * The node UUID.
+   *
+   * @var string
+   */
+  public $uuid;
+
+  /**
+   * The node content type (bundle).
+   *
+   * @var string
+   */
+  public $type;
+
+  /**
+   * The node language code.
+   *
+   * @var string
+   */
+  public $langcode;
+
+  /**
+   * The node title.
+   *
+   * @var string
+   */
+  public $title;
+
+  /**
+   * The node owner's user ID.
+   *
+   * @var integer
+   */
+  public $uid;
+
+  /**
+   * The node published status indicator.
+   *
+   * Unpublished nodes are only visible to their authors and to administrators.
+   * The value is either NODE_PUBLISHED or NODE_NOT_PUBLISHED.
+   *
+   * @var integer
+   */
+  public $status;
+
+  /**
+   * The node creation timestamp.
+   *
+   * @var integer
+   */
+  public $created;
+
+  /**
+   * The node modification timestamp.
+   *
+   * @var integer
+   */
+  public $changed;
+
+  /**
+   * The node comment status indicator.
+   *
+   * COMMENT_NODE_HIDDEN => no comments
+   * COMMENT_NODE_CLOSED => comments are read-only
+   * COMMENT_NODE_OPEN => open (read/write)
+   *
+   * @var integer
+   */
+  public $comment;
+
+  /**
+   * The node promotion status.
+   *
+   * Promoted nodes should be displayed on the front page of the site. The value
+   * is either NODE_PROMOTED or NODE_NOT_PROMOTED.
+   *
+   * @var integer
+   */
+  public $promote;
+
+  /**
+   * The node sticky status.
+   *
+   * Sticky nodes should be displayed at the top of lists in which they appear.
+   * The value is either NODE_STICKY or NODE_NOT_STICKY.
+   *
+   * @var integer
+   */
+  public $sticky;
+
+  /**
+   * The node translation set ID.
+   *
+   * Translations sets are based on the ID of the node containing the source
+   * text for the translation set.
+   *
+   * @var integer
+   */
+  public $tnid;
+
+  /**
+   * The node translation status.
+   *
+   * If the translation page needs to be updated, the value is 1; otherwise 0.
+   *
+   * @var integer
+   */
+  public $translate;
+
+  /**
+   * The node revision creation timestamp.
+   *
+   * @var integer
+   */
+  public $revision_timestamp;
+
+  /**
+   * The node revision author's user ID.
+   *
+   * @var integer
+   */
+  public $revision_uid;
+
+  /**
+   * 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))),
+    'isDefaultRevision' => array(LANGUAGE_DEFAULT => array(0 => array('value' => TRUE))),
+  );
+
+  /**
+   * Overrides \Drupal\Core\Entity\EntityNG::init().
+   */
+  protected function init() {
+    parent::init();
+    // We unset all defined properties, so magic getters apply.
+    unset($this->nid);
+    unset($this->vid);
+    unset($this->isDefaultRevision);
+    unset($this->uuid);
+    unset($this->type);
+    unset($this->title);
+    unset($this->uid);
+    unset($this->status);
+    unset($this->created);
+    unset($this->changed);
+    unset($this->comment);
+    unset($this->promote);
+    unset($this->sticky);
+    unset($this->tnid);
+    unset($this->translate);
+    unset($this->revision_timestamp);
+    unset($this->revision_uid);
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityInterface::id().
+   */
+  public function id() {
+    return $this->get('nid')->value;
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\Entity::getRevisionId().
+   */
+  public function getRevisionId() {
+    return $this->get('vid')->value;
+  }
+
+ /**
+   * Overrides EntityNG::getBCEntity().
+   */
+  public function getBCEntity() {
+    if (!isset($this->bcEntity)) {
+      $this->bcEntity = new Node($this);
+    }
+    return $this->bcEntity;
+  }
+}
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index eb56876..74d59d1 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -923,7 +923,12 @@ function node_invoke($node, $hook, $a2 = NULL, $a3 = NULL, $a4 = NULL) {
  * @see Drupal\Core\Entity\Query\EntityQueryInterface
  */
 function node_load_multiple(array $nids = NULL, $reset = FALSE) {
-  return entity_load_multiple('node', $nids, $reset);
+  $entities = entity_load_multiple('node', $nids, $reset);
+  // Return BC-entities.
+  foreach ($entities as $id => $entity) {
+    $entities[$id] = $entity->getBCEntity();
+  }
+  return $entities;
 }
 
 /**
@@ -939,7 +944,7 @@ function node_load_multiple(array $nids = NULL, $reset = FALSE) {
  *   A fully-populated node entity, or FALSE if the node is not found.
  */
 function node_load($nid = NULL, $reset = FALSE) {
-  return entity_load('node', $nid, $reset);
+  return entity_load('node', $nid, $reset)->getBCEntity();
 }
 
 /**
diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc
index 245fef7..82cc5ff 100644
--- a/core/modules/node/node.pages.inc
+++ b/core/modules/node/node.pages.inc
@@ -106,7 +106,7 @@ function node_add($node_type) {
     'name' => (isset($user->name) ? $user->name : ''),
     'type' => $type,
     'langcode' => $langcode ? $langcode : language_default()->langcode,
-  ));
+  ))->getBCEntity();
   drupal_set_title(t('Create @name', array('@name' => $node_type->name)), PASS_THROUGH);
   $output = entity_get_form($node);
 
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 92c6ae5..fa87182 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -281,8 +281,8 @@ protected function drupalCreateNode(array $settings = array()) {
 
     // Small hack to link revisions to our test user.
     db_update('node_revision')
-      ->fields(array('uid' => $node->uid))
-      ->condition('vid', $node->vid)
+      ->fields(array('uid' => $node->uid->value))
+      ->condition('vid', $node->vid->value)
       ->execute();
     return $node;
   }
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 f01d440..ce8f7cf 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
@@ -537,4 +537,28 @@ protected function assertComputedProperties($entity_type) {
     $entity = entity_load($entity_type, $entity->id());
     $this->assertEqual($entity->field_test_text->processed, $target, format_string('%entity_type: Text is processed with the default filter.', array('%entity_type' => $entity_type)));
   }
+
+  /**
+   * Tests using the entity BC decorator with entity properties.
+   *
+   * @todo: Remove once the entit BC decorator is removed.
+   * @see \Drupal\Core\Entity\EntityBCDecorator
+   */
+  public function testBCDecorator() {
+    // Test using comment subject via the BC decorator.
+    module_enable(array('node', 'comment'));
+    $node = $this->drupalCreateNode();
+    $comment = entity_create('comment', array(
+      'nid' => $node->nid,
+      'subject' => 'old-value',
+    ));
+    $comment->save();
+
+    // Test reading.
+    $bc_entity = $comment->getBCEntity();
+    $this->assertEqual($bc_entity->subject, 'old-value', 'Accessing entity property via BC decorator.');
+    // Test writing.
+    $bc_entity->subject = 'new';
+    $this->assertEqual($comment->subject->value, 'new', 'Updated entity property via BC decorator.');
+  }
 }
