Параллельные транзакции UWP SQLite

#sqlite #uwp #sqlite-net-pcl

Вопрос:

Я разрабатываю приложение UWP, которое может одновременно загружать файлы и записывать данные файлов в базу данных SQLite. Я использовал sqlite-net-pcl в качестве оболочки SQLite. Я получаю исключения из БД, когда выполняю несколько транзакций базы данных. Это пример кода, как я использую SQLite.

AppSQLite.cs

 //Database name
     public static readonly string DATABASE_NAME = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "App.db");
     SQLiteAsyncConnection conn = null;

     /// <summary>
     /// Constructor
     /// </summary>
     public SASQLite()
     {
         try
         {
             conn = new SQLiteAsyncConnection(DATABASE_NAME);
             CreateTables();
         }
         catch (Exception er)
         {
              Log(er);
         }
     }

     public async Task CreateTables()
     {
         try
         {
             await CreateUserTable();
             await CreateUserProject();
             await CreateUserFacility();
             await CreateTopic();
                  //More tables to create
         }
         catch (Exception er)
         {
                 Log(er);
         }
         finally
         {
             await conn.CloseAsync();
         }
         AppUtils.PrintDebug("=========End", CLASS_NAME, "CreateTables");
     }

     // All the table creations similar to this
     private async Task CreateUserTable()
     {
         if (conn != null)
         {
             await conn.CreateTableAsync<User>();
         }
         else
         {
             //null connection
         }
     }
 

Тема: <url>

 /// <summary>
     /// add topic to topic table
     /// </summary>
     /// <param name="topicModel"></param>
     /// <returns></returns>
     public static async Task AddTopic(TopicModel topicModel)
     {
         try
         {
             SQLiteAsyncConnection conn = new SQLiteAsyncConnection(AppSQLite.DATABASE_NAME);
             // create a new Id for the db entry
             string id = Guid.NewGuid().ToString();

             Topic topic = new Topic()
             {
                 Id = id,
                 TopicId = topicModel.Id,
                 TopicTitle = topicModel.TopicTitle,
                 TopicContent = topicModel.Content,
                 DocumentId = topicModel.DocumentId
             };
             await conn.InsertAsync(topic);
                    
             await conn.CloseAsync();
         }
         catch (Exception er)
         {
            Log(ex);
         }
      }
    }
 

Write data to database

  ......

 foreach (IXmlNode topicElement in TopicElementList)
                     {
                         if (topicElement.NodeType == NodeType.ElementNode)
                         {
                             string itemType = null;
                             if (topicElement.Attributes.GetNamedItem("itemType") != null)
                             {
                                 itemType = topicElement.Attributes.GetNamedItem("itemType").NodeValue as string;
                             }

                             if (itemType == "Topic")
                             {
                                 // Create topic using topicElement
                                ............
                                 await TopicDAL.AddTopic(topic);
                             }
                             ................................
                             }
                         }  
 

There can be 1000 topics for each download and user can do 100 of such downloads. So this fails with different DB exceptions as followings.

TopicDAL::AddTopic::=========Start TopicDAL::AddTopic::=========Id : d94a0a04-4bea-4b68-8757-cb304e36d16b Exception thrown: ‘System.NullReferenceException’ in System.Private.CoreLib.dll TopicDAL::AddTopic::=========Exception : System.NullReferenceException: Object reference not set to an instance of an object. at SQLite.PreparedSqlLiteInsertCommand.ExecuteNonQuery(Object[] source) at SQLite.SQLiteConnection.Insert(Object obj, String extra, Type objType) at SQLite.SQLiteAsyncConnection.<>c_DisplayClass33_0 1.<WriteAsync>b_0() at System.Threading.Tasks.Task 1.InnerInvoke() at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) — End of stack trace from previous location where exception was thrown — at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Taskamp; currentTaskSlot) — End of stack trace from previous location where exception was thrown — at App.Repository.DAL.TopicDAL.AddTopic(TopicModel topicModel)

===== = ===Исключение : Система.Исключение ArgumentNullException: SafeHandle не может быть нулевым. Имя параметра: pHandle в системе.СтабХелперы.СтабХелперы.SafeHandleAddRef(функция SafeHandle, логическое значение и успех) в SQLitePCL.SQLite3Provider_e_sqlite3.NativeMethods.sqlite3_prepare_v2(база данных sqlite3, байт* pSql, 32 байта, IntPtr и stmt, Байт* и ptrRemain) в SQLitePCL.SQLite3Provider_e_sqlite3.SQLitePCL.ISQLite3Provider.sqlite3_prepare_v2(база данных sqlite3, sql utf8z, IntPtr и stm, utf8z и хвост) в SQLitePCL.raw.sqlite3_prepare_v2(база данных sqlite3, sql utf8z, sqlite3_stmt и stmt) в SQLite.SQLite3.Подготовьте 2(бд sqlite3, строковый запрос) в SQLite.Подготовитьклитейинсерт-команду.ExecuteNonQuery(объект[] источник) в SQLite.Подключение к SQLiteConnection.Вставьте(Объект obj, Дополнительная строка, Тип objType) в SQLite.Соединение SQLiteAsyncConnection.<>c_DisplayClass33_0<> 1.<WriteAsync>b_0() at System.Threading.Tasks.Task 1.InnerInvoke() в системе.Нарезание резьбы.Контекст исполнения.RunInternal(ExecutionContext ExecutionContext, обратный вызов ContextCallback, состояние объекта) — Конец трассировки стека из предыдущего местоположения, в котором в системе было вызвано исключение.Нарезание резьбы.Задачи.Задачи.ExecuteWithThreadLocal(Taskamp; currentTaskSlot) — Конец трассировки стека из предыдущего местоположения, где было создано исключение —

Не могли бы вы, пожалуйста, направить меня, если есть какие-либо проблемы с этим дополнением? Если это связано с оболочкой SQLite, что может быть лучшим вариантом для использования в этом сценарии?

Комментарии:

1. Поскольку ваши вставленные данные получены из Интернета, воспроизвести вашу проблему сложно. Сообщение об исключении запрашивает пустую ссылку в AddTopic методе, поэтому вам необходимо проверить, пуст ли переданный объект ( topicModel ), прежде чем вставлять его в таблицу. Кроме того, вам также необходимо проверить, открыто ли соединение с базой данных.