• c# Resolve SQlite Concurrency Exception Problem (Using Read-Write Lock)


    This article describes the c# example to solve the problem of SQlite concurrent exception method. To share with you for your reference, as follows:

    Access to sqlite using c#, often encounter multithreading SQLITE database damage caused by the problem.

    SQLite is a file-level database, the lock is the file level : multiple threads can be read at the same time, but only one thread to write. Android provides the SqliteOpenHelper class, adding Java’s locking mechanism for invocation. But does not provide similar functionality in c#.

    The author uses the ReaderWriterLock to achieve the goal of multi-thread secure access.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Data.SQLite;
    using System.Threading;
    using System.Data;
    namespace DataAccess
    {
    /////////////////
    public sealed class SqliteConn
    {
      private bool m_disposed;
      private static Dictionary<String, SQLiteConnection> connPool =
        new Dictionary<string, SQLiteConnection>();
      private static Dictionary<String, ReaderWriterLock> rwl =
        new Dictionary<String, ReaderWriterLock>();
      private static readonly SqliteConn instance = new SqliteConn();
      private static string DEFAULT_NAME = "LOCAL";
      #region Init
      //  Use single case , Solve the problem of initialization and destruction 
      private SqliteConn()
      {
        rwl.Add("LOCAL", new ReaderWriterLock());
        rwl.Add("DB1", new ReaderWriterLock());
        connPool.Add("LOCAL", CreateConn("\local.db"));
        connPool.Add("DB1", CreateConn("\db1.db"));
        Console.WriteLine("INIT FINISHED");
      }
      private static SQLiteConnection CreateConn(string dbName)
      {
        SQLiteConnection _conn = new SQLiteConnection();
        try
        {
          string pstr = "pwd";
          SQLiteConnectionStringBuilder connstr = new SQLiteConnectionStringBuilder();
          connstr.DataSource = Environment.CurrentDirectory + dbName;
          _conn.ConnectionString = connstr.ToString();
          _conn.SetPassword(pstr);
          _conn.Open();
          return _conn;
        }
        catch (Exception exp)
        {
          Console.WriteLine("===CONN CREATE ERR====
    {0}", exp.ToString());
          return null;
        }
      }
      #endregion
      #region Destory
      //  Manual control of the destruction , Ensure data integrity 
      public void Dispose()
      {
        Dispose(true);
        GC.SuppressFinalize(this);
      }
      protected void Dispose(bool disposing)
      {
        if (!m_disposed)
        {
          if (disposing)
          {
            // Release managed resources
            Console.WriteLine(" Close local DB Connect ...");
            CloseConn();
          }
          // Release unmanaged resources
          m_disposed = true;
        }
      }
      ~SqliteConn()
      {
        Dispose(false);
      }
      public void CloseConn()
      {
        foreach (KeyValuePair<string, SQLiteConnection> item in connPool)
        {
          SQLiteConnection _conn = item.Value;
          String _connName = item.Key;
          if (_conn != null && _conn.State != ConnectionState.Closed)
          {
            try
            {
              _conn.Close();
              _conn.Dispose();
              _conn = null;
              Console.WriteLine("Connection {0} Closed.", _connName);
            }
            catch (Exception exp)
            {Console.WriteLine(" Serious anomaly :  Unable to close local DB {0}  Connection 。", _connName);
              exp.ToString();}finally{
              _conn =null;}}}}#endregion#region GetConnpublicstaticSqliteConnGetInstance(){return instance;}publicSQLiteConnectionGetConnection(string name){SQLiteConnection _conn = connPool[name];try{if(_conn !=null){Console.WriteLine("TRY GET LOCK");// Lock , Until the release , Other threads can't get conn
            rwl[name].AcquireWriterLock(3000);Console.WriteLine("LOCK GET");return _conn;}}catch(Exception exp){Console.WriteLine("===GET CONN ERR====
    {0}", exp.StackTrace);}returnnull;}publicvoidReleaseConn(string name){try{// release Console.WriteLine("RELEASE LOCK");
          rwl[name].ReleaseLock();}catch(Exception exp){Console.WriteLine("===RELEASE CONN ERR====
    {0}", exp.StackTrace);}}publicSQLiteConnectionGetConnection(){returnGetConnection(DEFAULT_NAME);}publicvoidReleaseConn(){ReleaseConn(DEFAULT_NAME);}#endregion}}////////////////////////

    The code is invoked as follows:

    SQLiteConnection conn = null;
    try
    {
      conn = SqliteConn.GetInstance().GetConnection();
      // Write your own code here. 
    }
    finally
    {
      SqliteConn.GetInstance().ReleaseConn();
    }

    It is worth noting that each application connection, you must use the ReleaseConn method to release, otherwise the other thread can no longer be connected.

    For security reasons, the most stringent read and write lock restrictions are enabled in the tool class written by the author (ie, they can not be read at the time of writing). If the data is read frequently, the reader can also develop a way to get read-only connections to improve performance.

  • 相关阅读:
    linux中的 tar命令的 -C 参数,以及其它一些参数
    dockerfile 介绍
    linux安装mysql后root无法登录
    centos搭建本地yum源,
    centos7下载自定义仓库的镜像设置方法
    QT TCP文件上传服务器
    QT UDP聊天小程序
    QT 网络编程三(TCP版)
    QT 网络编程二(UDP版本)
    QT 网络编程一
  • 原文地址:https://www.cnblogs.com/mschen/p/8268499.html
Copyright © 2020-2023  润新知