diff --git a/data_entity/data_entity.entity.inc b/data_entity/data_entity.entity.inc
index 5a58199..49461aa 100644
--- a/data_entity/data_entity.entity.inc
+++ b/data_entity/data_entity.entity.inc
@@ -31,4 +31,27 @@ class DataEntityController extends EntityAPIController implements EntityAPIContr
 
     return $entities;
   }
+
+  public function save ($entity) {
+    $record = array();
+    $table_name = $this->dataTable;
+    $schema = drupal_get_schema($table_name);
+
+    // Get all fields in the table
+    foreach ($schema['fields'] as $field_name => $field_info) {
+      // Only use fields which are being saved
+      if (isset($entity->{$field_name})) {
+        $record[$field_name] = $entity->{$field_name};
+      }
+    }
+
+    // Save the row
+    if ($handler = DataHandler::instance($table_name)) {
+      return $handler->save($record);
+    }
+    else {
+      return FALSE;
+    }
+
+  }
 }
diff --git a/data_entity/data_entity.module b/data_entity/data_entity.module
index 755da61..1e9e11f 100644
--- a/data_entity/data_entity.module
+++ b/data_entity/data_entity.module
@@ -223,3 +223,77 @@ function data_entity_views_api() {
   );
 }
 
+/**
+ * Implements hook_entity_property_info().
+ *
+ * Allow modules to define metadata about entity properties.
+ */
+function data_entity_entity_property_info() {
+  $tables = data_entity_get_entity_tables();
+  foreach ($tables as $table) {
+    foreach ($table->table_schema['fields'] as $field_name => $field) {
+      $info['data_' . $table->name]['properties'][$field_name] = array(
+        'label' => !empty($table->meta['fields'][$field_name]['label']) ? $table->meta['fields'][$field_name]['label'] : $field_name,
+        'getter callback' => 'entity_metadata_field_verbatim_get',
+        'setter callback' => 'entity_metadata_field_verbatim_set',
+        'field' => TRUE,
+      );
+    }
+  }
+  return $info;
+}
+
+/**
+ * Implements hook_feeds_processor_targets_alter().
+ *
+ * Alter mapping targets for entities. Use this hook to add additional target
+ * options to the mapping form of Node processors.
+ */
+function data_entity_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+  if (substr($entity_type, 0, 5) == 'data_') {
+    $table_name = substr($entity_type, 5);
+    $tables = data_entity_get_entity_tables();
+    if (isset($tables[$table_name])) {
+      $table = $tables[$table_name];
+      foreach ($table->table_schema['fields'] as $field_name => $field) {
+        $targets[$field_name] = array(
+          'name' => !empty($table->meta['fields'][$field_name]['label']) ? $table->meta['fields'][$field_name]['label'] : $field_name,
+          'description' => 'Field of type ' . $field['type'] . '.',
+          'callback' => 'data_entity_set_target',
+          'optional_unique' => TRUE,
+        );
+      }
+    }
+  }
+}
+
+/**
+ * Callback specified in data_entity_feeds_processor_targets_alter().
+ */
+function data_entity_set_target($source, $entity, $target, $value) {
+  $entity->{$target} = $value;
+  return $entity;
+}
+
+/**
+ * Invoked before a feed item is saved.
+ *
+ * @param $source
+ *  FeedsSource object that describes the source that is being imported.
+ * @param $entity
+ *   The entity object.
+ * @param $item
+ *   The parser result for this entity.
+ */
+function data_entity_feeds_presave(FeedsSource $source, $entity, $item) {
+  if (substr($entity->feeds_item->entity_type, 0, 5) == 'data_') {
+    // Add a timestamp source field
+    $item['feeds_item_imported'] = $source->state['start_time'];
+    // Set target field values
+    foreach ($source->importer->config['processor']['config']['mappings'] as $mapping) {
+      $source = $mapping['source'];
+      $target = $mapping['target'];
+      $entity->$target = $item[$source];
+    }
+  }
+}
