zoukankan      html  css  js  c++  java
  • 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.

  • 相关阅读:
    欢迎加入强哥的 Android 开发交流群
    HashMap和ConcurrentHashMap的区别,HashMap的底层源码
    angular ngIf 导致不点击屏幕,就无法显示内容的问题
    angular date 过滤器不兼容 ios 造成 列表循环渲染错误的问题
    部署Node.js到阿里云服务器CentOs
    使用手淘VW适配方案后造成伪类使用content报错的解决办法
    Vue 加载 Sass Loader 报错的解决方案
    Typescript中private、public、protected修饰符的区别
    搭建Android开发环境 以及 ionic 编译安卓app步骤
    前端开发规范:3-CSS
  • 原文地址:https://www.cnblogs.com/mschen/p/8268499.html
Copyright © 2011-2022 走看看