[UWP] Run SQLite Concurrent Transactions

SudhaSub 1 Reputation point
2021-06-09T09:33:39.58+00:00

Hi,

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?

Thanks

Universal Windows Platform (UWP)
SQL Server
SQL Server
A family of Microsoft relational database management and analysis systems for e-commerce, line-of-business, and data warehousing solutions.
12,641 questions
{count} votes