想要在不同的服务器上部署我的项目,我希望能够使用相对路径指定连接字符串.我似乎无法让它工作,并想知道它是否有一些技巧......?
我有一个关于SQLite数据库的纯学术问题.
我正在使用SQLite.net在我的WinForm项目中使用数据库,当我设置一个新表时,我开始考虑ID列的最大值.
我使用IDENTITYfor my [ID]列,根据SQLite.net DataType Mappings,相当于DbType.Int64.我通常在零处启动我的ID列(将该行作为测试记录)并使数据库自动增加.
最大值(Int64.MaxValue)为9,223,372,036,854,775,807.出于我的目的,我甚至不会在达到最大值时划伤表面,但在数据库中发生了什么呢?在尝试阅读本文时,我发现DB2显然将值"包装"到负值(-9,223,372,036,854,775,807)并从那里递增,直到数据库无法插入行,因为ID列必须是唯一的.
这是在SQLite和/或其他数据库引擎中发生的事情吗?
我正在使用System.Data.Sqlite访问C#中的SQLite数据库.我有一个查询必须读取表中的行.在遍历行并且在阅读器打开时,必须执行某些SQL更新.我遇到了"数据库被锁定"异常.
在SQLite的文档状态:
当进程想要从数据库文件中读取时,它遵循以下步骤:
- 打开数据库文件并获取SHARED锁.
文档进一步说明了"共享"锁定:
可以读取数据库但不写入数据库.任意数量的进程可以同时保存SHARED锁,因此可以有许多同时读取器.但是,当一个或多个SHARED锁处于活动状态时,不允许其他线程或进程写入数据库文件.
在常见问题状态:
多个进程可以同时打开同一个数据库.多个进程可以同时执行SELECT.但是,只有一个进程可以随时对数据库进行更改.
SQLite权威指南一书指出:
... 通过使用read_uncommited编译指示,连接可以选择具有读取未提交的隔离级别.如果设置为true,则连接不会对其读取的表放置读锁定.因此,另一个writer实际上可以更改表,因为read-uncommitted模式下的连接既不会阻塞也不会被任何其他连接阻塞.
我尝试将pragma设置为在SQL查询命令语句中读取未提交,如下所示:
PRAGMA read_uncommitted = 1;
SELECT Column1, Column2 FROM MyTable
Run Code Online (Sandbox Code Playgroud)
使用不同连接在同一线程上的SQL更新仍然失败,并出现"数据库已锁定"异常.然后,我尝试将隔离级别设置为在连接实例上读取未提交.同样的例外仍然没有变化.
如何在不锁定数据库的情况下使用开放数据读取器来遍历数据库中的行,以便我可以执行更新?
更新:
以下两个答案都有效.然而,我已经从使用默认回滚日志转移到现在使用预写日志,这提供了改进的数据库读写并发性.
我正在尝试使用System.Data.Sqlite库,我正在遵循有关优化插入的文档,因此我直接从文档中复制了此代码:
using (SQLiteTransaction mytransaction = myconnection.BeginTransaction())
{
using (SQLiteCommand mycommand = new SQLiteCommand(myconnection))
{
SQLiteParameter myparam = new SQLiteParameter();
int n;
mycommand.CommandText = "INSERT INTO [MyTable] ([MyId]) VALUES(?)";
mycommand.Parameters.Add(myparam);
for (n = 0; n < 100000; n ++)
{
myparam.Value = n + 1;
mycommand.ExecuteNonQuery();
}
}
mytransaction.Commit();
}
Run Code Online (Sandbox Code Playgroud)
现在,我通过使用来初始化我之前的连接
SqlConnection myconnection = new SqlConnection("Data Source=blah");
Run Code Online (Sandbox Code Playgroud)
我有一个名为blah的数据库,具有正确的表和值.
问题是当我运行这段代码时,它说"由于对象的当前状态,操作无效"
我已尝试多次更改代码,它仍指向BeginTransaction.是什么赋予了?
我已经做了一些搜索,也阅读了SQLite网站上的常见问题解答,没有运气找到我的问题的答案.
很可能我的数据库方法存在缺陷,但目前,我想将我的数据存储在多个SQLite3数据库中,这意味着单独的文件.我非常担心由于我的应用程序可能崩溃导致的数据损坏,或者在我的表中更改数据时停电.
为了确保数据完整性,我基本上需要这样做:
在数据库#1中启动事务修改表#1修改数据库#2提交中的表,如果错误则回滚
这是否得到了SQLite的支持?另外,我使用的是sqlite.net,特别是基于SQLite 3.6.23.1的最新版本.
UPDATE
还有一个问题 - 这是人们通常会在单元测试中添加的内容吗?我总是单元测试数据库,但从来没有像这样的情况.如果是这样,你会怎么做?这几乎就像你必须将另一个参数传递给方法,如bool test_transaction,如果是真的,则在数据库访问之间抛出异常.然后在调用后进行测试,以确保第一组数据没有进入其他数据库.但也许这是可以被SQLite的测试覆盖了东西,应该不会出现在我的测试案例.
我确信有一些简单的事情我还没有完成,但我想让Fluent NHibernate在我的机器上使用Sqlite.
我使用NuGet下载流畅的nhibernate并添加了以下实体和映射:
public class Customer
{
public virtual string CustomerCode { get; set; }
public virtual string Name { get; set; }
}
public class CustomerMap : ClassMap<Customer>
{
public CustomerMap ()
{
Id(x => x.CustomerCode);
Map(x => x.Name);
Table("tblCustomer");
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在开始使用流畅的指南之后,我将以下代码添加到Windows Command项目中:
class Program
{
static void Main(string[] args)
{
var sessionFactory = CreateSessionFactory();
using (var session = sessionFactory.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var customer = new Customer { CustomerCode = "123", Name = …Run Code Online (Sandbox Code Playgroud) 我正在尝试加载一个SQLite数据库,该数据库将作为资源嵌入我的可执行文件中.对于那些好奇的人来说,这是因为我使用一个小的SQLite数据库来存储配置数据,并且我想发布嵌入在可执行文件中的默认配置(我讨厌必须随文件携带文件).
这只是默认配置.也就是说,我不需要修改此配置.它是静态的,在我的程序构建完成后无法更改.
我正在使用SQLite的System.Data.SQLite包装器.
我可以像这样访问字节流:
using (var stream =
Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) {
// use of "stream" here.
}
Run Code Online (Sandbox Code Playgroud)
但是,关于SQLiteConnection从此流创建对象,我感到很茫然.
简单的方法是在每次程序加载时简单地生成一个新的配置文件,然后告诉SQLite从该文件中读取.这可能会工作,但我想避免这种技术 - 我打算重用我解决这个问题还包括国际化的支持(其中每种语言是[压缩] SQLite数据库和默认语言嵌入可执行文件 - 一个用户可以添加其他语言,只需将其他语言数据库复制到程序的工作目录中).
我不关心在内存中保存这个数据库的内存成本.它会非常小(可能小于50 KiB),所以这不会打扰我.显然,如果这是一个更大的数据库,这可能是一个问题.
最后,我知道这可能被视为存储配置的一种糟糕方式.虽然我同意基于纯文本的解决方案适用于用户手动输入所有设置的情况,但这主要用于用户未明确定义的设置.例如,将各种停靠窗口的位置存储在应用程序中,或存储有关可能找到内部资源的位置的数据.
谢谢您的帮助.
在Write-Ahead Logging模式下使用System.Data.Sqlite 1.0.86.0(包括SQLite 3.7.17),我在同时读取时遇到数据库锁定,如果我正确理解WAL,则不应该这样.我没有编写或提交任何内容,并且ReadCommitted正确使用事务隔离模式来避免序列化读取.
准备"选择"状态时,SQLite DB(带WAL)被锁定 - 为什么?是一个类似的问题.唯一的答案是关于sqlite3_reset每个之后的调用sqlite3_step,这是由我在源代码中看到的System.Data.Sqlite正确完成的.
完全复制:
internal static class Program {
private const string DbFileName = "test.sqlite";
private static readonly string _connectionString = BuildConnectionString(DbFileName);
internal static void Main() {
File.Delete(DbFileName);
ExecuteSql("CREATE TABLE Test (Id INT NOT NULL, Name TEXT);", true);
for (int i = 0; i < 10; i++)
Task.Run(() => ExecuteSql("SELECT Id, Name FROM Test;", false));
Console.ReadKey();
}
private static string BuildConnectionString(string fileName) {
var builder = …Run Code Online (Sandbox Code Playgroud) 我注意到该SQLiteConnection对象System.Data.SQLite拥有两个类似的方法:
Close()Dispose()SQLiteDataReader对象相同.
有什么不同 ?
我正在尝试使用Dapper连接到现有的数据库格式,该格式具有在BIGINT列中编码为刻度的持续时间的表.TimeSpan在插入和读取数据库时,如何告诉Dapper将我的POCO的-typed属性映射到滴答?
我试着设置类型映射TimeSpan到DbType.Int64:
SqlMapper.AddTypeMap(typeof(TimeSpan), DbType.Int64);
Run Code Online (Sandbox Code Playgroud)
我也创建了一个ITypeHandler,但SetValue从未调用过该方法:
public class TimeSpanToTicksHandler : SqlMapper.TypeHandler<TimeSpan>
{
public override TimeSpan Parse(object value)
{
return new TimeSpan((long)value);
}
public override void SetValue(IDbDataParameter parameter, TimeSpan value)
{
parameter.Value = value.Ticks;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的POCO:
public class Task
{
public TimeSpan Duration { get; set; }
// etc.
}
Run Code Online (Sandbox Code Playgroud)
执行这样的简单插入语句时:
string sql = "INSERT INTO Tasks (Duration) values (@Duration);";
Run Code Online (Sandbox Code Playgroud)
并将POCO作为要插入的对象传递:
Task task = new Task { Duration = TimeSpan.FromSeconds(20) }; …Run Code Online (Sandbox Code Playgroud) sqlite ×9
c# ×5
.net ×2
database ×2
concurrency ×1
dapper ×1
locking ×1
nhibernate ×1
orm ×1
transactions ×1