微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

UWP SQLite 并发事务

如何解决UWP SQLite 并发事务

我正在开发一个 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
         }
     }

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);
         }
      }
    }

将数据写入数据库

 ......

 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);
                             }
                             ................................
                             }
                         }  

每次下载可以有 1000 个主题用户可以进行 100 次这样的下载。因此,这会因以下不同的数据库异常而失败。

TopicDAL::AddTopic::==========Start TopicDAL::AddTopic::========Id : d94a0a04-4bea-4b68-8757-cb304e36d16b 异常抛出:'系统System.Private.CoreLib.dll 中的 .NullReferenceException' TopicDAL::AddTopic::==========异常:System.NullReferenceException:未将对象引用设置为对象的实例。在 sqlite.PreparedsqlLiteInsertCommand.ExecuteNonQuery(Object[] source) 在 sqlite.sqliteConnection.Insert(Object obj,String extra,Type objType) 在 sqlite.sqliteAsyncConnection.c_displayClass33_01.<WriteAsync>b_0() at System.Threading.Tasks.Task1.InnerInvoke() 在 System.Threading .ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object state) --- 从上一个抛出异常的位置开始的堆栈跟踪结束 --- 在 System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot) --- 结束来自之前抛出异常的位置的堆栈跟踪 --- 在 App.Repository.DAL.TopicDAL.AddTopic(TopicModel topicModel)

==========异常:System.ArgumentNullException:SafeHandle 不能为空。参数名称:pHandle at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle,布尔值和成功)在 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,sqlite3_stmt& stmt) 在 sqlite.sqlite3.Prepare2(sqlite3 db,String query) at sqlite.PreparedsqlLiteInsertCommand.ExecuteNonQuery(Object[] source) 在 sqlite.sqliteConnection.Insert(Object obj,Type 对象类型)在 sqlite.sqliteAsyncConnection.c_displayClass33_01.<WriteAsync>b_0() at System.Threading.Tasks.Task1.InnerInvoke() 在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback 回调,对象状态) --- 在 System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& 当前任务槽) --- 从上一个抛出异常的位置开始的堆栈跟踪结束---

如果这个实现有任何问题,你能指导我吗?如果它与 sqlite 包装器有关,在这种情况下使用什么是最佳选择?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。