Dart Database Integration
In this lesson, you will learn how Dart applications interact with databases. Database integration is essential for storing, retrieving, and managing persistent data in real-world applications.
We will focus on practical workflows such as saving records, querying data, updating values, and handling failures — exactly how databases are used in production systems.
Why Database Integration Is Important
Without a database, application data is lost when the program stops. Databases allow applications to:
- Store user information
- Save transactions and logs
- Retrieve historical data
- Maintain application state
Common Databases Used with Dart
- SQLite (local storage)
- PostgreSQL
- MySQL
- NoSQL databases (MongoDB, Firebase)
Dart interacts with databases using packages and drivers.
Simulating a Database Connection
Before using a real database, let’s simulate a database connection. This helps understand the workflow without external dependencies.
Future connectDatabase() async {
await Future.delayed(Duration(seconds: 1));
return true;
}
void main() async {
bool connected = await connectDatabase();
print(connected ? "Database Connected" : "Connection Failed");
}
This pattern mirrors real connection logic.
Inserting Data into a Database
Inserting records is one of the most common operations. Below is a simulated insert operation.
Future insertUser(String name, int age) async {
await Future.delayed(Duration(seconds: 1));
print("User $name added with age $age");
}
void main() async {
await insertUser("Sophia", 29);
}
In real systems, this would execute an SQL INSERT query.
Reading Data from a Database
Applications often fetch records to display dashboards or reports.
Future> fetchUsers() async {
await Future.delayed(Duration(seconds: 1));
return ["Alice", "Bob", "Charlie"];
}
void main() async {
var users = await fetchUsers();
print("Users: $users");
}
This simulates a SELECT query returning rows.
Updating Records
Updating existing records is required when user data changes.
Future updateUserAge(String name, int newAge) async {
await Future.delayed(Duration(seconds: 1));
print("Updated $name age to $newAge");
}
void main() async {
await updateUserAge("Alice", 32);
}
This represents an SQL UPDATE operation.
Deleting Records
Deleting unused or outdated records keeps databases clean.
Future deleteUser(String name) async {
await Future.delayed(Duration(seconds: 1));
print("Deleted user $name");
}
void main() async {
await deleteUser("Charlie");
}
Handling Database Errors
Database operations can fail due to network issues or invalid queries. Proper error handling is critical.
Future safeInsert() async {
try {
await Future.delayed(Duration(seconds: 1));
throw Exception("Database write error");
} catch (e) {
print("Error occurred: $e");
}
}
void main() async {
await safeInsert();
}
This prevents application crashes and improves reliability.
Batch Operations
Batch operations improve performance by grouping database actions.
Future batchInsert(List users) async {
await Future.delayed(Duration(seconds: 2));
print("Inserted ${users.length} users");
}
void main() async {
await batchInsert(["Tom", "Jerry", "Mia"]);
}
Best Practices for Database Integration
- Use async/await for non-blocking operations
- Validate data before inserting
- Handle errors gracefully
- Close database connections properly
- Use batch operations for performance
📝 Practice Exercises
Exercise 1
Create a function that inserts a list of product prices into a database.
Exercise 2
Simulate fetching transaction history and calculate the total amount.
Exercise 3
Implement error handling for a failed database update.
What’s Next?
In the next lesson, you will explore file operations in Dart, learning how applications read from and write to files efficiently.