SQL view generation framework for creating database views from C# entity attributes.
- Attribute-based view definition
- Automatic view SQL generation
- Join and filter support
- Materialized view support (PostgreSQL)
- Cross-database compatibility (SQL Server, PostgreSQL, MySQL, SQLite)
dotnet add package Birko.Data.SQL.View- Birko.Data.Core (AbstractModel)
- Birko.Data.Stores (store interfaces)
- Birko.Data.SQL
using Birko.Data.SQL.View.Attributes;
[View("customer_orders_view")]
[ViewJoin("Orders", "Id", "CustomerId")]
public class CustomerOrderView
{
[ViewColumn("customer_id", "Id")]
public Guid CustomerId { get; set; }
[ViewColumn("customer_name", "Name")]
public string CustomerName { get; set; }
[ViewColumn("order_count")]
public int OrderCount { get; set; }
}var generator = new ViewGenerator<CustomerOrderView>();
var sql = generator.GenerateCreateView(connection);[View("active_users_view")]
[ViewFilter("IsActive = true")]
[ViewFilter("DeletedAt IS NULL")]
public class ActiveUsersView { /* ... */ }[View("user_stats", Materialized = true, RefreshInterval = "1 hour")]
public class UserStatsView { /* ... */ }- ViewAttribute - Marks entity for view generation (name, materialized, refresh)
- ViewColumnAttribute - Defines view column mapping
- ViewJoinAttribute - Defines table joins
- ViewFilterAttribute - Defines WHERE filters
- ViewGenerator<T> - Generates CREATE VIEW SQL
- ViewBuilder - View query builder
- ViewDefinition - View metadata
The framework supports multiple query modes via the ViewQueryMode enum:
| Mode | Description |
|---|---|
OnTheFly |
Generates a SELECT statement at query time without creating a database view object. Default mode. |
Persistent |
Queries an existing database VIEW object (must be created first via DDL methods). |
Auto |
Uses the persistent view if it exists, otherwise falls back to on-the-fly generation. |
// Query a persistent view directly
var results = connector.SelectView<CustomerOrderView>(ViewQueryMode.Persistent);
// Auto mode: uses persistent view if available, on-the-fly otherwise
var results = connector.SelectView<CustomerOrderView>(ViewQueryMode.Auto);The MaterializedViewType enum identifies the materialization strategy across providers:
| Type | Provider | Description |
|---|---|---|
None |
All | Standard (non-materialized) view |
Materialized |
PostgreSQL | PostgreSQL MATERIALIZED VIEW with explicit refresh |
Indexed |
SQL Server | Indexed view with SCHEMABINDING and clustered index |
In addition to on-the-fly SELECT generation, the framework supports creating and managing actual database VIEW objects.
// Sync
connector.CreateView(typeof(CustomerOrderView));
connector.CreateViewIfNotExists(typeof(CustomerOrderView));
connector.DropView("customer_orders_view");
connector.RecreateView(typeof(CustomerOrderView));
// Async
await connector.CreateViewAsync(typeof(CustomerOrderView));
await connector.CreateViewIfNotExistsAsync(typeof(CustomerOrderView));
await connector.DropViewAsync("customer_orders_view");
await connector.RecreateViewAsync(typeof(CustomerOrderView));bool exists = connector.ViewExists("customer_orders_view");
bool exists = await connector.ViewExistsAsync("customer_orders_view");connector.CreateViews(new[] { typeof(View1), typeof(View2) });
connector.DropViews(new[] { "view1", "view2" });Each SQL provider has a separate view project with DDL overrides:
| Provider | CREATE syntax | ViewExists catalog |
|---|---|---|
| MSSql | CREATE OR ALTER VIEW |
sys.views |
| PostgreSQL | CREATE OR REPLACE VIEW |
information_schema.views |
| MySQL | CREATE OR REPLACE VIEW |
information_schema.VIEWS |
| SQLite | CREATE VIEW IF NOT EXISTS |
sqlite_master |
PostgreSQL also supports materialized views via CreateMaterializedView, RefreshMaterializedView, and DropMaterializedView.
- Birko.Data.SQL - SQL base classes
- Birko.Data.SQL.MSSql.View - SQL Server view DDL
- Birko.Data.SQL.PostgreSQL.View - PostgreSQL view DDL
- Birko.Data.SQL.MySQL.View - MySQL view DDL
- Birko.Data.SQL.SqLite.View - SQLite view DDL
Part of the Birko Framework.