开始
sqlite-net被设计为在.NET环境中使用sqlite非常简单。
该库包含可用于控制表的构造的简单属性。 在一个简单的股票程序中,您可以使用:
public class Stock
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Symbol { get; set; }
}
public class Valuation
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[Indexed]
public int StockId { get; set; }
public DateTime Time { get; set; }
public decimal Price { get; set; }
}
有了这些,您可以通过调用CreateTable自动在数据库中生成表格:
var db = new SQLiteConnection("foofoo");
db.CreateTable<Stock>();
db.CreateTable<Valuation>();
您可以使用Insert
在数据库中插入行。 如果表中包含一个自动递增的主键,那么插入后该键的值将可用:
public static void AddStock(SQLiteConnection db, string symbol) {
var Id = db.Insert(new Stock() {
Symbol = symbol
});
Console.WriteLine("{0}", Id);
}
您可以使用SQLiteConnection
的Query
方法查询数据库:
public static IEnumerable<Valuation> QueryValuations (SQLiteConnection db, Stock stock)
{
return db.Query<Valuation> ("select * from Valuation where StockId = ?", stock.Id);
}
Query方法的通用参数指定要为每行创建的对象的类型。 它可以是您的表类或其公共属性与查询返回的列匹配的任何其他类。 例如,我们可以将上面的查询重写为:
public class Val {
public decimal Money { get; set; }
public DateTime Date { get; set; }
}
public static IEnumerable<Val> QueryVals (SQLiteConnection db, Stock stock)
{
return db.Query<Val> ("select \"Price\" as \"Money\", \"Time\" as \"Date\" from Valuation where StockId = ?", stock.Id);
}
更新必须使用SQLiteConnection
的Execute
方法手动执行。
Asynchronous API
您可以调用不会阻塞的”asynchronous API”。 您可能会考虑将移动应用程序的异步API用于增加响应性。
异步库使用任务并行库(TPL)。 因此,Task对象的正常使用以及async和await关键字将适用于您。
一旦定义了实体,就可以通过调用CreateTableAsync
自动生成表格:
var conn = new SQLiteAsyncConnection("foofoo");
conn.CreateTableAsync<Stock>().ContinueWith((results) =>
{
Debug.WriteLine("Table created!");
});
您可以使用Insert
在数据库中插入行。 如果表中包含一个自动递增的主键,那么插入后该键的值将可用:
Stock stock = new Stock()
{
Symbol = "AAPL"
};
var conn = new SQLiteAsyncConnection("foofoo");
conn.InsertAsync(stock).ContinueWith((t) =>
{
Debug.WriteLine("New customer ID: {0}", stock.Id);
});
UpdateAsync
和DeleteAsync
存在类似的方法。
查询数据最直接的方法是使用Table方法。 这将返回一个AsyncTableQuery
实例,因此您可以添加预测约束通过WHERE子句和/或添加ORDER BY
。 只有在调用特殊的检索方法之一ToListAsync
,FirstAsync
或FirstOrDefaultAsync
之后,才会触及数据库。
var conn = new SQLiteAsyncConnection("foofoo");
var query = conn.Table<Stock>().Where(v => v.Symbol.StartsWith("A"));
query.ToListAsync().ContinueWith((t) =>
{
foreach (var stock in t.Result)
Debug.WriteLine("Stock: " + stock.Symbol);
});
有一些低层方法可用。 您也可以通过QueryAsync
方法直接查询数据库。 除了InsertAsync
提供的更改操作之外,您可以发出ExecuteAsync
方法直接在数据库内更改数据集。
另一个有用的方法是ExecuteScalarAsync
。 这使您可以轻松地从数据库返回标量值:
var conn = new SQLiteAsyncConnection("foofoo");
conn.ExecuteScalarAsync<int>("select count(*) from Stock", null).ContinueWith((t) =>
{
Debug.WriteLine(string.Format("Found '{0}' stock items.", t.Result));
});
特征
ORM
ORM能够获得一个.NET类的定义并将其转换为SQL表定义。 (大多数ORM都是朝另一个方向发展。)它通过检查您的类的所有公共属性来完成此任务,并且可以使用可用于指定列详细信息的属性进行辅助。
使用以下属性:
PrimaryKey
该属性是表的主键。只支持单列主键。AutoIncrement
该属性在插入时由数据库自动生成。 属性类型应该是一个整数,也应该用PrimaryKey属性标记.Indexed
这个属性应该为它创建一个索引.MaxLength
如果此属性是一个字符串,则使用MaxLength指定varchar max的大小。 默认的最大长度是140。Ignore
这个属性不会在表中.
属性支持以下数据类型:
Integers
使用integer
或bigint
SQLite类型存储.Boolean
被存储为integers
,值1被指定为true
,而所有其他值都是false
的。Enums
以enum的值存储为integers
.Singles
andDoubles
浮点数存储为float
列.Strings
存储为 使用由MaxLength属性指定的最大大小的变量存储。 如果未指定属性,则最大长度默认为140 .DateTimes
存储为datetime
列并受到SQLite提供的精度的支配.- Byte数组
byte[]
存储为blob
列. Guid
结构存储为varchar(36) 列.
事务
库支持嵌套事务。 它们都可以在同步API和异步API中使用。
同步API
当使用同步SQLiteConnection
时,在事务内部执行的数据库调用应作为一个Action
传递给RunInTransaction(Action)
:
var db = new SQLiteConnection(path);
db.RunInTransaction(() => {
// database calls inside the transaction
db.Insert(stock);
db.Insert(valuation);
});
请注意,在Action
委托中,在调用RunInTransaction
(上例中的名为db)时使用了SQLiteConnection
的相同实例。
异步API
在使用异步SQLiteAsyncConnection
时,要在事务内部执行的数据库调用应作为Action <SQLiteConnection>
传递给RunInTransactionAsync(Action<SQLiteConnection>)
:
var db = new SQLiteAsyncConnection(path);
db.RunInTransactionAsync(tran => {
// database calls inside the transaction
tran.Insert(stock);
tran.Insert(valuation);
});
请注意,在Action
委托中,正在使用SQLiteConnection
实例(在上例中命名为tran
),而不是调用RunInTransactionAsync
来自SQLiteAsyncConnection
的实例(上面的示例中名为db)。
低层API
大部分时间RunInTransaction
和RunInTransactionAsync
方法应该是你所需要的。 如果由于某种原因需要更多的控制,SQLiteConnection
包含一组处理事务的方法:
BeginTransaction
开始一个新的事务。 如果事务已经打开,它将引发异常SaveTransactionPoint
在可以回滚的事务中创建一个新的保存点。 如果没有事务正在进行,它将启动一个新的事务,因此它可以作为BeginTransaction
的一个更安全的替代方案.Commit
提交当前事务.Rollback
完全回滚当前的事务.RollbackTo
可以回滚到由SaveTransactionPoint
返回的现有保存点.
处理错误
如果您的事务代码抛出一个异常,那么在事务回滚后,它将冒泡到RunInTransaction
的调用者。
自动迁移
代码更改。 在数据库已经部署和使用了一段时间之后,有时候需要将新值与表(实体)相关联。
由于关系模型的原因,数据库中的实体可以通过添加新表并将这些新表与实体相关联来获得与它们相关联的值。
但是,这并不总是理想的,因为无论何时需要查询实体的值,都需要执行连接。
为了帮助,sqlite-net支持自动迁移。
细节
当调用CreateTable
时,表格会自动迁移。 如果该表已经存在,则查询其元数据并将其与传递给CreateTable
的类的结构进行比较。 如果两个结构不同,那么表格会自动迁移以匹配代码。
自动迁移目前只支持添加新列。 如果您的类具有与表中的列没有关联的新属性,则会执行alter table ... add column
命令以使数据库保持最新状态。 这些新列不会有默认值,因此将为null
。
不支持的其他迁移包括删除列,更改列的类型和重命名列。 如果有需求,可以添加这些迁移。