简体   繁体   中英

Database is locked: SQLite exception thrown on my android and ios xamarin app

The database was very stable until I did all the package and bundle signing and deploy the app to the app center for distributed testing, then I started getting all kind of errors from the SQLite database. I did some research and got to know that the database is not threading safe, but how can I make it thread safe, all my database connections and queries are through async.
This is my database connection

    private static object collisionLock = new object();
    //local SQLite database.

    public SQLiteAsyncConnection Db;
    private Uri url;
    private MemberDataStore membersStore;
    private AdvantageMemberDataStore advMembersStore;
    private EventDataStore eventDataStore;



    public ConnectionsUtil()
    {
         Db = DependencyService.Get<IDatabaseConnection>().DbConnection();
    }       

This is the code that does inserts and updates, I have three methods like the one below that access the database and many queries that uses the Db within the app

    public async Task GetAdvantageMembersAsync(AdvantageMemberDataStore store)
    {
        await Db.QueryAsync<AdvantageMember>("DROP TABLE IF EXISTS AdvantageMember").ContinueWith(t =>
        {

            Db.CreateTableAsync<AdvantageMember>();

            Console.WriteLine("AdvantageMember table created!");

        });
        url = new Uri("http://54.39.180.209/benefits");

        Console.WriteLine("Gideon: Attempting to get advantage members.");
        try
        {

            string json;
            //Gideon: get json string containing advantage members.
            using (WebClient sr = new WebClient())
            {

                Console.WriteLine("Gideon: Retrieving advantage Members....");

                sr.DownloadStringCompleted += async (s, e) =>
                {

                    Console.WriteLine("Gideon: Advantage Members Downloaded. Processing advantage Members....");
                    json = e.Result;
                    lock (collisionLock)
                    {
                       Db.InsertAllAsync(JsonConvert.DeserializeObject<IEnumerable<AdvantageMember>>(json)).ContinueWith(async t =>
                        {
                            await store.UpdateItemsAsync(Db.QueryAsync<AdvantageMember>("SELECT * FROM AdvantageMember GROUP BY Title").Result);
                        });
                    }

                        Console.WriteLine("Processing Members benefits for android");
                        advMembersStore = store;      
                };

                await Task.Run(() => sr.DownloadStringAsync(url));

            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Gideon: An error occured while trying to dbect. ERROR: " + e);
        }
    }
 **This is the code that specify the folder for the sqlite connection**

 public class DatabaseConnection_iOS: Services.IDatabaseConnection
{
    public SQLiteAsyncConnection DbConnection()
    {
        var dbName = "MyDb.db3";
        string personalFolder =
          Environment.
          GetFolderPath(Environment.SpecialFolder.Personal);
        string libraryFolder =
          Path.Combine(personalFolder, "..", "Library");
        var path = Path.Combine(libraryFolder, dbName);
        return new SQLiteAsyncConnection(path);
    }
}

In my case, I was put SaveContext inside foreach

            var transaction = _context.Database.BeginTransaction();

            try
            {
                foreach (var item in obj)
                {
                    _context.EntrevistaNacionals.Add(item);
await _context.SaveChangesAsync(); //--wrong 
                }
                
                transaction.Commit();

                return true;
            }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM