Database schema synchronization tool for Noundry.Tuxedo. Define your database schema directly in POCO model classes with attributes, and Bowtie automatically keeps your database in perfect sync.
Model-first database tool designed for .NET developers who want to define their schema in code and automatically synchronize with any RDBMS.
Automatically synchronize database schema with POCO model classes using attributes to define tables, indexes, and constraints.
Automatically synchronize database schema across all environments based on your POCO model definitions with attribute-driven configuration.
Use .NET attributes on your model classes to define tables, indexes, constraints, and relationships - all in your familiar C# code.
Install Bowtie and start defining your database schema directly in your POCO model classes.
using Noundry.Tuxedo.Bowtie.Attributes;
using System.ComponentModel.DataAnnotations;
// Define your database schema in the model
[Table("Products")]
public class Product
{
[Key]
public int Id { get; set; }
[Column(MaxLength = 100)]
[Index("IX_Products_Name")]
public string Name { get; set; }
[CheckConstraint("Price > 0")]
public decimal Price { get; set; }
[ForeignKey("Categories", "Id")]
public int CategoryId { get; set; }
[Column(TypeName = "datetime2")]
[DefaultValue("GETUTCDATE()")]
public DateTime CreatedAt { get; set; }
}
// Bowtie automatically creates this table structure:
// - Products table with all columns
// - IX_Products_Name index
// - Price > 0 check constraint
// - Foreign key to Categories table
Define your complete database schema using attributes on your model classes. Bowtie handles the rest.
Use standard .NET attributes to define table names, column properties, and data types.
Specify custom table name
Mark property as primary key
Set column length and properties
Make column NOT NULL
[Table("Users")]
public class User
{
[Key]
public int Id { get; set; }
[Required]
[Column(MaxLength = 100)]
public string Name { get; set; }
[Required]
[Column(MaxLength = 255)]
public string Email { get; set; }
[Column(TypeName = "decimal(10,2)")]
public decimal? Balance { get; set; }
[Column(TypeName = "datetime2")]
[DefaultValue("GETUTCDATE()")]
public DateTime CreatedAt { get; set; }
}
// Bowtie automatically creates:
// CREATE TABLE Users (
// Id int IDENTITY(1,1) PRIMARY KEY,
// Name nvarchar(100) NOT NULL,
// Email nvarchar(255) NOT NULL,
// Balance decimal(10,2) NULL,
// CreatedAt datetime2 DEFAULT GETUTCDATE()
//)
Define indexes directly on model properties for optimal query performance across different database providers.
Create single-column index
Create unique index
Specify index type (B-Tree, Hash, GIN)
[Table("Products")]
public class Product
{
[Key]
public int Id { get; set; }
// Single column index for fast lookups
[Index("IX_Products_Name")]
[Column(MaxLength = 100)]
public string Name { get; set; }
// Unique index for email addresses
[Index("IX_Products_SKU", Unique = true)]
[Column(MaxLength = 50)]
public string SKU { get; set; }
// Composite index for category + active filtering
[Index("IX_Products_Category_Active", Order = 1)]
public int CategoryId { get; set; }
[Index("IX_Products_Category_Active", Order = 2)]
public bool IsActive { get; set; }
// Hash index for PostgreSQL (fast equality lookups)
[Index("IX_Products_Hash", Type = IndexType.Hash)]
public Guid ProductCode { get; set; }
}
Define check constraints, unique constraints, and default values directly in your model classes.
Add database check constraints
Set column default values
Create unique constraints
[Table("Orders")]
public class Order
{
[Key]
public int Id { get; set; }
// Unique order number constraint
[UniqueConstraint("UQ_Orders_OrderNumber")]
[Column(MaxLength = 50)]
public string OrderNumber { get; set; }
// Check constraint for positive total
[CheckConstraint("Total > 0")]
[Column(TypeName = "decimal(10,2)")]
public decimal Total { get; set; }
// Default value for status
[DefaultValue("'Pending'")]
[Column(MaxLength = 20)]
public string Status { get; set; }
// Date range constraint
[CheckConstraint("OrderDate >= '2024-01-01'")]
[DefaultValue("GETUTCDATE()")]
public DateTime OrderDate { get; set; }
// Multiple constraints on single property
[CheckConstraint("Quantity > 0 AND Quantity <= 1000")]
[DefaultValue("1")]
public int Quantity { get; set; }
}
Define foreign key relationships and referential integrity directly in your model classes.
Define foreign key relationship
Cascading delete behavior
Update behavior configuration
// Parent table
[Table("Categories")]
public class Category
{
[Key]
public int Id { get; set; }
[Required]
[Column(MaxLength = 100)]
public string Name { get; set; }
}
// Child table with foreign key
[Table("Products")]
public class Product
{
[Key]
public int Id { get; set; }
[Column(MaxLength = 100)]
public string Name { get; set; }
// Foreign key with cascade delete
[ForeignKey("Categories", "Id", OnDelete = Rule.Cascade)]
public int CategoryId { get; set; }
}
// Bowtie creates:
// ALTER TABLE Products ADD CONSTRAINT FK_Products_Categories
// FOREIGN KEY (CategoryId) REFERENCES Categories(Id)
// ON DELETE CASCADE
Bowtie analyzes your POCO models and automatically synchronizes your database schema to match.
Bowtie scans your POCO classes and analyzes all attributes to understand the desired database schema.
Compares the current database schema with the desired schema defined in your models.
Generates and executes the necessary SQL commands to bring the database schema into sync with your models.
// When you run SynchronizeDatabaseAsync(), Bowtie:
🔍 Analyzing POCO models...
• Found Product model with [Table("Products")]
• Found Category model with [Table("Categories")]
• Found Index attributes: IX_Products_Name, IX_Products_SKU
• Found ForeignKey: Products.CategoryId → Categories.Id
📊 Comparing with database schema...
• Products table: missing IX_Products_SKU index
• Categories table: exists and matches
• Foreign key constraint: missing
🔧 Generating synchronization commands...
• CREATE INDEX IX_Products_SKU ON Products(SKU)
• ALTER TABLE Products ADD CONSTRAINT FK_Products_Categories...
✅ Database schema synchronized successfully!
• 2 indexes created
• 1 foreign key constraint added
• 0 tables modified
See complete POCO models with Bowtie attributes for common application scenarios.
Full e-commerce schema with products, categories, orders, and customers defined entirely through POCO model attributes.
[Table("Products")]
public class Product
{
[Key]
public int Id { get; set; }
[Required]
[Column(MaxLength = 200)]
[Index("IX_Products_Name")]
public string Name { get; set; }
[UniqueConstraint("UQ_Products_SKU")]
[Column(MaxLength = 50)]
public string SKU { get; set; }
[CheckConstraint("Price > 0")]
[Column(TypeName = "decimal(10,2)")]
public decimal Price { get; set; }
[ForeignKey("Categories", "Id")]
[Index("IX_Products_Category_Active", Order = 1)]
public int CategoryId { get; set; }
[DefaultValue("1")]
[Index("IX_Products_Category_Active", Order = 2)]
public bool IsActive { get; set; }
[DefaultValue("0")]
[CheckConstraint("StockQuantity >= 0")]
public int StockQuantity { get; set; }
// Audit trail
[DefaultValue("GETUTCDATE()")]
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
}
Configure Bowtie for different environments and deployment scenarios.
// Program.cs - Advanced Bowtie configuration
builder.Services.AddNoundryTuxedoBowtie(options =>
{
// Assembly containing your POCO models
options.ModelAssembly = typeof(Product).Assembly;
// Database provider and connection
options.Provider = DatabaseProvider.SqlServer;
options.ConnectionString = connectionString;
// Synchronization behavior
options.AutoCreateTables = true;
options.AutoCreateIndexes = true;
options.AutoCreateConstraints = true;
// Safety settings
options.AllowDropColumns = app.Environment.IsDevelopment();
options.AllowDropTables = false; // Never drop tables
// Dry run mode (generate SQL without execution)
options.DryRun = false;
options.LogGeneratedSQL = true;
});
// Manual synchronization
var syncService = app.Services.GetRequiredService<IBowtieService>();
// Check what changes would be made
var changes = await syncService.GetPendingChangesAsync();
if (changes.Any())
{
// Apply changes
await syncService.SynchronizeSchemaAsync();
}
Use Bowtie CLI tools for build processes, CI/CD integration, and production deployments.
Synchronize database schema with POCO models
Validate model definitions and check for issues
Generate SQL scripts without executing
Check current database schema status
# GitHub Actions - Schema Sync
name: Deploy with Schema Sync
jobs:
deploy:
steps:
- name: Validate Schema
run: bowtie validate --connection "${{ secrets.DB_CONNECTION }}"
- name: Generate Schema SQL
run: bowtie generate-sql --output schema-changes.sql
- name: Review Changes
run: cat schema-changes.sql
- name: Apply Schema Changes
run: bowtie sync --connection "${{ secrets.DB_CONNECTION }}" --confirm
# Azure DevOps Pipeline
- task: DotNetCoreCLI@2
displayName: 'Sync Database Schema'
inputs:
command: 'custom'
custom: 'bowtie'
arguments: 'sync --connection "$(ConnectionString)" --validate-first'
Same POCO models work across SQL Server, PostgreSQL, MySQL, and SQLite with database-specific optimizations.
Native SQL Server types, indexes, and constraints
GIN indexes, JSONB columns, and PostgreSQL-specific features
MySQL engine optimization and charset handling
Lightweight file-based database perfect for testing and development
// This single model definition works across all supported databases:
[Table("Products")]
public class Product
{
[Key]
public int Id { get; set; }
[Index("IX_Products_Search", Type = IndexType.GIN)] // PostgreSQL: GIN index
[Index("IX_Products_Search", Type = IndexType.FullText)] // SQL Server: Full-text
[Column(MaxLength = 100)]
public string Name { get; set; }
}
// SQL Server generates:
// CREATE FULLTEXT INDEX IX_Products_Search ON Products(Name)
// PostgreSQL generates:
// CREATE INDEX IX_Products_Search ON Products USING GIN(to_tsvector('english', Name))
// MySQL generates:
// CREATE FULLTEXT INDEX IX_Products_Search ON Products(Name)
// SQLite generates:
// CREATE INDEX IX_Products_Search ON Products(Name)
Start using Noundry.Tuxedo.Bowtie today and define your database schema directly in your POCO model classes with automatic synchronization.