2014-09-26 5 views
0

Использование SQLite, System.Data.SQLite и Dapper (в консольном приложении, а затем Windows Service, высокая пропускная способность); почему «база данных заблокирована», так или иначе?SQLite и «База данных заблокирована»

Я даже абстрагироваться призывающим к БД SQLite в этом методе:

public static void LocalDbScope(Action<IDbConnection> action) 
{ 
    try 
    { 
     lock (DbLock) 
     { 
      using (var connection = Open(LocalStorageConnectionString)) 
      { 
       action(connection); 
      } 
     } 
    } 
    catch (Exception xux) 
    { 
     ErrLog.Error(xux); 
     throw; 
    } 
} 

Включения отображенных в памяти опции не помог:

connection.Execute("PRAGMA wal_autocheckpoint=32; PRAGMA journal_size_limit = 2048;"); 
connection.Execute("PRAGMA mmap_size=" + GB); 

И это строка соединения:

var builder = new SQLiteConnectionStringBuilder 
{ 
    DataSource = storageDbFilePath, 
    FailIfMissing = false, 
    PageSize = 32 * KB, 
    CacheSize = 10 * MB, 
    ForeignKeys = false, 
    UseUTF16Encoding = false, 
    Pooling = true, 
    JournalMode = SQLiteJournalModeEnum.Wal, 
    SyncMode = SynchronizationModes.Normal, 
    DateTimeKind = DateTimeKind.Utc, 
    DateTimeFormat = SQLiteDateFormats.ISO8601, 
    DefaultIsolationLevel = IsolationLevel.ReadCommitted, 
    DefaultTimeout = (int)TimeSpan.FromMinutes(1).TotalMilliseconds 
}; 
LocalStorageConnectionString = builder.ToString(); 

Что мне здесь не хватает?

Примечание. Когда вы используете Google для «базы данных заблокировано», все верхние результаты (и вся первая страница) относятся к этой проблеме на разных языках программирования и платформах. Кажется, что в SQLite есть что-то еще, что я не могу отфильтровать эту картину.

+0

Понятия не имею, но вместо того, чтобы Dapper, взглянуть на SQLite-сети, и это подключение асинхронной. –

+0

Что делать, если вы пытаетесь сделать его в памяти db. Google, но это было так же просто, как поставить: men: или эквивалент в cnnstring. –

+0

Локальное хранилище необходимо для обеспечения того, чтобы не было потери данных, независимо от того, вставлена ​​или нет основная база данных; даже когда происходят грязные выключения. Для этой цели нельзя использовать резидентную базу данных. –

ответ

1

Как указано в моем комментарии, у меня нет идеи о том, что происходит, продолжается, не видя больше вашего кода.

Тем не менее, если вы не хотите менять Dapper на Sqlite-net, ниже приведен небольшой пример без блокировки, используя вашу абстракцию, которая не бросает никаких исключений. Надеюсь, это поможет вам понять это.

using System; 
using System.Data; 
using System.Data.SQLite; 
using System.Linq; 
using System.Threading; 
using System.Threading.Tasks; 
using Dapper; 

namespace MyConsoleApplication 
{ 
    public class Program 
    { 
     static void Main(string[] args) 
     { 
      var test = new TestSQLite(); 
      test.GoForIt(); 
     } 
    } 

    public class Entity 
    { 
     public int Id { get; set; } 
     public string Content { get; set; } 
    } 

    public class TestSQLite 
    { 
     private const string ConnectionString = "Data Source=sqlitetest.sqlite"; 
     private static readonly object DbLock = new object(); 

     public void GoForIt() 
     { 
      CreateTable(); 

      var random = new Random(); 

      for (int i = 0; i < 100; i++) 
      { 
       if (i % 2 != 0) 
       { 
        Task.Factory.StartNew(() => Thread.Sleep(random.Next(0, 200))).ContinueWith(other => 
         LocalDbScope(action => 
          { 
           var entity = new Entity {Content = "hoax"}; 
           entity.Id = action.Query<int>(
            @"insert into entity (content) values (@Content); select last_insert_rowid()", 
            entity).First(); 
           var ids = action.Query<int>(@"select id from entity").ToList(); 
           Console.WriteLine("Inserted id:{0}, all ids:[{1}]", entity.Id, string.Join(",", ids)); 
          })); 
       } 
       else 
       { 
        Task.Factory.StartNew(() => Thread.Sleep(random.Next(200, 500))).ContinueWith(other => 
         LocalDbScope(action => 
          { 
           action.Execute(@"delete from entity"); 
           Console.WriteLine("Deleted all entities"); 
          })); 
       } 
      } 

      Console.ReadLine(); 
     } 

     public static void LocalDbScope(Action<IDbConnection> action) 
     { 
      lock (DbLock) 
      { 
       using (var connection = new SQLiteConnection(ConnectionString)) 
        action(connection); 
      } 
     } 

     private static void CreateTable() 
     { 
      using (IDbConnection c = new SQLiteConnection(ConnectionString)) 
      { 
       c.Execute(@"drop table if exists entity"); 
       c.Execute(@"create table entity (id integer primary key autoincrement, content varchar(100))"); 
      } 
     } 
    } 
} 

 

enter image description here

+0

Thanks; Я думаю, что это что-то не так с SQLite, когда у вас высокая пропускная способность. В настоящее время я полностью отклонил локальную базу данных из проекта (pre-alpha), потому что я потратил на это достаточно времени. Я рассмотрю это снова. «Мой опыт» с SQLite был настолько разочаровывающим до сих пор. –

+0

Дайте еще одну попытку. У меня есть только хороший опыт, я использовал его на Win8, родном Windows Phone 7/8- и гибридных кросс-платформенных приложениях –

Смежные вопросы