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.

  • 相关阅读:
    eclipse中文乱码问题解决方案
    修改Tomcat的JDK目录
    Tomcat 5.5 修改服务器的侦听端口
    HTML DOM教程 27HTML DOM Button 对象
    HTML DOM教程 24HTML DOM Frameset 对象
    Navicat for MySQL v8.0.27 的注册码
    HTML DOM教程 25HTML DOM IFrame 对象
    Tomcat 5.5 的下载和安装
    android manifest相关属性
    ubuntu10.04 下 eclipse 小结
  • 原文地址:https://www.cnblogs.com/mschen/p/8268499.html
Copyright © 2011-2022 走看看