diff --git a/handlers/views_handler_field_entity.inc b/handlers/views_handler_field_entity.inc
new file mode 100644
index 0000000..338492f
--- /dev/null
+++ b/handlers/views_handler_field_entity.inc
@@ -0,0 +1,54 @@
+<?php
+/**
+ * A handler to display data from entity objects.
+ *
+ * @ingroup views_field_handlers
+ */
+class views_handler_field_entity extends views_handler_field {
+
+  protected $entity_type, $entities;
+
+  /**
+   * Override the parent's query method, since it doesn't need to do anything.
+   */
+  function query() {
+    // Only do something if the default backend is in use.
+    if (get_class($this->query) != 'views_plugin_query_default') {
+      return;
+    }
+
+    $base_table_alias = $base_table = $this->view->base_table;
+    $base_field = $this->view->base_field;
+
+    if (!empty($this->relationship)) {
+      foreach ($this->view->relationship as $relationship) {
+        if ($relationship->alias == $this->relationship) {
+          $base_table = $relationship->definition['base'];
+          $base_table_alias = $relationship->alias;
+
+          $table_data = views_fetch_data($base_table);
+          $base_field = $table_data['table']['base']['field'];
+        }
+      }
+    }
+
+    // We always need the base field (entity_id).
+    $this->field_alias = $this->query->add_field($base_table_alias, $base_field, '');
+  }
+
+  /**
+   * Load the entities for all fields that are about to be displayed.
+   */
+  function pre_render(&$values) {
+    if (!empty($values)) {
+      list($this->entity_type, $this->entities) = $this->query->get_result_entities($values, !empty($this->relationship) ? $this->relationship : NULL, $this->field_alias);
+    }
+  }
+
+  /**
+   * Overridden to return the entity object.
+   */
+  function get_value($values, $field = NULL) {
+    return isset($this->entities[$this->view->row_index]) ? $this->entities[$this->view->row_index] : FALSE;
+  }
+}
diff --git a/modules/comment.views.inc b/modules/comment.views.inc
index 43bc6e1..ed15386 100644
--- a/modules/comment.views.inc
+++ b/modules/comment.views.inc
@@ -26,6 +26,7 @@ function comment_views_data() {
   $data['comment']['table']['base'] = array(
     'field' => 'cid',
     'title' => t('Comment'),
+    'entity type' => 'comment',
     'help' => t("Comments are responses to node content."),
   );
 
diff --git a/modules/file.views.inc b/modules/file.views.inc
index 6574998..1f00ca4 100644
--- a/modules/file.views.inc
+++ b/modules/file.views.inc
@@ -26,6 +26,7 @@ function file_field_views_data($field) {
     $data[$table_name][$field['field_name'] . '_fid']['relationship'] = array(
       'handler' => 'views_handler_relationship',
       'base' => 'file_managed',
+      'entity type' => 'file',
       'base field' => 'fid',
       'label' => t('file from !field_name', array('!field_name' => $field['field_name'])),
     );
diff --git a/modules/node.views.inc b/modules/node.views.inc
index 563b15c..c5026bb 100644
--- a/modules/node.views.inc
+++ b/modules/node.views.inc
@@ -26,6 +26,7 @@ function node_views_data() {
   $data['node']['table']['base'] = array(
     'field' => 'nid',
     'title' => t('Content'),
+    'entity type' => 'node',
     'weight' => -10,
     'access query tag' => 'node_access',
     'defaults' => array(
diff --git a/modules/node/views_handler_field_node_link.inc b/modules/node/views_handler_field_node_link.inc
index c9339ac..f42328f 100644
--- a/modules/node/views_handler_field_node_link.inc
+++ b/modules/node/views_handler_field_node_link.inc
@@ -2,17 +2,11 @@
 /**
  * Field handler to present a link to the node.
  */
-class views_handler_field_node_link extends views_handler_field {
-  function construct() {
-    parent::construct();
-    $this->additional_fields['nid'] = 'nid';
-  }
+class views_handler_field_node_link extends views_handler_field_entity {
 
   function option_definition() {
     $options = parent::option_definition();
-
     $options['text'] = array('default' => '', 'translatable' => TRUE);
-
     return $options;
   }
 
@@ -25,20 +19,18 @@ class views_handler_field_node_link extends views_handler_field {
     parent::options_form($form, $form_state);
   }
 
-  function query() {
-    $this->ensure_my_table();
-    $this->add_additional_fields();
-  }
-
   function render($values) {
-    $value = $this->get_value($values, 'nid');
-    return $this->render_link($this->sanitize_value($value), $values);
+    if ($entity = $this->get_value($values)) {
+      return $this->render_link($entity);
+    }
   }
 
-  function render_link($data, $values) {
-    $this->options['alter']['make_link'] = TRUE;
-    $this->options['alter']['path'] = "node/$data";
-    $text = !empty($this->options['text']) ? $this->options['text'] : t('view');
-    return $text;
+  function render_link($node) {
+    if (node_access('view', $node)) {
+      $this->options['alter']['make_link'] = TRUE;
+      $this->options['alter']['path'] = "node/$node->nid";
+      $text = !empty($this->options['text']) ? $this->options['text'] : t('view');
+      return $text;
+    }
   }
 }
diff --git a/modules/node/views_handler_field_node_link_delete.inc b/modules/node/views_handler_field_node_link_delete.inc
index caf7439..8b057cd 100644
--- a/modules/node/views_handler_field_node_link_delete.inc
+++ b/modules/node/views_handler_field_node_link_delete.inc
@@ -3,19 +3,12 @@
  * Field handler to present a link to delete a node.
  */
 class views_handler_field_node_link_delete extends views_handler_field_node_link {
-  function construct() {
-    parent::construct();
-    $this->additional_fields['type'] = 'type';
-    $this->additional_fields['uid'] = 'uid';
-  }
 
-  function render_link($data, $values) {
-    // ensure user has access to edit this node.
-    $node = new stdClass();
-    $node->nid = $this->get_value($values, 'nid');
-    $node->uid = $this->get_value($values, 'uid');
-    $node->type = $this->get_value($values, 'type');
-    $node->status = 1; // unpublished nodes ignore access control
+  /**
+   * Renders the link.
+   */
+  function render_link($node) {
+    // Ensure user has access to delete this node.
     if (!node_access('delete', $node)) {
       return;
     }
diff --git a/modules/node/views_handler_field_node_link_edit.inc b/modules/node/views_handler_field_node_link_edit.inc
index 687412f..074b669 100644
--- a/modules/node/views_handler_field_node_link_edit.inc
+++ b/modules/node/views_handler_field_node_link_edit.inc
@@ -3,19 +3,12 @@
  * Field handler to present a link node edit.
  */
 class views_handler_field_node_link_edit extends views_handler_field_node_link {
-  function construct() {
-    parent::construct();
-    $this->additional_fields['uid'] = 'uid';
-    $this->additional_fields['type'] = 'type';
-  }
 
-  function render_link($data, $values) {
-    // ensure user has access to edit this node.
-    $node = new stdClass();
-    $node->nid = $this->get_value($values, 'nid');
-    $node->uid = $this->get_value($values, 'uid');
-    $node->type = $this->get_value($values, 'type');
-    $node->status = 1; // unpublished nodes ignore access control
+  /**
+   * Renders the link.
+   */
+  function render_link($node) {
+    // Ensure user has access to edit this node.
     if (!node_access('update', $node)) {
       return;
     }
diff --git a/modules/taxonomy.views.inc b/modules/taxonomy.views.inc
index 927d083..d3024cb 100644
--- a/modules/taxonomy.views.inc
+++ b/modules/taxonomy.views.inc
@@ -95,6 +95,7 @@ function taxonomy_views_data() {
   $data['taxonomy_term_data']['table']['base'] = array(
     'field' => 'tid',
     'title' => t('Term'),
+    'entity type' => 'taxonomy_term',
     'help' => t('Taxonomy terms are attached to nodes.'),
     'access query tag' => 'term_access',
   );
diff --git a/modules/user.views.inc b/modules/user.views.inc
index 442a7b2..fe2fd0e 100644
--- a/modules/user.views.inc
+++ b/modules/user.views.inc
@@ -24,6 +24,7 @@ function user_views_data() {
   $data['users']['table']['base'] = array(
     'field' => 'uid',
     'title' => t('User'),
+    'entity type' => 'user',
     'help' => t('Users who have created accounts on your site.'),
     'access query tag' => 'user_access',
   );
diff --git a/plugins/views_plugin_query.inc b/plugins/views_plugin_query.inc
index f661269..f200384 100644
--- a/plugins/views_plugin_query.inc
+++ b/plugins/views_plugin_query.inc
@@ -148,4 +148,10 @@ class views_plugin_query extends views_plugin {
     $this->group_operator = strtoupper($type);
   }
 
+  /**
+   * Returns the according entity objects for the given query results.
+   */
+  function get_result_entities($results, $relationship = NULL) {
+    return FALSE;
+  }
 }
diff --git a/plugins/views_plugin_query_default.inc b/plugins/views_plugin_query_default.inc
index a2f8a74..228a043 100644
--- a/plugins/views_plugin_query_default.inc
+++ b/plugins/views_plugin_query_default.inc
@@ -79,6 +79,11 @@ class views_plugin_query_default extends views_plugin_query {
    */
    var $pager = NULL;
 
+   /**
+    * An array mapping table aliases and field names to field aliases.
+    */
+   var $field_aliases = array();
+
   /**
    * Constructor; Create the basic query object and fill with default values.
    */
@@ -782,6 +787,9 @@ class views_plugin_query_default extends views_plugin_query {
       $this->fields[$alias] = $field_info;
     }
 
+    // Keep track of all aliases used.
+    $this->field_aliases[$table][$field] = $alias;
+
     return $alias;
   }
 
@@ -1021,6 +1029,15 @@ class views_plugin_query_default extends views_plugin_query {
   }
 
   /**
+   * Returns the alias for the given field added to $table.
+   *
+   * @see views_plugin_query_default::add_field()
+   */
+  function get_field_alias($table_alias, $field) {
+    return isset($this->field_aliases[$table_alias][$field]) ? $this->field_aliases[$table_alias][$field] : FALSE;
+  }
+
+  /**
    * Generates a unique placeholder used in the db query.
    */
   function placeholder($base = 'views') {
@@ -1463,6 +1480,49 @@ class views_plugin_query_default extends views_plugin_query {
       ),
     );
   }
+
+  /**
+   * Returns the according entity objects for the given query results.
+   *
+   */
+  function get_result_entities($results, $relationship = NULL) {
+    $base_table = $this->base_table;
+    $base_table_alias = $base_table;
+
+    if (!empty($relationship)) {
+      foreach ($this->view->relationship as $current) {
+        if ($current->alias == $relationship) {
+          $base_table = $current->definition['base'];
+          $base_table_alias = $relationship;
+        }
+      }
+    }
+    $table_data = views_fetch_data($base_table);
+
+    // Bail out if the base-table has not specified the according entity-type.
+    if (!isset($table_data['table']['base']['entity type'])) {
+      return FALSE;
+    }
+    $entity_type = $table_data['table']['base']['entity type'];
+    $info = entity_get_info($entity_type);
+    $id_alias = $this->get_field_alias($base_table_alias, $info['entity keys']['id']);
+
+    // Assemble the ids of the entities to load.
+    $ids = array();
+    foreach ($results as $key => $result) {
+      if (isset($result->$id_alias)) {
+        $ids[$key] = $result->$id_alias;
+      }
+    }
+
+    $entities = entity_load($entity_type, $ids);
+    // Re-key the array by row-index.
+    $result = array();
+    foreach ($ids as $key => $id) {
+      $result[$key] = isset($entities[$id]) ? $entities[$id] : FALSE;
+    }
+    return array($entity_type, $result);
+  }
 }
 
 function views_query_default_aggregation_method_simple($group_type, $field) {
diff --git a/views.info b/views.info
index 0dd88aa..579135f 100644
--- a/views.info
+++ b/views.info
@@ -25,6 +25,7 @@ files[] = handlers/views_handler_field_counter.inc
 files[] = handlers/views_handler_field_boolean.inc
 files[] = handlers/views_handler_field_custom.inc
 files[] = handlers/views_handler_field_date.inc
+files[] = handlers/views_handler_field_entity.inc
 files[] = handlers/views_handler_field_markup.inc
 files[] = handlers/views_handler_field_math.inc
 files[] = handlers/views_handler_field_numeric.inc
