Search code examples
c#xamarin.iosazure-mobile-services

Microsoft.Datasync.Client DatasyncClient with options.Offlinestore set throws Unable to configure sqlite3 for URI connection strings


I'm trying to implement a basic sync service for a xamarin.ios app.

Following this example: https://learn.microsoft.com/en-us/azure/developer/mobile-apps/azure-mobile-apps/quickstarts/xamarin-ios/offline?pivots=vs2022-windows

Code Block:

var connectionString = new UriBuilder { Scheme = "file", Path = "file://localhost/var/mobile/Containers/Data/Application/B707F702-7368-484C-B6F9-09C86F86E072/Documents/dev.db3?mode=rwc", Query = "?mode=rwc" }.Uri.ToString();

var store = new OfflineSQLiteStore(connectionString);
store.DefineTable<AppUser>();

var options = new DatasyncClientOptions
{
    OfflineStore = store
};

var client = new DatasyncClient(AppSettings.DownstreamApi.BaseAddress, options);

Throws:

{
  "SqliteMessage": null,
  "Message": "Unable to configure sqlite3 for URI connection strings.",
  "Data": {},
  "InnerException": null,
  "StackTrace": "  at Microsoft.Datasync.Client.SQLiteStore.Driver.SqliteConnection..ctor (System.String connectionString) [0x00026] in <91fe6adffeec4df489b907fb5ce22b43>:0 \n  at Microsoft.Datasync.Client.SQLiteStore.OfflineSQLiteStore..ctor (System.String connectionString) [0x00044] in <91fe6adffeec4df489b907fb5ce22b43>:0 \n  at TRKIOSAPP.AuthenticationViewController..ctor (System.IntPtr handle) [0x00430] in D:\\Source\\repos\\atlas\\ios\\TRKIOSAPP\\ViewControllers\\AppViews\\AuthenticationViewController.cs:160 ",
  "HelpLink": null,
  "Source": "Microsoft.Datasync.Client.SQLiteStore",
  "HResult": -2146233088
}

I've tried many variations in the connection string: file:///var/mobile/... and so forth.

Doing some research to try and figure out what the error message means exactly:https://github.com/Azure/azure-mobile-apps/blob/64ebfd230a0a17b9c938cf86058ec6963261c96d/sdk/dotnet/src/Microsoft.Datasync.Client.SQLiteStore/Driver/SqliteConnection.cs

public SqliteConnection(string connectionString)
{
    if (!sqliteIsInitialized)
    {
        Batteries_V2.Init();

        // You only need to configure the sqlite3 interface once.
        if (raw.sqlite3_config(raw.SQLITE_CONFIG_URI, 1) != raw.SQLITE_OK)
        {
            throw new SQLiteException("Unable to configure sqlite3 for URI connection strings.");
        }

        sqliteIsInitialized = true;
    }

    int rc = raw.sqlite3_open(connectionString, out connection);
    if (rc != raw.SQLITE_OK)
    {
        throw new SQLiteException("Unable to open database connection to '{connectionString}'", rc, connection);
    }

    int limit = raw.sqlite3_limit(connection, raw.SQLITE_LIMIT_VARIABLE_NUMBER, -1);
    MaxParametersPerQuery = limit - 16;
}

Why does it keep throwing this error when using the OfflineStore in options? I'm at a loss on this one and will have to find a new approach soon.


Solution

  • The error is basically a throw because the underlying SQLite database threw an error.

    I suspect it is because your UriBuilder statement is wrong - you need to include just the path in the Path element - no "file://" and no query on it. Right now, the UriBuilder will build an invalid URI following the string. If you print the connectionString, you will likely see the issue.