C# SQLite和;“数据库已锁定”;
使用SQLite、System.Data.SQLite和Dapper(在控制台应用程序中;更高版本的Windows服务;高吞吐量);为什么会有“数据库被锁定” 我甚至用这种方法抽象了对SQLite db的所有调用:C# SQLite和;“数据库已锁定”;,c#,sqlite,dapper,C#,Sqlite,Dapper,使用SQLite、System.Data.SQLite和Dapper(在控制台应用程序中;更高版本的Windows服务;高吞吐量);为什么会有“数据库被锁定” 我甚至用这种方法抽象了对SQLite db的所有调用: public static void LocalDbScope(Action<IDbConnection> action) { try { lock (DbLock) { using (var con
public static void LocalDbScope(Action<IDbConnection> action)
{
try
{
lock (DbLock)
{
using (var connection = Open(LocalStorageConnectionString))
{
action(connection);
}
}
}
catch (Exception xux)
{
ErrLog.Error(xux);
throw;
}
}
这是连接字符串:
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();
我错过了什么
注意:当你用谷歌搜索“数据库被锁定”时,所有最重要的结果(以及整个第一页)都是关于不同编程语言和平台中的这个问题。似乎SQLite还有其他一些东西我无法从这张图片中过滤掉。如我在评论中所述,我不知道在没有看到更多代码的情况下会发生什么 尽管如此,如果您不愿意将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))");
}
}
}
}
使用系统;
使用系统数据;
使用System.Data.SQLite;
使用System.Linq;
使用系统线程;
使用System.Threading.Tasks;
使用整洁;
命名空间MyConsoleApplication
{
公共课程
{
静态void Main(字符串[]参数)
{
var test=新的TestSQLite();
test.GoForIt();
}
}
公共类实体
{
公共int Id{get;set;}
公共字符串内容{get;set;}
}
公共类TestSQLite
{
private const string ConnectionString=“数据源=sqlitetest.sqlite”;
私有静态只读对象DbLock=新对象();
公共部门
{
CreateTable();
var random=新的random();
对于(int i=0;i<100;i++)
{
如果(i%2!=0)
{
Task.Factory.StartNew(()=>Thread.Sleep(random.Next(0200))).ContinueWith(other=>
LocalDbScope(操作=>
{
var实体=新实体{Content=“hoax”};
entity.Id=action.Query(
@“插入实体(内容)值(@content);选择最后一次插入\u rowid()”,
实体);
var id=action.Query(@“从实体中选择id”).ToList();
WriteLine(“插入的id:{0},所有id:[{1}]”,entity.id,string.Join(“,”,ids));
}));
}
其他的
{
Task.Factory.StartNew(()=>Thread.Sleep(random.Next(200500))).ContinueWith(other=>
LocalDbScope(操作=>
{
执行(@“从实体中删除”);
Console.WriteLine(“删除所有实体”);
}));
}
}
Console.ReadLine();
}
公共静态void LocalDbScope(操作)
{
锁(DbLock)
{
使用(var连接=新的SQLiteConnection(ConnectionString))
行动(联系);
}
}
私有静态void CreateTable()
{
使用(IDbConnection=newSQLiteConnection(ConnectionString))
{
c、 执行(@“如果存在实体,则删除表”);
c、 执行(@“创建表实体(id integer主键自动递增,content varchar(100))”;
}
}
}
}
不知道,但请看一下sqlite net及其异步连接,而不是dapper。如果您尝试在内存数据库中创建它会怎么样。谷歌搜索它,但它很简单,只要在cnnstring中输入:men:或同等内容即可。无论主数据库是否启动,都需要一个本地存储来确保不会丢失数据;即使发生脏停机。内存驻留数据库不能用于此目的。您完全正确。您说过“当您具有高吞吐量时,我认为SQLite有问题。”所以我想如果您尝试内存数据库,您会确认它,否则db锁是由其他原因造成的。谢谢;我认为当您具有高吞吐量时,SQLite有问题。目前,我已经完全从项目中删除了本地数据库(pre-alpha),因为我在这方面花了足够的时间。我会再调查的。到目前为止,SQLite的“我的经历”令人失望。再试一次。到目前为止,我只有很好的体验,我一直在Win8、原生Windows Phone 7/8和混合跨平台应用程序上使用它
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))");
}
}
}
}