0

I am developing a UWP app, which can download files concurrently and write file data to SQLite database. I have used sqlite-net-pcl as SQLite wrapper. I get DB exceptions when I am running multiple database transactions. This is sample code how I am using 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
         }
     }

TopicDAL.cs

/// <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_01.<WriteAsync>b_0() at System.Threading.Tasks.Task1.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(Task& currentTaskSlot) --- End of stack trace from previous location where exception was thrown --- at App.Repository.DAL.TopicDAL.AddTopic(TopicModel topicModel)

=========Exception : System.ArgumentNullException: SafeHandle cannot be null. Parameter name: pHandle at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success) at SQLitePCL.SQLite3Provider_e_sqlite3.NativeMethods.sqlite3_prepare_v2(sqlite3 db, Byte* pSql, Int32 nBytes, IntPtr& stmt, Byte*& ptrRemain) at SQLitePCL.SQLite3Provider_e_sqlite3.SQLitePCL.ISQLite3Provider.sqlite3_prepare_v2(sqlite3 db, utf8z sql, IntPtr& stm, utf8z& tail) at SQLitePCL.raw.sqlite3_prepare_v2(sqlite3 db, utf8z sql, sqlite3_stmt& stmt) at SQLite.SQLite3.Prepare2(sqlite3 db, String query) at SQLite.PreparedSqlLiteInsertCommand.ExecuteNonQuery(Object[] source) at SQLite.SQLiteConnection.Insert(Object obj, String extra, Type objType) at SQLite.SQLiteAsyncConnection.<>c_DisplayClass33_01.<WriteAsync>b_0() at System.Threading.Tasks.Task1.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(Task& currentTaskSlot) --- End of stack trace from previous location where exception was thrown ---

Can you please guide me if there is any issue withthis mplementation? If it is related to SQLite wrapper what can be the best option, to use in this scenario?

4

0 に答える 0