简体   繁体   中英

SQLite throws busy exception and locked

I have a android app created with xamarin . This is the code that crashes, not the first time, but often on the second time!

        public void InsertOrUpdateInventoryWithoutEntries(Inventory inventory)
        {
        _logger.Debug("Enter");
        try
        {
            var db = _dataBaseConnection.GetSqLiteConnection();
            using (db)
            {
                var existingDbInventory = db.Find<DbInventory>(dbInventory => dbInventory.Code == 
                 inventory.Code);
                if (existingDbInventory != null)
                {
                    if (!existingDbInventory.Finished ) // do not update if finished.
                    {
                        existingDbInventory.Description = inventory.Description;

                        existingDbInventory.OpenTime = inventory.OpenTime;
                        existingDbInventory.Finished = inventory.Finished ;
                        existingDbInventory.UseInventoryList = inventory.UseInventoryList;
                        existingDbInventory.PostedToServer = inventory.PostedToServer;
                        existingDbInventory.InventoryListIsDownloaded = 
                                                      inventory.InventoryListIsDownloaded;
                        UpdateInventory(existingDbInventory,db);

                    }
                }
                else
                {
                    db.Insert(DbInventory.FromInventory(inventory));
                }
                db.Close();
            }
        }
        catch
        (SQLiteException ex)
        {
            _logger.Error(ex);
            throw;
        }
    }

        private void UpdateInventory(DbInventory inventory, SQLiteConnection db)
    {
        _logger.Debug("Enter");
        try
        {
           var result = db.Update(inventory);

        }
        catch (SQLiteException ex)
        {
            _logger.Error(ex);
            throw;
        }
    }
        public bool InsertOrUpdateInventoryEntry(InventoryEntry inventoryEntryModel, 
        SQLiteConnection db=null)
    {
        _logger.Debug("Enter");
        bool disposeFlg = false;

        //detta då sqllite inte klarar av samtidiga anrop så bra, så man skall bara använda en 
         connection i taget !
        if (db == null)
        {
            db = _dataBaseConnection.GetSqLiteConnection();
            disposeFlg = true;
        }

        var existingDbInvetoryRow = db.Find<DbInventoryEntry>(dbInventoryRow => 
             dbInventoryRow.ItemId == inventoryEntryModel.ItemId && dbInventoryRow.InventoryCode == 

            inventoryEntryModel.InventoryCode);
            if (existingDbInvetoryRow != null)
            {
                existingDbInvetoryRow.Cost = inventoryEntryModel.Cost;
                existingDbInvetoryRow.Quantity = inventoryEntryModel.Quantity;

                db.Update(existingDbInvetoryRow);
            }
            else
            {
                db.Insert(DbInventoryEntry.FromInventoryEntry(inventoryEntryModel));
            }

            if (disposeFlg)
            {
                db.Close();
                db.Dispose();
            }

            return true;
    }
       private bool InsertInventoryRows(IEnumerable<InventoryEntry> inventoryEntryModels)
    {
        _logger.Debug("Enter");
        var dbRows = inventoryEntryModels.Select(entry => 
        (DbInventoryEntry.FromInventoryEntry(entry)));

        var db = _dataBaseConnection.GetSqLiteConnection();

        using (db)
        {
            db.InsertAll(dbRows);

            db.Close();
        }
        return true;
    }

The error I get is:

SQLite.SQLiteException: 'database is locked' or SQLite.SQLiteException: 'database is busy'

I found the solution thanks to Jason - github.com/praeclarum/sqlite-net/issues/700

I would advise you to keep a single SQLiteConnection for your app and cache it to take advantage of the type mapping caching strategy. Opening it with the Create |ReadWrite | FullMutex flags will ensure all operations are multithread-wise serialized. Don't forget to Dispose the connection whenever your app closes

This worked perfectly and speeded up the app ! Thanks Jason !

What i did was to handle one static connection that i held open all the time !

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