@ -34,64 +34,67 @@ namespace SQLite
{
{
SQLiteConnectionString _ connectionString ;
SQLiteConnectionString _ connectionString ;
public SQLiteAsyncConnection ( string databasePath , bool storeDateTimeAsTicks = false )
public SQLiteAsyncConnection ( string databasePath , bool storeDateTimeAsTicks = false )
{
{
_ connectionString = new SQLiteConnectionString ( databasePath , storeDateTimeAsTicks ) ;
_ connectionString = new SQLiteConnectionString ( databasePath , storeDateTimeAsTicks ) ;
}
}
SQLiteConnectionWithLock GetConnection ( )
SQLiteConnectionWithLock GetConnection ( )
{
{
return SQLiteConnectionPool . Shared . GetConnection ( _ connectionString ) ;
return SQLiteConnectionPool . Shared . GetConnection ( _ connectionString ) ;
}
}
public Task < CreateTablesResult > CreateTableAsync < T > ( )
public Task < CreateTablesResult > CreateTableAsync < T > ( )
where T : new ( )
where T : new ( )
{
{
return CreateTablesAsync ( typeof ( T ) ) ;
return CreateTablesAsync ( typeof ( T ) ) ;
}
}
public Task < CreateTablesResult > CreateTablesAsync < T , T2 > ( )
public Task < CreateTablesResult > CreateTablesAsync < T , T2 > ( )
where T : new ( )
where T : new ( )
where T2 : new ( )
where T2 : new ( )
{
{
return CreateTablesAsync ( typeof ( T ) , typeof ( T2 ) ) ;
return CreateTablesAsync ( typeof ( T ) , typeof ( T2 ) ) ;
}
}
public Task < CreateTablesResult > CreateTablesAsync < T , T2 , T3 > ( )
public Task < CreateTablesResult > CreateTablesAsync < T , T2 , T3 > ( )
where T : new ( )
where T : new ( )
where T2 : new ( )
where T2 : new ( )
where T3 : new ( )
where T3 : new ( )
{
{
return CreateTablesAsync ( typeof ( T ) , typeof ( T2 ) , typeof ( T3 ) ) ;
return CreateTablesAsync ( typeof ( T ) , typeof ( T2 ) , typeof ( T3 ) ) ;
}
}
public Task < CreateTablesResult > CreateTablesAsync < T , T2 , T3 , T4 > ( )
public Task < CreateTablesResult > CreateTablesAsync < T , T2 , T3 , T4 > ( )
where T : new ( )
where T : new ( )
where T2 : new ( )
where T2 : new ( )
where T3 : new ( )
where T3 : new ( )
where T4 : new ( )
where T4 : new ( )
{
{
return CreateTablesAsync ( typeof ( T ) , typeof ( T2 ) , typeof ( T3 ) , typeof ( T4 ) ) ;
return CreateTablesAsync ( typeof ( T ) , typeof ( T2 ) , typeof ( T3 ) , typeof ( T4 ) ) ;
}
}
public Task < CreateTablesResult > CreateTablesAsync < T , T2 , T3 , T4 , T5 > ( )
public Task < CreateTablesResult > CreateTablesAsync < T , T2 , T3 , T4 , T5 > ( )
where T : new ( )
where T : new ( )
where T2 : new ( )
where T2 : new ( )
where T3 : new ( )
where T3 : new ( )
where T4 : new ( )
where T4 : new ( )
where T5 : new ( )
where T5 : new ( )
{
{
return CreateTablesAsync ( typeof ( T ) , typeof ( T2 ) , typeof ( T3 ) , typeof ( T4 ) , typeof ( T5 ) ) ;
return CreateTablesAsync ( typeof ( T ) , typeof ( T2 ) , typeof ( T3 ) , typeof ( T4 ) , typeof ( T5 ) ) ;
}
}
public Task < CreateTablesResult > CreateTablesAsync ( params Type [ ] types )
public Task < CreateTablesResult > CreateTablesAsync ( params Type [ ] types )
{
return Task . Factory . StartNew ( ( ) = >
{
CreateTablesResult result = new CreateTablesResult ( ) ;
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) )
{
foreach ( Type type in types )
{
{
return Task . Factory . StartNew ( ( ) = > {
int aResult = conn . CreateTable ( type ) ;
CreateTablesResult result = new CreateTablesResult ( ) ;
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) ) {
foreach ( Type type in types ) {
int aResult = conn . CreateTable ( type ) ;
result . Results [ type ] = aResult ;
result . Results [ type ] = aResult ;
}
}
}
}
@ -99,43 +102,51 @@ namespace SQLite
} ) ;
} ) ;
}
}
public Task < int > DropTableAsync < T > ( )
public Task < int > DropTableAsync < T > ( )
where T : new ( )
where T : new ( )
{
{
return Task . Factory . StartNew ( ( ) = > {
return Task . Factory . StartNew ( ( ) = >
var conn = GetConnection ( ) ;
{
using ( conn . Lock ( ) ) {
var conn = GetConnection ( ) ;
return conn . DropTable < T > ( ) ;
using ( conn . Lock ( ) )
{
return conn . DropTable < T > ( ) ;
}
}
} ) ;
} ) ;
}
}
public Task < int > InsertAsync ( object item )
public Task < int > InsertAsync ( object item )
{
return Task . Factory . StartNew ( ( ) = >
{
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) )
{
{
return Task . Factory . StartNew ( ( ) = > {
return conn . Insert ( item ) ;
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) ) {
return conn . Insert ( item ) ;
}
}
} ) ;
} ) ;
}
}
public Task < int > UpdateAsync ( object item )
public Task < int > UpdateAsync ( object item )
{
return Task . Factory . StartNew ( ( ) = >
{
{
return Task . Factory . StartNew ( ( ) = > {
var conn = GetConnection ( ) ;
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) )
using ( conn . Lock ( ) ) {
{
return conn . Update ( item ) ;
return conn . Update ( item ) ;
}
}
} ) ;
} ) ;
}
}
public Task < int > DeleteAsync ( object item )
public Task < int > DeleteAsync ( object item )
{
return Task . Factory . StartNew ( ( ) = >
{
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) )
{
{
return Task . Factory . StartNew ( ( ) = > {
return conn . Delete ( item ) ;
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) ) {
return conn . Delete ( item ) ;
}
}
} ) ;
} ) ;
}
}
@ -153,18 +164,20 @@ namespace SQLite
} ) ;
} ) ;
}
}
public Task < T > FindAsync < T > ( object pk )
public Task < T > FindAsync < T > ( object pk )
where T : new ( )
where T : new ( )
{
return Task . Factory . StartNew ( ( ) = >
{
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) )
{
{
return Task . Factory . StartNew ( ( ) = > {
return conn . Find < T > ( pk ) ;
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) ) {
return conn . Find < T > ( pk ) ;
}
}
} ) ;
} ) ;
}
}
public Task < T > GetAsync < T > ( Expression < Func < T , bool > > predicate )
public Task < T > GetAsync < T > ( Expression < Func < T , bool > > predicate )
where T : new ( )
where T : new ( )
{
{
return Task . Factory . StartNew ( ( ) = >
return Task . Factory . StartNew ( ( ) = >
@ -172,55 +185,65 @@ namespace SQLite
var conn = GetConnection ( ) ;
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) )
using ( conn . Lock ( ) )
{
{
return conn . Get < T > ( predicate ) ;
return conn . Get < T > ( predicate ) ;
}
}
} ) ;
} ) ;
}
}
public Task < T > FindAsync < T > ( Expression < Func < T , bool > > predicate )
public Task < T > FindAsync < T > ( Expression < Func < T , bool > > predicate )
where T : new ( )
where T : new ( )
{
return Task . Factory . StartNew ( ( ) = >
{
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) )
{
{
return Task . Factory . StartNew ( ( ) = > {
return conn . Find < T > ( predicate ) ;
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) ) {
return conn . Find < T > ( predicate ) ;
}
}
} ) ;
} ) ;
}
}
public Task < int > ExecuteAsync ( string query , params object [ ] args )
public Task < int > ExecuteAsync ( string query , params object [ ] args )
{
return Task < int > . Factory . StartNew ( ( ) = >
{
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) )
{
{
return Task < int > . Factory . StartNew ( ( ) = > {
return conn . Execute ( query , args ) ;
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) ) {
return conn . Execute ( query , args ) ;
}
}
} ) ;
} ) ;
}
}
public Task < int > InsertAllAsync ( IEnumerable items )
public Task < int > InsertAllAsync ( IEnumerable items )
{
{
return Task . Factory . StartNew ( ( ) = > {
return Task . Factory . StartNew ( ( ) = >
var conn = GetConnection ( ) ;
{
using ( conn . Lock ( ) ) {
var conn = GetConnection ( ) ;
return conn . InsertAll ( items ) ;
using ( conn . Lock ( ) )
{
return conn . InsertAll ( items ) ;
}
}
} ) ;
} ) ;
}
}
[Obsolete("Will cause a deadlock if any call in action ends up in a different thread. Use RunInTransactionAsync(Action<SQLiteConnection>) instead.")]
[Obsolete("Will cause a deadlock if any call in action ends up in a different thread. Use RunInTransactionAsync(Action<SQLiteConnection>) instead.")]
public Task RunInTransactionAsync ( Action < SQLiteAsyncConnection > action )
public Task RunInTransactionAsync ( Action < SQLiteAsyncConnection > action )
{
{
return Task . Factory . StartNew ( ( ) = > {
return Task . Factory . StartNew ( ( ) = >
var conn = this . GetConnection ( ) ;
{
using ( conn . Lock ( ) ) {
var conn = this . GetConnection ( ) ;
conn . BeginTransaction ( ) ;
using ( conn . Lock ( ) )
try {
{
action ( this ) ;
conn . BeginTransaction ( ) ;
conn . Commit ( ) ;
try
}
{
catch ( Exception ) {
action ( this ) ;
conn . Rollback ( ) ;
conn . Commit ( ) ;
}
catch ( Exception )
{
conn . Rollback ( ) ;
throw ;
throw ;
}
}
}
}
@ -249,35 +272,39 @@ namespace SQLite
} ) ;
} ) ;
}
}
public AsyncTableQuery < T > Table < T > ( )
public AsyncTableQuery < T > Table < T > ( )
where T : new ( )
where T : new ( )
{
{
//
//
// This isn't async as the underlying connection doesn't go out to the database
// This isn't async as the underlying connection doesn't go out to the database
// until the query is performed. The Async methods are on the query iteself.
// until the query is performed. The Async methods are on the query iteself.
//
//
var conn = GetConnection ( ) ;
var conn = GetConnection ( ) ;
return new AsyncTableQuery < T > ( conn . Table < T > ( ) ) ;
return new AsyncTableQuery < T > ( conn . Table < T > ( ) ) ;
}
}
public Task < T > ExecuteScalarAsync < T > ( string sql , params object [ ] args )
public Task < T > ExecuteScalarAsync < T > ( string sql , params object [ ] args )
{
return Task < T > . Factory . StartNew ( ( ) = >
{
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) )
{
{
return Task < T > . Factory . StartNew ( ( ) = > {
var command = conn . CreateCommand ( sql , args ) ;
var conn = GetConnection ( ) ;
return command . ExecuteScalar < T > ( ) ;
using ( conn . Lock ( ) ) {
var command = conn . CreateCommand ( sql , args ) ;
return command . ExecuteScalar < T > ( ) ;
}
}
} ) ;
} ) ;
}
}
public Task < List < T > > QueryAsync < T > ( string sql , params object [ ] args )
public Task < List < T > > QueryAsync < T > ( string sql , params object [ ] args )
where T : new ( )
where T : new ( )
{
return Task < List < T > > . Factory . StartNew ( ( ) = >
{
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) )
{
{
return Task < List < T > > . Factory . StartNew ( ( ) = > {
return conn . Query < T > ( sql , args ) ;
var conn = GetConnection ( ) ;
using ( conn . Lock ( ) ) {
return conn . Query < T > ( sql , args ) ;
}
}
} ) ;
} ) ;
}
}
@ -288,81 +315,91 @@ namespace SQLite
// execution can still work after a Pool.Reset.
// execution can still work after a Pool.Reset.
//
//
public class AsyncTableQuery < T >
public class AsyncTableQuery < T >
where T : new ( )
where T : new ( )
{
{
TableQuery < T > _ innerQuery ;
TableQuery < T > _ innerQuery ;
public AsyncTableQuery ( TableQuery < T > innerQuery )
public AsyncTableQuery ( TableQuery < T > innerQuery )
{
{
_ innerQuery = innerQuery ;
_ innerQuery = innerQuery ;
}
}
public AsyncTableQuery < T > Where ( Expression < Func < T , bool > > predExpr )
public AsyncTableQuery < T > Where ( Expression < Func < T , bool > > predExpr )
{
{
return new AsyncTableQuery < T > ( _ innerQuery . Where ( predExpr ) ) ;
return new AsyncTableQuery < T > ( _ innerQuery . Where ( predExpr ) ) ;
}
}
public AsyncTableQuery < T > Skip ( int n )
public AsyncTableQuery < T > Skip ( int n )
{
{
return new AsyncTableQuery < T > ( _ innerQuery . Skip ( n ) ) ;
return new AsyncTableQuery < T > ( _ innerQuery . Skip ( n ) ) ;
}
}
public AsyncTableQuery < T > Take ( int n )
public AsyncTableQuery < T > Take ( int n )
{
{
return new AsyncTableQuery < T > ( _ innerQuery . Take ( n ) ) ;
return new AsyncTableQuery < T > ( _ innerQuery . Take ( n ) ) ;
}
}
public AsyncTableQuery < T > OrderBy < U > ( Expression < Func < T , U > > orderExpr )
public AsyncTableQuery < T > OrderBy < U > ( Expression < Func < T , U > > orderExpr )
{
{
return new AsyncTableQuery < T > ( _ innerQuery . OrderBy < U > ( orderExpr ) ) ;
return new AsyncTableQuery < T > ( _ innerQuery . OrderBy < U > ( orderExpr ) ) ;
}
}
public AsyncTableQuery < T > OrderByDescending < U > ( Expression < Func < T , U > > orderExpr )
public AsyncTableQuery < T > OrderByDescending < U > ( Expression < Func < T , U > > orderExpr )
{
{
return new AsyncTableQuery < T > ( _ innerQuery . OrderByDescending < U > ( orderExpr ) ) ;
return new AsyncTableQuery < T > ( _ innerQuery . OrderByDescending < U > ( orderExpr ) ) ;
}
}
public Task < List < T > > ToListAsync ( )
public Task < List < T > > ToListAsync ( )
{
return Task . Factory . StartNew ( ( ) = >
{
{
return Task . Factory . StartNew ( ( ) = > {
using ( ( ( SQLiteConnectionWithLock ) _ innerQuery . Connection ) . Lock ( ) )
using ( ( ( SQLiteConnectionWithLock ) _ innerQuery . Connection ) . Lock ( ) ) {
{
return _ innerQuery . ToList ( ) ;
return _ innerQuery . ToList ( ) ;
}
}
} ) ;
} ) ;
}
}
public Task < int > CountAsync ( )
public Task < int > CountAsync ( )
{
return Task . Factory . StartNew ( ( ) = >
{
{
return Task . Factory . StartNew ( ( ) = > {
using ( ( ( SQLiteConnectionWithLock ) _ innerQuery . Connection ) . Lock ( ) )
using ( ( ( SQLiteConnectionWithLock ) _ innerQuery . Connection ) . Lock ( ) ) {
{
return _ innerQuery . Count ( ) ;
return _ innerQuery . Count ( ) ;
}
}
} ) ;
} ) ;
}
}
public Task < T > ElementAtAsync ( int index )
public Task < T > ElementAtAsync ( int index )
{
return Task . Factory . StartNew ( ( ) = >
{
{
return Task . Factory . StartNew ( ( ) = > {
using ( ( ( SQLiteConnectionWithLock ) _ innerQuery . Connection ) . Lock ( ) )
using ( ( ( SQLiteConnectionWithLock ) _ innerQuery . Connection ) . Lock ( ) ) {
{
return _ innerQuery . ElementAt ( index ) ;
return _ innerQuery . ElementAt ( index ) ;
}
}
} ) ;
} ) ;
}
}
public Task < T > FirstAsync ( )
public Task < T > FirstAsync ( )
{
return Task < T > . Factory . StartNew ( ( ) = >
{
using ( ( ( SQLiteConnectionWithLock ) _ innerQuery . Connection ) . Lock ( ) )
{
{
return Task < T > . Factory . StartNew ( ( ) = > {
return _ innerQuery . First ( ) ;
using ( ( ( SQLiteConnectionWithLock ) _ innerQuery . Connection ) . Lock ( ) ) {
return _ innerQuery . First ( ) ;
}
}
} ) ;
} ) ;
}
}
public Task < T > FirstOrDefaultAsync ( )
public Task < T > FirstOrDefaultAsync ( )
{
{
return Task < T > . Factory . StartNew ( ( ) = > {
return Task < T > . Factory . StartNew ( ( ) = >
using ( ( ( SQLiteConnectionWithLock ) _ innerQuery . Connection ) . Lock ( ) ) {
{
return _ innerQuery . FirstOrDefault ( ) ;
using ( ( ( SQLiteConnectionWithLock ) _ innerQuery . Connection ) . Lock ( ) )
{
return _ innerQuery . FirstOrDefault ( ) ;
}
}
} ) ;
} ) ;
}
}
@ -372,9 +409,9 @@ namespace SQLite
{
{
public Dictionary < Type , int > Results { get ; private set ; }
public Dictionary < Type , int > Results { get ; private set ; }
internal CreateTablesResult ( )
internal CreateTablesResult ( )
{
{
this . Results = new Dictionary < Type , int > ( ) ;
this . Results = new Dictionary < Type , int > ( ) ;
}
}
}
}
@ -385,23 +422,23 @@ namespace SQLite
public SQLiteConnectionString ConnectionString { get ; private set ; }
public SQLiteConnectionString ConnectionString { get ; private set ; }
public SQLiteConnectionWithLock Connection { get ; private set ; }
public SQLiteConnectionWithLock Connection { get ; private set ; }
public Entry ( SQLiteConnectionString connectionString )
public Entry ( SQLiteConnectionString connectionString )
{
{
ConnectionString = connectionString ;
ConnectionString = connectionString ;
Connection = new SQLiteConnectionWithLock ( connectionString ) ;
Connection = new SQLiteConnectionWithLock ( connectionString ) ;
}
}
public void OnApplicationSuspended ( )
public void OnApplicationSuspended ( )
{
{
Connection . Dispose ( ) ;
Connection . Dispose ( ) ;
Connection = null ;
Connection = null ;
}
}
}
}
readonly Dictionary < string , Entry > _ entries = new Dictionary < string , Entry > ( ) ;
readonly Dictionary < string , Entry > _ entries = new Dictionary < string , Entry > ( ) ;
readonly object _ entriesLock = new object ( ) ;
readonly object _ entriesLock = new object ( ) ;
static readonly SQLiteConnectionPool _ shared = new SQLiteConnectionPool ( ) ;
static readonly SQLiteConnectionPool _ shared = new SQLiteConnectionPool ( ) ;
/// <summary>
/// <summary>
/// Gets the singleton instance of the connection tool.
/// Gets the singleton instance of the connection tool.
@ -414,14 +451,16 @@ namespace SQLite
}
}
}
}
public SQLiteConnectionWithLock GetConnection ( SQLiteConnectionString connectionString )
public SQLiteConnectionWithLock GetConnection ( SQLiteConnectionString connectionString )
{
lock ( _ entriesLock )
{
{
lock ( _ entriesLock ) {
Entry entry ;
Entry entry ;
string key = connectionString . ConnectionString ;
string key = connectionString . ConnectionString ;
if ( ! _ entries . TryGetValue ( key , out entry ) ) {
if ( ! _ entries . TryGetValue ( key , out entry ) )
entry = new Entry ( connectionString ) ;
{
entry = new Entry ( connectionString ) ;
_ entries [ key ] = entry ;
_ entries [ key ] = entry ;
}
}
@ -432,13 +471,15 @@ namespace SQLite
/// <summary>
/// <summary>
/// Closes all connections managed by this pool.
/// Closes all connections managed by this pool.
/// </summary>
/// </summary>
public void Reset ( )
public void Reset ( )
{
lock ( _ entriesLock )
{
foreach ( var entry in _ entries . Values )
{
{
lock ( _ entriesLock ) {
entry . OnApplicationSuspended ( ) ;
foreach ( var entry in _ entries . Values ) {
entry . OnApplicationSuspended ( ) ;
}
}
_ entries . Clear ( ) ;
_ entries . Clear ( ) ;
}
}
}
}
@ -446,39 +487,39 @@ namespace SQLite
/// Call this method when the application is suspended.
/// Call this method when the application is suspended.
/// </summary>
/// </summary>
/// <remarks>Behaviour here is to close any open connections.</remarks>
/// <remarks>Behaviour here is to close any open connections.</remarks>
public void ApplicationSuspended ( )
public void ApplicationSuspended ( )
{
{
Reset ( ) ;
Reset ( ) ;
}
}
}
}
class SQLiteConnectionWithLock : SQLiteConnection
class SQLiteConnectionWithLock : SQLiteConnection
{
{
readonly object _l ockPoint = new object ( ) ;
readonly object _l ockPoint = new object ( ) ;
public SQLiteConnectionWithLock ( SQLiteConnectionString connectionString )
public SQLiteConnectionWithLock ( SQLiteConnectionString connectionString )
: base ( connectionString . DatabasePath , connectionString . StoreDateTimeAsTicks )
: base ( connectionString . DatabasePath , connectionString . StoreDateTimeAsTicks )
{
{
}
}
public IDisposable Lock ( )
public IDisposable Lock ( )
{
{
return new LockWrapper ( _l ockPoint ) ;
return new LockWrapper ( _l ockPoint ) ;
}
}
private class LockWrapper : IDisposable
private class LockWrapper : IDisposable
{
{
object _l ockPoint ;
object _l ockPoint ;
public LockWrapper ( object lockPoint )
public LockWrapper ( object lockPoint )
{
{
_l ockPoint = lockPoint ;
_l ockPoint = lockPoint ;
Monitor . Enter ( _l ockPoint ) ;
Monitor . Enter ( _l ockPoint ) ;
}
}
public void Dispose ( )
public void Dispose ( )
{
{
Monitor . Exit ( _l ockPoint ) ;
Monitor . Exit ( _l ockPoint ) ;
}
}
}
}
}
}