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.

  • 相关阅读:
    元素的ID和Name有什么区别???[转自"天道酬勤"]
    招聘时会问到的问题
    关于asp.net开发B/S应用系统的思索和讨论
    软件文档知多少?
    C# 编码规范和编程好习惯
    [转]多层结构来开发ASP.NET程序
    ASP.NET页面间的传值的几种方法
    为sql server 表数据生成创建的储存过程(生成insert 脚本)
    XHTML+CSS应用教程——利用CSS实现双语导航条
    XHTML+CSS应用教程——CSS实现文字的双影
  • 原文地址:https://www.cnblogs.com/mschen/p/8268499.html
Copyright © 2011-2022 走看看