Skip to main content

Repositories

Repositories are the data access layer of Tasteful flavors. They provide an abstraction over data storage and retrieval, isolating business logic from database-specific operations. Repositories handle all interactions with databases, external APIs, and other data sources while providing a clean, testable interface for services.

What is a Repository?

A Repository in Tasteful is a class that inherits from BaseRepository or SQLModelRepository and encapsulates data access logic. Repositories are responsible for:
  • Data Access Abstraction: Hiding database-specific implementation details from business logic
  • CRUD Operations: Providing Create, Read, Update, and Delete functionality
  • Query Management: Handling complex queries and data filtering
  • Connection Management: Managing database connections and sessions
  • Data Mapping: Converting between database records and domain objects
  • Transaction Support: Ensuring data consistency through proper transaction handling
Repositories act as the single point of data access for each entity or aggregate, providing a clean interface that services can use without knowing about database specifics.

Core Concepts

Repository Hierarchy

Tasteful provides two base repository classes:

BaseRepository

The foundational repository class that provides basic structure:

SQLModelRepository

The recommended repository class for SQLModel-based applications:

Session Management

SQLModelRepository provides robust session management through context managers:
Key features of session management:
  • Automatic Rollback: Sessions automatically rollback on exceptions
  • Connection Pooling: Efficient database connection management
  • Transaction Safety: Proper transaction boundaries for data consistency

Implementation

Basic Repository Implementation

Here’s a complete example of a repository implementation:

Advanced Query Patterns

Repositories can implement complex queries while maintaining clean interfaces:

Database Initialization

Repositories can handle database table creation:

Integration with Other Components

Service Integration

Repositories are injected into services through dependency injection:

Configuration Integration

Repositories receive configuration through dependency injection:

Flavor Integration

Repositories are registered in flavor containers:

Best Practices

Do’s

  • Single Responsibility: Each repository should handle one entity or aggregate
  • Interface Consistency: Use consistent method naming across repositories (get_by_id, create, update, delete)
  • Session Management: Always use the get_session() context manager for database operations
  • Error Handling: Let database exceptions bubble up to services for proper business logic handling
  • Query Optimization: Use appropriate indexes and query patterns for performance
  • Transaction Boundaries: Keep transactions as short as possible while maintaining consistency

Don’ts

  • Business Logic: Don’t put business rules in repositories - they belong in services
  • Direct Database Access: Don’t bypass the repository pattern by accessing the database directly from services
  • Session Leaks: Don’t store sessions as instance variables - always use context managers
  • Complex Joins: Avoid overly complex queries that are hard to maintain - consider breaking them down
  • Tight Coupling: Don’t make repositories dependent on other repositories directly