diff --git a/src/ImageProcessor.Web/Caching/CachedImage.cs b/src/ImageProcessor.Web/Caching/CachedImage.cs index bc7ef15b7..41241cb1b 100644 --- a/src/ImageProcessor.Web/Caching/CachedImage.cs +++ b/src/ImageProcessor.Web/Caching/CachedImage.cs @@ -9,6 +9,9 @@ namespace ImageProcessor.Web.Caching { #region Using using System; + + using SQLite; + #endregion /// @@ -16,28 +19,14 @@ namespace ImageProcessor.Web.Caching /// internal sealed class CachedImage { + //[PrimaryKey, AutoIncrement] + //public int Id { get; set; } + /// - /// Initializes a new instance of the class. + /// Gets or sets the key identifying the cached image. /// - /// - /// The value of the cached image. - /// - /// - /// The max age of the cached image. - /// - /// - /// The last write time of the cached image. - /// - /// - /// The expires time. - /// - public CachedImage(string path, int maxAge, DateTime lastWriteTimeUtc, DateTime expiresTimeUtc) - { - this.Path = path; - this.MaxAge = maxAge; - this.LastWriteTimeUtc = lastWriteTimeUtc; - this.ExpiresUtc = expiresTimeUtc; - } + [PrimaryKey] + internal string Key { get; set; } /// /// Gets or sets the value of the cached image. diff --git a/src/ImageProcessor.Web/Caching/DiskCache.cs b/src/ImageProcessor.Web/Caching/DiskCache.cs index 33d48d19f..6a1f1b841 100644 --- a/src/ImageProcessor.Web/Caching/DiskCache.cs +++ b/src/ImageProcessor.Web/Caching/DiskCache.cs @@ -227,7 +227,15 @@ namespace ImageProcessor.Web.Caching { string key = Path.GetFileNameWithoutExtension(this.CachedPath); DateTime expires = DateTime.UtcNow.AddDays(MaxFileCachedDuration).ToUniversalTime(); - CachedImage cachedImage = new CachedImage(this.CachedPath, MaxFileCachedDuration, lastWriteTimeUtc, expires); + CachedImage cachedImage = new CachedImage + { + Key = key, + Path = this.CachedPath, + MaxAge = MaxFileCachedDuration, + LastWriteTimeUtc = lastWriteTimeUtc, + ExpiresUtc = expires + }; + await PersistantDictionary.Instance.AddAsync(key, cachedImage); } diff --git a/src/ImageProcessor.Web/Caching/PersistantDictionary.cs b/src/ImageProcessor.Web/Caching/PersistantDictionary.cs index cd868f03c..644d74364 100644 --- a/src/ImageProcessor.Web/Caching/PersistantDictionary.cs +++ b/src/ImageProcessor.Web/Caching/PersistantDictionary.cs @@ -130,7 +130,7 @@ namespace ImageProcessor.Web.Caching return await SQLContext.RemoveImageAsync(key); } - return await SQLContext.AddImageAsync(key, cachedImage); + return await SQLContext.AddImageAsync(cachedImage); } catch { diff --git a/src/ImageProcessor.Web/Caching/SQLContext.cs b/src/ImageProcessor.Web/Caching/SQLContext.cs index 22c2c70d6..1f5be5475 100644 --- a/src/ImageProcessor.Web/Caching/SQLContext.cs +++ b/src/ImageProcessor.Web/Caching/SQLContext.cs @@ -8,14 +8,17 @@ namespace ImageProcessor.Web.Caching { #region Using + using System; using System.Collections.Generic; - using System.Data.SQLite; using System.IO; using System.Threading.Tasks; using System.Web.Hosting; using ImageProcessor.Web.Config; using ImageProcessor.Web.Helpers; + + using SQLite; + #endregion /// @@ -37,57 +40,44 @@ namespace ImageProcessor.Web.Caching /// /// The connection string. /// - private static readonly string ConnectionString = string.Format("Data Source={0};Version=3;", IndexLocation); + private static readonly string ConnectionString = IndexLocation; #endregion #region Methods #region Internal + /// /// Creates the database if it doesn't already exist. /// internal static void CreateDatabase() { - if (!File.Exists(IndexLocation)) + try { - string absolutePath = HostingEnvironment.MapPath(VirtualCachePath); - - if (absolutePath != null) + if (!File.Exists(IndexLocation)) { - DirectoryInfo directoryInfo = new DirectoryInfo(absolutePath); + string absolutePath = HostingEnvironment.MapPath(VirtualCachePath); - if (!directoryInfo.Exists) + if (absolutePath != null) { - // Create the directory. - Directory.CreateDirectory(absolutePath); - } - } - - SQLiteConnection.CreateFile(IndexLocation); - - using (SQLiteConnection connection = new SQLiteConnection(ConnectionString)) - { - connection.Open(); + DirectoryInfo directoryInfo = new DirectoryInfo(absolutePath); - using (SQLiteTransaction transaction = connection.BeginTransaction()) - { - using (SQLiteCommand command = new SQLiteCommand(connection)) + if (!directoryInfo.Exists) { - command.CommandText = @"CREATE TABLE names - (Key TEXT, - Path TEXT, - MaxAge INTEGER, - LastWriteTimeUtc TEXT, - ExpiresUtc TEXT, - PRIMARY KEY (Key), - UNIQUE (Path));"; - - command.ExecuteNonQuery(); + // Create the directory. + Directory.CreateDirectory(absolutePath); } + } - transaction.Commit(); + using (SQLiteConnection connection = new SQLiteConnection(IndexLocation)) + { + connection.CreateTable(); } } } + catch (Exception ex) + { + throw ex; + } } /// @@ -104,25 +94,11 @@ namespace ImageProcessor.Web.Caching { using (SQLiteConnection connection = new SQLiteConnection(ConnectionString)) { - connection.Open(); + List images = connection.Query("SELECT * FROM CachedImage"); - using (SQLiteCommand command = new SQLiteCommand(connection)) + foreach (CachedImage cachedImage in images) { - command.CommandText = "SELECT * FROM names;"; - - SQLiteDataReader reader = command.ExecuteReader(); - - while (reader.Read()) - { - string key = reader["Key"].ToString(); - CachedImage image = new CachedImage( - reader["Path"].ToString(), - int.Parse(reader["MaxAge"].ToString()), - DateTime.Parse(reader["LastWriteTimeUtc"].ToString()).ToUniversalTime(), - DateTime.Parse(reader["ExpiresUtc"].ToString()).ToUniversalTime()); - - dictionary.Add(key, image); - } + dictionary.Add(cachedImage.Key, cachedImage); } } @@ -137,19 +113,16 @@ namespace ImageProcessor.Web.Caching /// /// Adds a cached image to the database. /// - /// - /// The key for the cached image. - /// /// /// The cached image to add. /// /// /// The true if the addition of the cached image is added; otherwise, false. /// - internal static async Task AddImageAsync(string key, CachedImage image) + internal static async Task AddImageAsync(CachedImage image) { // Create Action delegate for AddImage. - return await TaskHelpers.Run(() => AddImage(key, image)); + return await TaskHelpers.Run(() => AddImage(image)); } /// @@ -169,48 +142,28 @@ namespace ImageProcessor.Web.Caching #endregion #region Private + /// /// Adds a cached image to the database. /// - /// - /// The key for the cached image. - /// /// /// The cached image to add. /// /// /// The true if the addition of the cached image is added; otherwise, false. /// - private static bool AddImage(string key, CachedImage image) + private static bool AddImage(CachedImage image) { try { - using (SQLiteConnection connection = new SQLiteConnection(ConnectionString)) - { - connection.Open(); + SQLiteConnection connection = new SQLiteConnection(ConnectionString); - using (SQLiteTransaction transaction = connection.BeginTransaction()) + connection.RunInTransaction(() => { - using (SQLiteCommand command = new SQLiteCommand(connection)) - { - command.CommandText = "INSERT INTO names VALUES(?, ?, ?, ?, ?)"; - - SQLiteParameter[] parameters = new[] - { - new SQLiteParameter("Key", key), - new SQLiteParameter("Path", image.Path), - new SQLiteParameter("MaxAge", image.MaxAge), - new SQLiteParameter("LastWriteTimeUtc", image.LastWriteTimeUtc), - new SQLiteParameter("ExpiresUtc", image.ExpiresUtc) - }; - - command.Parameters.AddRange(parameters); - command.ExecuteNonQuery(); - } - - transaction.Commit(); - } - } + // Database calls inside the transaction + connection.Insert(image); + connection.Dispose(); + }); return true; } @@ -233,22 +186,14 @@ namespace ImageProcessor.Web.Caching { try { - using (SQLiteConnection connection = new SQLiteConnection(ConnectionString)) - { - connection.Open(); + SQLiteConnection connection = new SQLiteConnection(ConnectionString); - using (SQLiteTransaction transaction = connection.BeginTransaction()) - { - using (SQLiteCommand command = new SQLiteCommand(connection)) - { - command.CommandText = "DELETE FROM names WHERE key = @searchParam;"; - command.Parameters.Add(new SQLiteParameter("searchParam", key)); - command.ExecuteNonQuery(); - } - - transaction.Commit(); - } - } + connection.RunInTransaction(() => + { + // Database calls inside the transaction + connection.Delete(key); + connection.Dispose(); + }); return true; } diff --git a/src/ImageProcessor.Web/ImageProcessor.Web.csproj b/src/ImageProcessor.Web/ImageProcessor.Web.csproj index 21ce0661c..60e5b6ed6 100644 --- a/src/ImageProcessor.Web/ImageProcessor.Web.csproj +++ b/src/ImageProcessor.Web/ImageProcessor.Web.csproj @@ -18,7 +18,7 @@ full false bin\Debug\ - DEBUG;TRACE + TRACE;DEBUG;USE_CSHARP_SQLITE prompt 4 @@ -66,6 +66,12 @@ MinimumRecommendedRules.ruleset + + ..\packages\Csharp-Sqlite.3.7.7.1\lib\net40\Community.CsharpSqlite.dll + + + ..\packages\Csharp-Sqlite.3.7.7.1\lib\net40\Community.CsharpSqlite.SQLiteClient.dll + ..\packages\Microsoft.Bcl.Async.1.0.14-rc\lib\net40\Microsoft.Threading.Tasks.dll @@ -78,10 +84,6 @@ - - False - ..\packages\SQLitex64.1.0.66\lib\32\System.Data.SQLite.DLL - @@ -108,6 +110,8 @@ + + diff --git a/src/ImageProcessor.Web/SQLite.cs.REMOVED.git-id b/src/ImageProcessor.Web/SQLite.cs.REMOVED.git-id new file mode 100644 index 000000000..ee7e14fe9 --- /dev/null +++ b/src/ImageProcessor.Web/SQLite.cs.REMOVED.git-id @@ -0,0 +1 @@ +ce0491dcbe39702bf25fb616f76e1b149f670688 \ No newline at end of file diff --git a/src/ImageProcessor.Web/SQLiteAsync.cs b/src/ImageProcessor.Web/SQLiteAsync.cs new file mode 100644 index 000000000..b4cf34e07 --- /dev/null +++ b/src/ImageProcessor.Web/SQLiteAsync.cs @@ -0,0 +1,486 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; + +namespace SQLite +{ + public partial class SQLiteAsyncConnection + { + SQLiteConnectionString _connectionString; + + public SQLiteAsyncConnection (string databasePath, bool storeDateTimeAsTicks = false) + { + _connectionString = new SQLiteConnectionString (databasePath, storeDateTimeAsTicks); + } + + SQLiteConnectionWithLock GetConnection () + { + return SQLiteConnectionPool.Shared.GetConnection (_connectionString); + } + + public Task CreateTableAsync () + where T : new () + { + return CreateTablesAsync (typeof (T)); + } + + public Task CreateTablesAsync () + where T : new () + where T2 : new () + { + return CreateTablesAsync (typeof (T), typeof (T2)); + } + + public Task CreateTablesAsync () + where T : new () + where T2 : new () + where T3 : new () + { + return CreateTablesAsync (typeof (T), typeof (T2), typeof (T3)); + } + + public Task CreateTablesAsync () + where T : new () + where T2 : new () + where T3 : new () + where T4 : new () + { + return CreateTablesAsync (typeof (T), typeof (T2), typeof (T3), typeof (T4)); + } + + public Task CreateTablesAsync () + where T : new () + where T2 : new () + where T3 : new () + where T4 : new () + where T5 : new () + { + return CreateTablesAsync (typeof (T), typeof (T2), typeof (T3), typeof (T4), typeof (T5)); + } + + public Task CreateTablesAsync (params Type[] types) + { + return Task.Factory.StartNew (() => { + CreateTablesResult result = new CreateTablesResult (); + var conn = GetConnection (); + using (conn.Lock ()) { + foreach (Type type in types) { + int aResult = conn.CreateTable (type); + result.Results[type] = aResult; + } + } + return result; + }); + } + + public Task DropTableAsync () + where T : new () + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.DropTable (); + } + }); + } + + public Task InsertAsync (object item) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Insert (item); + } + }); + } + + public Task UpdateAsync (object item) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Update (item); + } + }); + } + + public Task DeleteAsync (object item) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Delete (item); + } + }); + } + + public Task GetAsync(object pk) + where T : new() + { + return Task.Factory.StartNew(() => + { + var conn = GetConnection(); + using (conn.Lock()) + { + return conn.Get(pk); + } + }); + } + + public Task FindAsync (object pk) + where T : new () + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Find (pk); + } + }); + } + + public Task GetAsync (Expression> predicate) + where T : new() + { + return Task.Factory.StartNew(() => + { + var conn = GetConnection(); + using (conn.Lock()) + { + return conn.Get (predicate); + } + }); + } + + public Task FindAsync (Expression> predicate) + where T : new () + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Find (predicate); + } + }); + } + + public Task ExecuteAsync (string query, params object[] args) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Execute (query, args); + } + }); + } + + public Task InsertAllAsync (IEnumerable items) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + 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) instead.")] + public Task RunInTransactionAsync (Action action) + { + return Task.Factory.StartNew (() => { + var conn = this.GetConnection (); + using (conn.Lock ()) { + conn.BeginTransaction (); + try { + action (this); + conn.Commit (); + } + catch (Exception) { + conn.Rollback (); + throw; + } + } + }); + } + + public Task RunInTransactionAsync(Action action) + { + return Task.Factory.StartNew(() => + { + var conn = this.GetConnection(); + using (conn.Lock()) + { + conn.BeginTransaction(); + try + { + action(conn); + conn.Commit(); + } + catch (Exception) + { + conn.Rollback(); + throw; + } + } + }); + } + + public AsyncTableQuery Table () + where T : new () + { + // + // 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. + // + var conn = GetConnection (); + return new AsyncTableQuery (conn.Table ()); + } + + public Task ExecuteScalarAsync (string sql, params object[] args) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + var command = conn.CreateCommand (sql, args); + return command.ExecuteScalar (); + } + }); + } + + public Task> QueryAsync (string sql, params object[] args) + where T : new () + { + return Task>.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Query (sql, args); + } + }); + } + } + + // + // TODO: Bind to AsyncConnection.GetConnection instead so that delayed + // execution can still work after a Pool.Reset. + // + public class AsyncTableQuery + where T : new () + { + TableQuery _innerQuery; + + public AsyncTableQuery (TableQuery innerQuery) + { + _innerQuery = innerQuery; + } + + public AsyncTableQuery Where (Expression> predExpr) + { + return new AsyncTableQuery (_innerQuery.Where (predExpr)); + } + + public AsyncTableQuery Skip (int n) + { + return new AsyncTableQuery (_innerQuery.Skip (n)); + } + + public AsyncTableQuery Take (int n) + { + return new AsyncTableQuery (_innerQuery.Take (n)); + } + + public AsyncTableQuery OrderBy (Expression> orderExpr) + { + return new AsyncTableQuery (_innerQuery.OrderBy (orderExpr)); + } + + public AsyncTableQuery OrderByDescending (Expression> orderExpr) + { + return new AsyncTableQuery (_innerQuery.OrderByDescending (orderExpr)); + } + + public Task> ToListAsync () + { + return Task.Factory.StartNew (() => { + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { + return _innerQuery.ToList (); + } + }); + } + + public Task CountAsync () + { + return Task.Factory.StartNew (() => { + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { + return _innerQuery.Count (); + } + }); + } + + public Task ElementAtAsync (int index) + { + return Task.Factory.StartNew (() => { + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { + return _innerQuery.ElementAt (index); + } + }); + } + + public Task FirstAsync () + { + return Task.Factory.StartNew(() => { + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { + return _innerQuery.First (); + } + }); + } + + public Task FirstOrDefaultAsync () + { + return Task.Factory.StartNew(() => { + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { + return _innerQuery.FirstOrDefault (); + } + }); + } + } + + public class CreateTablesResult + { + public Dictionary Results { get; private set; } + + internal CreateTablesResult () + { + this.Results = new Dictionary (); + } + } + + class SQLiteConnectionPool + { + class Entry + { + public SQLiteConnectionString ConnectionString { get; private set; } + public SQLiteConnectionWithLock Connection { get; private set; } + + public Entry (SQLiteConnectionString connectionString) + { + ConnectionString = connectionString; + Connection = new SQLiteConnectionWithLock (connectionString); + } + + public void OnApplicationSuspended () + { + Connection.Dispose (); + Connection = null; + } + } + + readonly Dictionary _entries = new Dictionary (); + readonly object _entriesLock = new object (); + + static readonly SQLiteConnectionPool _shared = new SQLiteConnectionPool (); + + /// + /// Gets the singleton instance of the connection tool. + /// + public static SQLiteConnectionPool Shared + { + get + { + return _shared; + } + } + + public SQLiteConnectionWithLock GetConnection (SQLiteConnectionString connectionString) + { + lock (_entriesLock) { + Entry entry; + string key = connectionString.ConnectionString; + + if (!_entries.TryGetValue (key, out entry)) { + entry = new Entry (connectionString); + _entries[key] = entry; + } + + return entry.Connection; + } + } + + /// + /// Closes all connections managed by this pool. + /// + public void Reset () + { + lock (_entriesLock) { + foreach (var entry in _entries.Values) { + entry.OnApplicationSuspended (); + } + _entries.Clear (); + } + } + + /// + /// Call this method when the application is suspended. + /// + /// Behaviour here is to close any open connections. + public void ApplicationSuspended () + { + Reset (); + } + } + + class SQLiteConnectionWithLock : SQLiteConnection + { + readonly object _lockPoint = new object (); + + public SQLiteConnectionWithLock (SQLiteConnectionString connectionString) + : base (connectionString.DatabasePath, connectionString.StoreDateTimeAsTicks) + { + } + + public IDisposable Lock () + { + return new LockWrapper (_lockPoint); + } + + private class LockWrapper : IDisposable + { + object _lockPoint; + + public LockWrapper (object lockPoint) + { + _lockPoint = lockPoint; + Monitor.Enter (_lockPoint); + } + + public void Dispose () + { + Monitor.Exit (_lockPoint); + } + } + } +} + diff --git a/src/ImageProcessor.Web/packages.config b/src/ImageProcessor.Web/packages.config index 58ea5f418..c3bf2d679 100644 --- a/src/ImageProcessor.Web/packages.config +++ b/src/ImageProcessor.Web/packages.config @@ -1,7 +1,8 @@  + - + \ No newline at end of file diff --git a/src/Test/Test/Web.config b/src/Test/Test/Web.config index f6e8b95f0..09f93bfb9 100644 --- a/src/Test/Test/Web.config +++ b/src/Test/Test/Web.config @@ -4,84 +4,84 @@ http://go.microsoft.com/fwlink/?LinkId=152368 --> - - - -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/packages/Csharp-Sqlite.3.7.7.1/Csharp-Sqlite.3.7.7.1.nupkg.REMOVED.git-id b/src/packages/Csharp-Sqlite.3.7.7.1/Csharp-Sqlite.3.7.7.1.nupkg.REMOVED.git-id new file mode 100644 index 000000000..873e6cddd --- /dev/null +++ b/src/packages/Csharp-Sqlite.3.7.7.1/Csharp-Sqlite.3.7.7.1.nupkg.REMOVED.git-id @@ -0,0 +1 @@ +81fffff68e71d82a09d8c6a345ce69410f351786 \ No newline at end of file diff --git a/src/packages/Csharp-Sqlite.3.7.7.1/Csharp-Sqlite.3.7.7.1.nuspec b/src/packages/Csharp-Sqlite.3.7.7.1/Csharp-Sqlite.3.7.7.1.nuspec new file mode 100644 index 000000000..574462183 --- /dev/null +++ b/src/packages/Csharp-Sqlite.3.7.7.1/Csharp-Sqlite.3.7.7.1.nuspec @@ -0,0 +1,21 @@ + + + + Csharp-Sqlite + 3.7.7.1 + C#-SqLite Unofficial Package + noah.hart + noah.hart + http://code.google.com/p/csharp-sqlite/ + false + C#-SQLite is an independent reimplementation of the SQLite software library version 3.7.7.1. + + + + Sqlite + + + + + + \ No newline at end of file diff --git a/src/packages/Csharp-Sqlite.3.7.7.1/lib/net20/Community.CsharpSqlite.SQLiteClient.dll b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net20/Community.CsharpSqlite.SQLiteClient.dll new file mode 100644 index 000000000..471796b1b Binary files /dev/null and b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net20/Community.CsharpSqlite.SQLiteClient.dll differ diff --git a/src/packages/Csharp-Sqlite.3.7.7.1/lib/net20/Community.CsharpSqlite.dll.REMOVED.git-id b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net20/Community.CsharpSqlite.dll.REMOVED.git-id new file mode 100644 index 000000000..cce826f42 --- /dev/null +++ b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net20/Community.CsharpSqlite.dll.REMOVED.git-id @@ -0,0 +1 @@ +703605507a2c2a90fa7b826aaf2cf7c78a7243b7 \ No newline at end of file diff --git a/src/packages/Csharp-Sqlite.3.7.7.1/lib/net35/Community.CsharpSqlite.SQLiteClient.dll b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net35/Community.CsharpSqlite.SQLiteClient.dll new file mode 100644 index 000000000..cb54313fe Binary files /dev/null and b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net35/Community.CsharpSqlite.SQLiteClient.dll differ diff --git a/src/packages/Csharp-Sqlite.3.7.7.1/lib/net35/Community.CsharpSqlite.dll.REMOVED.git-id b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net35/Community.CsharpSqlite.dll.REMOVED.git-id new file mode 100644 index 000000000..75db259e4 --- /dev/null +++ b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net35/Community.CsharpSqlite.dll.REMOVED.git-id @@ -0,0 +1 @@ +2e6a85ddf4ce868ed48de14c2be21ee94f689b78 \ No newline at end of file diff --git a/src/packages/Csharp-Sqlite.3.7.7.1/lib/net40/Community.CsharpSqlite.SQLiteClient.dll b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net40/Community.CsharpSqlite.SQLiteClient.dll new file mode 100644 index 000000000..aba80685c Binary files /dev/null and b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net40/Community.CsharpSqlite.SQLiteClient.dll differ diff --git a/src/packages/Csharp-Sqlite.3.7.7.1/lib/net40/Community.CsharpSqlite.dll.REMOVED.git-id b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net40/Community.CsharpSqlite.dll.REMOVED.git-id new file mode 100644 index 000000000..ecea89996 --- /dev/null +++ b/src/packages/Csharp-Sqlite.3.7.7.1/lib/net40/Community.CsharpSqlite.dll.REMOVED.git-id @@ -0,0 +1 @@ +ab181a987d0059a31c26ee3891a01c40d43019a0 \ No newline at end of file diff --git a/src/packages/SQLitex64.1.0.66/SQLitex64.1.0.66.nupkg.REMOVED.git-id b/src/packages/SQLitex64.1.0.66/SQLitex64.1.0.66.nupkg.REMOVED.git-id deleted file mode 100644 index 6e8c802e1..000000000 --- a/src/packages/SQLitex64.1.0.66/SQLitex64.1.0.66.nupkg.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -aff828512d1afca48fa5d6824429359562199078 \ No newline at end of file diff --git a/src/packages/SQLitex64.1.0.66/SQLitex64.1.0.66.nuspec b/src/packages/SQLitex64.1.0.66/SQLitex64.1.0.66.nuspec deleted file mode 100644 index 2275c52d5..000000000 --- a/src/packages/SQLitex64.1.0.66/SQLitex64.1.0.66.nuspec +++ /dev/null @@ -1,23 +0,0 @@ - - - - SQLitex64 - 1.0.66 - SQLitex64 - Amir Barylko - Amir Barylko - http://www.sqlite.org/ - http://www.sqlite.org/images/sqlite370_banner.gif - false - Provides both (32 and 64 bit) assemblies needed to use SQLite. -The current package only provides 32 bit. - SQLite 64 bit and 32 bit assemblies - - - - SQLite - - - - - \ No newline at end of file diff --git a/src/packages/SQLitex64.1.0.66/lib/32/System.Data.SQLite.DLL.REMOVED.git-id b/src/packages/SQLitex64.1.0.66/lib/32/System.Data.SQLite.DLL.REMOVED.git-id deleted file mode 100644 index f6116a77c..000000000 --- a/src/packages/SQLitex64.1.0.66/lib/32/System.Data.SQLite.DLL.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -aa398bbec1a567de55f984959d200900b794372a \ No newline at end of file diff --git a/src/packages/SQLitex64.1.0.66/lib/64/System.Data.SQLite.DLL.REMOVED.git-id b/src/packages/SQLitex64.1.0.66/lib/64/System.Data.SQLite.DLL.REMOVED.git-id deleted file mode 100644 index acf4e1240..000000000 --- a/src/packages/SQLitex64.1.0.66/lib/64/System.Data.SQLite.DLL.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -6f07d5e7ab41a0f791f07d5407f10edb4b716a02 \ No newline at end of file diff --git a/src/packages/SQLitex64.1.0.66/lib/System.Data.SQLite.DLL.REMOVED.git-id b/src/packages/SQLitex64.1.0.66/lib/System.Data.SQLite.DLL.REMOVED.git-id deleted file mode 100644 index f6116a77c..000000000 --- a/src/packages/SQLitex64.1.0.66/lib/System.Data.SQLite.DLL.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -aa398bbec1a567de55f984959d200900b794372a \ No newline at end of file diff --git a/src/packages/sqlite-net.1.0.7/content/SQLite.cs.REMOVED.git-id b/src/packages/sqlite-net.1.0.7/content/SQLite.cs.REMOVED.git-id new file mode 100644 index 000000000..2dfc5c248 --- /dev/null +++ b/src/packages/sqlite-net.1.0.7/content/SQLite.cs.REMOVED.git-id @@ -0,0 +1 @@ +d2856e3733eb6c7d85057c37ae415e54c8bf2386 \ No newline at end of file diff --git a/src/packages/sqlite-net.1.0.7/content/SQLiteAsync.cs b/src/packages/sqlite-net.1.0.7/content/SQLiteAsync.cs new file mode 100644 index 000000000..b4cf34e07 --- /dev/null +++ b/src/packages/sqlite-net.1.0.7/content/SQLiteAsync.cs @@ -0,0 +1,486 @@ +// +// Copyright (c) 2012 Krueger Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; + +namespace SQLite +{ + public partial class SQLiteAsyncConnection + { + SQLiteConnectionString _connectionString; + + public SQLiteAsyncConnection (string databasePath, bool storeDateTimeAsTicks = false) + { + _connectionString = new SQLiteConnectionString (databasePath, storeDateTimeAsTicks); + } + + SQLiteConnectionWithLock GetConnection () + { + return SQLiteConnectionPool.Shared.GetConnection (_connectionString); + } + + public Task CreateTableAsync () + where T : new () + { + return CreateTablesAsync (typeof (T)); + } + + public Task CreateTablesAsync () + where T : new () + where T2 : new () + { + return CreateTablesAsync (typeof (T), typeof (T2)); + } + + public Task CreateTablesAsync () + where T : new () + where T2 : new () + where T3 : new () + { + return CreateTablesAsync (typeof (T), typeof (T2), typeof (T3)); + } + + public Task CreateTablesAsync () + where T : new () + where T2 : new () + where T3 : new () + where T4 : new () + { + return CreateTablesAsync (typeof (T), typeof (T2), typeof (T3), typeof (T4)); + } + + public Task CreateTablesAsync () + where T : new () + where T2 : new () + where T3 : new () + where T4 : new () + where T5 : new () + { + return CreateTablesAsync (typeof (T), typeof (T2), typeof (T3), typeof (T4), typeof (T5)); + } + + public Task CreateTablesAsync (params Type[] types) + { + return Task.Factory.StartNew (() => { + CreateTablesResult result = new CreateTablesResult (); + var conn = GetConnection (); + using (conn.Lock ()) { + foreach (Type type in types) { + int aResult = conn.CreateTable (type); + result.Results[type] = aResult; + } + } + return result; + }); + } + + public Task DropTableAsync () + where T : new () + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.DropTable (); + } + }); + } + + public Task InsertAsync (object item) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Insert (item); + } + }); + } + + public Task UpdateAsync (object item) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Update (item); + } + }); + } + + public Task DeleteAsync (object item) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Delete (item); + } + }); + } + + public Task GetAsync(object pk) + where T : new() + { + return Task.Factory.StartNew(() => + { + var conn = GetConnection(); + using (conn.Lock()) + { + return conn.Get(pk); + } + }); + } + + public Task FindAsync (object pk) + where T : new () + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Find (pk); + } + }); + } + + public Task GetAsync (Expression> predicate) + where T : new() + { + return Task.Factory.StartNew(() => + { + var conn = GetConnection(); + using (conn.Lock()) + { + return conn.Get (predicate); + } + }); + } + + public Task FindAsync (Expression> predicate) + where T : new () + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Find (predicate); + } + }); + } + + public Task ExecuteAsync (string query, params object[] args) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Execute (query, args); + } + }); + } + + public Task InsertAllAsync (IEnumerable items) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + 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) instead.")] + public Task RunInTransactionAsync (Action action) + { + return Task.Factory.StartNew (() => { + var conn = this.GetConnection (); + using (conn.Lock ()) { + conn.BeginTransaction (); + try { + action (this); + conn.Commit (); + } + catch (Exception) { + conn.Rollback (); + throw; + } + } + }); + } + + public Task RunInTransactionAsync(Action action) + { + return Task.Factory.StartNew(() => + { + var conn = this.GetConnection(); + using (conn.Lock()) + { + conn.BeginTransaction(); + try + { + action(conn); + conn.Commit(); + } + catch (Exception) + { + conn.Rollback(); + throw; + } + } + }); + } + + public AsyncTableQuery Table () + where T : new () + { + // + // 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. + // + var conn = GetConnection (); + return new AsyncTableQuery (conn.Table ()); + } + + public Task ExecuteScalarAsync (string sql, params object[] args) + { + return Task.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + var command = conn.CreateCommand (sql, args); + return command.ExecuteScalar (); + } + }); + } + + public Task> QueryAsync (string sql, params object[] args) + where T : new () + { + return Task>.Factory.StartNew (() => { + var conn = GetConnection (); + using (conn.Lock ()) { + return conn.Query (sql, args); + } + }); + } + } + + // + // TODO: Bind to AsyncConnection.GetConnection instead so that delayed + // execution can still work after a Pool.Reset. + // + public class AsyncTableQuery + where T : new () + { + TableQuery _innerQuery; + + public AsyncTableQuery (TableQuery innerQuery) + { + _innerQuery = innerQuery; + } + + public AsyncTableQuery Where (Expression> predExpr) + { + return new AsyncTableQuery (_innerQuery.Where (predExpr)); + } + + public AsyncTableQuery Skip (int n) + { + return new AsyncTableQuery (_innerQuery.Skip (n)); + } + + public AsyncTableQuery Take (int n) + { + return new AsyncTableQuery (_innerQuery.Take (n)); + } + + public AsyncTableQuery OrderBy (Expression> orderExpr) + { + return new AsyncTableQuery (_innerQuery.OrderBy (orderExpr)); + } + + public AsyncTableQuery OrderByDescending (Expression> orderExpr) + { + return new AsyncTableQuery (_innerQuery.OrderByDescending (orderExpr)); + } + + public Task> ToListAsync () + { + return Task.Factory.StartNew (() => { + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { + return _innerQuery.ToList (); + } + }); + } + + public Task CountAsync () + { + return Task.Factory.StartNew (() => { + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { + return _innerQuery.Count (); + } + }); + } + + public Task ElementAtAsync (int index) + { + return Task.Factory.StartNew (() => { + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { + return _innerQuery.ElementAt (index); + } + }); + } + + public Task FirstAsync () + { + return Task.Factory.StartNew(() => { + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { + return _innerQuery.First (); + } + }); + } + + public Task FirstOrDefaultAsync () + { + return Task.Factory.StartNew(() => { + using (((SQLiteConnectionWithLock)_innerQuery.Connection).Lock ()) { + return _innerQuery.FirstOrDefault (); + } + }); + } + } + + public class CreateTablesResult + { + public Dictionary Results { get; private set; } + + internal CreateTablesResult () + { + this.Results = new Dictionary (); + } + } + + class SQLiteConnectionPool + { + class Entry + { + public SQLiteConnectionString ConnectionString { get; private set; } + public SQLiteConnectionWithLock Connection { get; private set; } + + public Entry (SQLiteConnectionString connectionString) + { + ConnectionString = connectionString; + Connection = new SQLiteConnectionWithLock (connectionString); + } + + public void OnApplicationSuspended () + { + Connection.Dispose (); + Connection = null; + } + } + + readonly Dictionary _entries = new Dictionary (); + readonly object _entriesLock = new object (); + + static readonly SQLiteConnectionPool _shared = new SQLiteConnectionPool (); + + /// + /// Gets the singleton instance of the connection tool. + /// + public static SQLiteConnectionPool Shared + { + get + { + return _shared; + } + } + + public SQLiteConnectionWithLock GetConnection (SQLiteConnectionString connectionString) + { + lock (_entriesLock) { + Entry entry; + string key = connectionString.ConnectionString; + + if (!_entries.TryGetValue (key, out entry)) { + entry = new Entry (connectionString); + _entries[key] = entry; + } + + return entry.Connection; + } + } + + /// + /// Closes all connections managed by this pool. + /// + public void Reset () + { + lock (_entriesLock) { + foreach (var entry in _entries.Values) { + entry.OnApplicationSuspended (); + } + _entries.Clear (); + } + } + + /// + /// Call this method when the application is suspended. + /// + /// Behaviour here is to close any open connections. + public void ApplicationSuspended () + { + Reset (); + } + } + + class SQLiteConnectionWithLock : SQLiteConnection + { + readonly object _lockPoint = new object (); + + public SQLiteConnectionWithLock (SQLiteConnectionString connectionString) + : base (connectionString.DatabasePath, connectionString.StoreDateTimeAsTicks) + { + } + + public IDisposable Lock () + { + return new LockWrapper (_lockPoint); + } + + private class LockWrapper : IDisposable + { + object _lockPoint; + + public LockWrapper (object lockPoint) + { + _lockPoint = lockPoint; + Monitor.Enter (_lockPoint); + } + + public void Dispose () + { + Monitor.Exit (_lockPoint); + } + } + } +} + diff --git a/src/packages/sqlite-net.1.0.7/sqlite-net.1.0.7.nupkg b/src/packages/sqlite-net.1.0.7/sqlite-net.1.0.7.nupkg new file mode 100644 index 000000000..64dd2824f Binary files /dev/null and b/src/packages/sqlite-net.1.0.7/sqlite-net.1.0.7.nupkg differ diff --git a/src/packages/sqlite-net.1.0.7/sqlite-net.1.0.7.nuspec b/src/packages/sqlite-net.1.0.7/sqlite-net.1.0.7.nuspec new file mode 100644 index 000000000..ad44185a8 --- /dev/null +++ b/src/packages/sqlite-net.1.0.7/sqlite-net.1.0.7.nuspec @@ -0,0 +1,20 @@ + + + + sqlite-net + 1.0.7 + sqlite-net + Frank Krueger + Frank Krueger + https://github.com/praeclarum/sqlite-net/blob/master/license.md + https://github.com/praeclarum/sqlite-net + false + sqlite-net is an open source, minimal library to allow .NET and Mono applications to store data in SQLite databases. It is written in C# 3.0 and is meant to be simply compiled in with your projects. It was first designed to work with MonoTouch on the iPhone, but should work in any other CLI environment. + A .NET client library to access SQLite embedded database files in a LINQ manner. + v1.0.7: Update with commits through 06-FEB-2013. + + + sqlite sql monotouch database metro winrt + + + \ No newline at end of file