DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Live Database Migration
  • How Doris Connects to Multiple Databases for Federated Analytics and Data Migration
  • Oracle: Migrate PDB to Another Database
  • Seamless Transition: Strategies for Migrating From MySQL to SQL Server With Minimal Downtime

Trending

  • AI's Dilemma: When to Retrain and When to Unlearn?
  • How To Replicate Oracle Data to BigQuery With Google Cloud Datastream
  • Why We Still Struggle With Manual Test Execution in 2025
  • Scalable System Design: Core Concepts for Building Reliable Software
  1. DZone
  2. Data Engineering
  3. Databases
  4. Automatic Versioning in Mobile Apps

Automatic Versioning in Mobile Apps

TL;DR: This article presents an automatic versioning and migration framework for mobile app databases using schema hashes and seamless upgrades.

By 
Liewen Huang, Ph.D. user avatar
Liewen Huang, Ph.D.
·
Mar. 27, 25 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
2.2K Views

Join the DZone community and get the full member experience.

Join For Free

Picture this: Your mobile app is evolving quickly, with new features requiring changes to the local database. Your users expect seamless upgrades, and your stakeholders want new functionality delivered fast. The challenge becomes even trickier when you realize you need to update the app's database schema without disrupting existing data or forcing users into error-prone migrations.

In this article, I’ll share a practical, automatic versioning approach I developed that simplifies database versioning and migration for mobile apps. This system lets developers focus on data models instead of manually scripting version changes, while making sure users’ data stays intact across updates.

The Challenge

Traditionally, handling local database changes in mobile apps means:

  • Keeping track of schema versions
  • Writing manual scripts to modify tables
  • Handling special cases where users jump over versions (e.g., upgrade from v1 straight to v4)
  • Debugging mismatches between app versions and database versions

It’s error-prone, time-consuming, and a pain to test. There had to be a better way, so I built one.

Automatic Versioning Approach

1. Model Classes as the Source of Truth

Instead of manually tracking versions, the data models themselves drive everything. Any changes developers make to the model classes automatically trigger schema updates. This way, developers only need to think about the data they need, not how to evolve the schema.

C#
 
public class TB
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }

    // ...
}


The schema for the database comes directly from these models — no manual scripts required.

2. Automatic Script Generation

A helper class generates the SQL script based on the model classes. Converting model classes into SQL scripts is a well-known practice and is not included in this article. Instead, this article focuses on what happens after the script is generated — specifically, that script is hashed to create a unique version identifier for the schema.

C#
 
public class DatabaseHelper
{
    public string GenerateDatabaseScript()
    {
        // Logic to generate the database script based on model classes
    }

    public string GetDatabaseName(string databaseScriptHashcode)
    {
        // Logic to generate the database name based on the hash code of the database script
        return $“{GetDatabaseNamePrefix()}_v{databaseScriptHashcode}.db”;
    }

    public string GetDatabaseNamePrefix()
    {
        // Logic to generate the optional database name’s prefix
    }

    // ...

}


Every schema change automatically results in a new hash, so versioning is tied directly to the schema itself, not some manually maintained version number.

3. Dynamic Database Initialization

At app launch, the system:

  • Generates the current schema script.
  • Computes the hash code for that script.
  • Checks if a local database file with the matching hash code already exists.
  • If no match is found, a new database is created using the current schema.
C#
 
public class DatabaseInitializer
{
    private readonly DatabaseHelper databaseHelper;

    public void InitializeDatabase()
    {
        string databaseScript = databaseHelper.GenerateDatabaseScript();
        string databaseName = databaseHelper.GetDatabaseName(GetHashCode(databaseScript));
        // Check if the database file with the current schema’s hash code exists
        if (!DoesMatchingDatabaseExist(databaseName))
        {
            // No matching database found, create a new database
            CreateDatabase(databaseScript);
        }
    }

    private bool DoesMatchingDatabaseExist()
    {
        // Logic to check if the database file with the specified name exists 
    }

    private void CreateDatabase(string databbaseScript)
    {
        // Logic to create a new database based on the database script
    }

    public string GetHashCode(string databbaseScript)
    {
        // Logic to create hash code
    }

    // ...

}


This ensures every schema change results in a clean, correctly versioned database.

4. Generating a Fixed-Length Hash Code

One small challenge is that .NET’s built-in GetHashCode() can generate:

  • Different hashes on different platforms.
  • Hashes of varying lengths, which are awkward for file names.

To make things predictable, one may use a simple function like the one below that produces a 6-digit numeric hash. This keeps the file name consistent and easy to read.

C#
 
static int GetHashCode(string s)
    {
        int hashValue = 0;

        foreach (char c in s)
        {
            hashValue = (hashValue * 31 + c) % 1000000;
        }

        return hashValue;
    }


This gives you:

  • A short, human-friendly hash.
  • Predictable behavior across devices.
  • Enough uniqueness to handle schema changes.

Data Migration Made Simple

1. Unified Initialization and Migration

This system doesn’t just create new databases — it also handles migrating data from the previous schema version if needed.

  • When a new schema is detected (i.e., hash has changed), a new database is created.
  • The system looks for the previous database (by its hash).
  • If found, data is migrated automatically.
C#
 
public class DatabaseInitializer
{
    private readonly DatabaseHelper databaseHelper;
    private readonly DatabaseMigrationHelper migrationHelper;

    public void InitializeDatabase()
    {
        string currentSchemaScript = databaseHelper.GenerateDatabaseScript();
        string currentSchemaHashCode = GetHashCode(currentSchemaScript);

        // Check if the database file with the current schema's hash code exists
        if (!DoesMatchingDatabaseExist(currentSchemaHashCode))
        {
            // No matching database found, create a new database
            CreateDatabase(currentSchemaScript);

            // Check if the database file with the previous schema's hash code exists
            string previousSchemaHashCode = RetrievePreviousSchemaHashCode();
            if (!string.IsNullOrEmpty(previousSchemaHashCode) && DoesMatchingDatabaseExist(previousSchemaHashCode))
            {
                // Matching database found
                if (previousSchemaHashCode != currentSchemaHashCode)
                {
                    // Previous schema is different, perform data migration
                    migrationHelper.PerformDataMigration(previousSchemaHashCode, currentSchemaHashCode);
                }

                // Store the hash code of the current schema for future reference
                StoreCurrentSchemaHashCode(currentSchemaHashCode);
            }
        }
    }

    // ...
}


This migration logic only runs if the schema actually changed, saving unnecessary processing.

2. Data Migration Helper

The migration itself is handled by a dedicated class. It copies data table-by-table from the old database to the new one. If any errors occur, they can be logged, and appropriate logic can be applied to handle the migration process gracefully.

C#
 
public class DatabaseMigrationHelper
{
    public void PerformDataMigration(string previousDatabaseName, string currentDatabaseName)
    {
        try
        {
            CopyData(previousDatabaseName, currentDatabaseName);
        }
        catch (Exception ex)
        {
            // Handle any potential errors during data migration
        }
    }

    // ...
}


Conclusion

This model-driven approach makes database versioning and migration practically invisible to developers. They focus on models, not migration scripts.

  • Schema changes automatically trigger new database versions.
  • Data is preserved when possible.
  • No manual version tracking is needed.

For teams working on rapidly evolving mobile apps, this kind of system removes one of the biggest headaches: schema management. It’s also future-proof — the same approach could work for desktop apps, embedded apps, or even local-first web apps.

This solution has saved my team and me countless hours of manual schema tracking and migration work, and I believe it could help others in the same boat.

Data migration Database mobile app Schema

Opinions expressed by DZone contributors are their own.

Related

  • Live Database Migration
  • How Doris Connects to Multiple Databases for Federated Analytics and Data Migration
  • Oracle: Migrate PDB to Another Database
  • Seamless Transition: Strategies for Migrating From MySQL to SQL Server With Minimal Downtime

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!