-
Notifications
You must be signed in to change notification settings - Fork 226
PostgreSQL
v3 needed
Npgsql.dllinstalled into the GAC and a<DbProviderFactories>entry added tomachine.config, because the reader ran inside the Visual Studio T4 host. v4 needs neither. Theefrpgtool carriesNpgsqlas an ordinary NuGet dependency, so you cangacutil /u Npgsqland delete themachine.configentry. Nothing will break. See Upgrading from v3 to v4.
Settings.DatabaseType = DatabaseType.PostgreSQL;
Settings.TemplateType = TemplateType.EfCore10; // or EfCore9, EfCore8
Settings.GeneratorType = GeneratorType.EfCore;
Settings.ConnectionString = "Server=127.0.0.1;Port=5432;Database=Northwind;User Id=testuser;Password=***;";Your project needs the Npgsql.EntityFrameworkCore.PostgreSQL NuGet package. The generated OnConfiguring
calls optionsBuilder.UseNpgsql(...).
More connection string shapes are on the Connection strings page.
CONNECT on the database and USAGE on the schemas you want to read. information_schema and the catalogue
are readable by default, so a plain read-only role is enough:
CREATE ROLE efrpg_reader LOGIN PASSWORD '***';
GRANT CONNECT ON DATABASE northwind TO efrpg_reader;
GRANT USAGE ON SCHEMA public, sales TO efrpg_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public, sales TO efrpg_reader;| Feature | Supported | Notes |
|---|---|---|
| Tables, views, columns | ✔ | |
| Primary and foreign keys | ✔ | Including composite |
| Indexes | ✔ | |
serial / bigserial
|
✔ | Treated as identity columns, so EF Core emits ValueGeneratedOnAdd() rather than ValueGeneratedNever()
|
GENERATED ... AS IDENTITY |
✔ | |
| Generated columns | ✔ | |
| Column defaults | ✔ | |
| Column comments | ✔ |
COMMENT ON COLUMN is read and emitted as an XML doc comment. See Extended Property Names Feature
|
| Sequences | ✔ | Sequences created implicitly to back a serial or identity column are correctly excluded |
| Triggers | ✔ | |
| Stored procedures and functions | ✔ | Signatures and parameters, so callers are generated |
| Function result models | ✔ | Read from pg_proc, so nothing is executed to discover them. See below |
| Array columns | ✔ | See below |
| Synonyms | n/a | PostgreSQL has none |
| Temporal tables | n/a |
Return models are produced for functions that return a set - RETURNS TABLE(...), RETURNS SETOF ..., or
a record - which the generator treats as table-valued functions. They are read straight out of pg_proc, so
unlike SQL Server nothing is executed to discover the shape and no EXECUTE permission is needed. PostgreSQL
has no equivalent of SET FMTONLY, so reading them any other way would mean running the function for real,
side effects and all.
A PostgreSQL PROCEDURE (CREATE PROCEDURE, called with CALL) returns no result set, so it gets a caller
but no return model. That is PostgreSQL's own semantics, not a gap in the generator.
PostgreSQL folds unquoted identifiers to lower case. CREATE TABLE MyTable really creates mytable.
Tools that quote everything (CREATE TABLE "MyTable") preserve the case, and then you have to quote it
forever afterwards.
This matters in two places:
Filters match the real database name. A filter of RegexIncludeFilter("^MyTable$") will not match
mytable. Use RegexOptions.IgnoreCase:
FilterSettings.TableFilters.Add(new RegexIncludeFilter(
new Regex("^mytable$", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(200))));Class names. Leave Settings.UsePascalCase = true (the default) and order_line_item becomes
OrderLineItem, which is what you want. Set it to false only if you genuinely want C# properties called
order_line_item.
The default schema is public, and every schema your user can see is read in one pass. Class names get the
schema prefixed unless it is the default:
-
public.hellobecomesHello -
sales.hellobecomessales_Hello
The schema is prepended verbatim, keeping whatever case PostgreSQL stores - which after identifier folding is usually lower case. Only the table name is PascalCased.
Restrict what is read with a schema filter:
FilterSettings.SchemaFilters.Add(new RegexIncludeFilter("^public$|^sales$"));Turn the prefixing off with Settings.PrependSchemaName = false.
PostgreSQL array columns come through as real C# arrays:
| Column type | Generated property |
|---|---|
integer[] |
int[] |
text[] |
string[] |
numeric[] |
decimal[] |
uuid[] |
Guid[] |
timestamptz[] |
DateTime[] |
bytea[] |
byte[][] |
information_schema collapses every array to the single type name ARRAY, which is useless, so the reader
digs the element type out of the catalogue and reports it PostgreSQL's own way (int4[], bpchar[],
timestamptz[]). If an element type cannot be resolved at all, the column falls back to string[].
| PostgreSQL | C# |
|---|---|
uuid |
Guid |
json, jsonb
|
string - see JSON column support to map it to a real type instead |
interval |
TimeSpan |
timestamp, timestamptz
|
DateTime |
time with time zone |
DateTimeOffset |
hstore |
Dictionary<string, string> |
citext |
string |
inet, cidr
|
NpgsqlInet |
macaddr |
PhysicalAddress |
geometry |
PostgisGeometry |
bit, varbit
|
BitArray |
money, numeric
|
decimal |
The Npgsql-specific types need the relevant namespace adding:
Settings.AdditionalNamespaces = new List<string> { "NpgsqlTypes", "System.Net.NetworkInformation", "System.Collections" };- Settings A-Z - every setting, with a page each
- Common Settings Types Explained
- Settings Callbacks
- Settings runtime values and helpers
- Filtering
- Full Control Over the Generated Code
- Enum Generation from Table Data
- Owned Entities
- JSON column support
- Global Query Filters
- Extended Property Names Feature
- Partial Properties
- File-Scoped Namespaces
- Data Annotations
- Spatial Types
- HierarchyId
- RowVersion and TimeStamp columns
- Lazy Loading
- Stored proc result sets
- Custom File-Based Templates
- Extra entities via partial classes
- INotifyPropertyChanged
- Syntax colour for T4