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.

  • 相关阅读:
    【洛谷 1536】村村通
    【洛谷 1551】亲戚
    【UOJ 300】感冒病毒
    【洛谷 2299】Mzc和体委的争夺战
    【洛谷 3371】模板_单源最短路径(弱化版)
    【洛谷 2910】寻宝之路
    【洛谷 1359】租用游艇
    【UOJ 275】最短路径问题
    【UOJ 38】 股票经济人通信网络
    【UOJ 276】无向图最小环
  • 原文地址:https://www.cnblogs.com/mschen/p/8268499.html
Copyright © 2011-2022 走看看