---
id: database--database-reader
title: "Table reader"
summary: "Selects the rows of one database table (or view) and emits them as typed records, one record per row. The row type is generated from the table definition. A `DbShapeRequest` input adds projection, filtering, sorting and paging. Use it to read reference data or to serve table data to an API."
audience: user
keywords: "input, output, nodata, continue, connectionstring, typeprefix, tablename, commandtimeout, keeporiginalnames, batchmode"
---
# Table reader

Selects the rows of one database table (or view) and emits them as typed records, one record per row. The row type is generated from the table definition. A `DbShapeRequest` input adds projection, filtering, sorting and paging. Use it to read reference data or to serve table data to an API.

## Pins

| Pin | Kind | Types | Description |
|---|---|---|---|
| Input | input | `Viaducta.Database.Types.Shaping.DbShapeRequest`, `Viaducta.TypeSystem.Metadata.AnyData`, `Viaducta.TypeSystem.Metadata.NoInputData` | Triggers the read. Any record works as a trigger; a `DbShapeRequest` shapes the select. |
| Output | output | generated `<flow namespace>.<TypePrefix><Table>Table` | Called once per selected row. |
| NoData | no-data output | same as input | Called with the input record when the select returns no rows. |
| Continue | continue output | same as input | Called with the input record after all rows (and after `NoData`). |

## Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `ConnectionString` | database link name | | Required. Name of a repository database link (link selector). Looked up by exact name; a raw connection string or `#name` prefix is not resolved. |
| `TypePrefix` | string | `Db` | Prefix of the generated type name. Triggers reconfigure. |
| `TableName` | string (database explorer) | | Required. `table` or `schema.table`; without a schema the link's default schema is used. Triggers reconfigure. |
| `CommandTimeOut` | integer (seconds) | `20` | Command timeout. |
| `KeepOriginalNames` | boolean | `false` | `true` keeps column names as property names; `false` converts them to C# names. Triggers reconfigure. |
| `BatchMode` | dropdown: `1` Auto, `2` Always, `3` Never | `1` | Whether the rows of one read form a batch for batch consumers. `Auto`: only if the input record is not already in a batch (Timer); a read per record of a batch keeps that batch. `Always`: a child batch per read. `Never`: no batch. |

## Behaviour

- Reconfigure (changing `TableName`, `TypePrefix` or `KeepOriginalNames`) reads the current table definition (never cached, so re-selecting the table picks up schema changes) and generates a locked type named `TypePrefix` + table name + `Table` (suffix omitted if the name already ends with `Table`; the table part converted to a C# name unless `KeepOriginalNames`). Properties are omitted from JSON when null/default. The type replaces the component's previous types and becomes the only type of `Output`. A component with its default name is renamed to `TRD_<TableName>`.
- Renaming the type (prefix, names) changes the type on `Output`: check the connections behind it.
- Each input runs `SELECT` of all columns of the table. With a `DbShapeRequest` input the select uses its `Projections` (selected columns; `*` or none means all), `Filter` (where tree), `Sort`, `Skip` and `Take` (negative `Skip`/`Take` is an error). Columns not selected stay at their default value on the record.
- The rows of one read form a batch (`BatchMode`, opened on the first row): it ends after the last row was processed downstream and before `NoData`/`Continue`, so batch consumers (*Build array*, *Bulk insert*, *Write file*) commit then; an error fails it.
- Without connections on `Output` the table is not read, only `Continue` is called (the component still starts).
- The status shows `Done (N rows).` after each read.

## Notes

- The component does not poll or mark rows. Every trigger reads the whole table unless a `DbShapeRequest` filters it.
- The row type is taken from the first `Output` connection at start; its properties must still match the table columns (start fails otherwise: re-select the table).
- Large tables are streamed row by row, but all downstream components run per row: filter with a shape request or use *Sql query* for selective reads.

## Example

```json
{ "ConnectionString": "MainDb", "TableName": "dbo.Customers", "TypePrefix": "Db", "CommandTimeOut": 30 }
```

Timer → **Table reader** → (Output) Data mapper → Http client; (Continue) Log
