Giter Club home page Giter Club logo

sqlite-net's Introduction

SQLite-net

[GitHub Action] [Code Coverage Report]

Use one of these packages:

Version Package Description
NuGet Package sqlite-net-pcl .NET Standard Library
NuGet Package with Encryption sqlite-net-sqlcipher With Encryption Support
NuGet Package using P/Invoke sqlite-net-static Special version that uses P/Invokes to platform-provided sqlite3
NuGet Package without a SQLitePCLRaw bundle sqlite-net-base without a SQLitePCLRaw bundle so you can choose your own provider

SQLite-net is an open source, minimal library to allow .NET, .NET Core, and Mono applications to store data in SQLite 3 databases. It was first designed to work with Xamarin.iOS, but has since grown up to work on all the platforms (Xamarin.*, .NET, UWP, Azure, etc.).

SQLite-net was designed as a quick and convenient database layer. Its design follows from these goals:

  • Very easy to integrate with existing projects and runs on all the .NET platforms.

  • Thin wrapper over SQLite that is fast and efficient. (This library should not be the performance bottleneck of your queries.)

  • Very simple methods for executing CRUD operations and queries safely (using parameters) and for retrieving the results of those query in a strongly typed fashion.

  • Works with your data model without forcing you to change your classes. (Contains a small reflection-driven ORM layer.)

NuGet Installation

Install sqlite-net-pcl from NuGet.

Important: You will need to add the NuGet package to both your .NET Standard library project and your platform-dependent app project.

Source Installation

SQLite-net is all contained in 1 file (I know, so cool right?) and is easy to add to your project. Just add SQLite.cs to your project, and you're ready to start creating tables. An asynchronous implementation can be found in SQLiteAsync.cs.

Please Contribute!

This is an open source project that welcomes contributions/suggestions/bug reports from those who use it. If you have any ideas on how to improve the library, please post an issue here on GitHub. Please check out the How to Contribute.

Example Time!

Please consult the Wiki for, ahem, complete documentation.

The library contains simple attributes that you can use to control the construction of tables. In a simple stock program, you might use:

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; }
	[Ignore]
	public string IgnoreField { get; set; }
}

Once you've defined the objects in your model you have a choice of APIs. You can use the "synchronous API" where calls block one at a time, or you can use the "asynchronous API" where calls do not block. You may care to use the asynchronous API for mobile applications in order to increase responsiveness.

Both APIs are explained in the two sections below.

Synchronous API

Once you have defined your entity, you can automatically generate tables in your database by calling CreateTable:

// Get an absolute path to the database file
var databasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MyData.db");

var db = new SQLiteConnection(databasePath);
db.CreateTable<Stock>();
db.CreateTable<Valuation>();

You can insert rows in the database using Insert. If the table contains an auto-incremented primary key, then the value for that key will be available to you after the insert:

public static void AddStock(SQLiteConnection db, string symbol) {
	var stock = new Stock() {
		Symbol = symbol
	};
	db.Insert(stock);
	Console.WriteLine("{0} == {1}", stock.Symbol, stock.Id);
}

Similar methods exist for Update and Delete.

The most straightforward way to query for data is using the Table method. This can take predicates for constraining via WHERE clauses and/or adding ORDER BY clauses:

var query = db.Table<Stock>().Where(v => v.Symbol.StartsWith("A"));

foreach (var stock in query)
	Console.WriteLine("Stock: " + stock.Symbol);

You can also query the database at a low-level using the Query method:

public static IEnumerable<Valuation> QueryValuations (SQLiteConnection db, Stock stock) {
	return db.Query<Valuation> ("select * from Valuation where StockId = ?", stock.Id);
}

The generic parameter to the Query method specifies the type of object to create for each row. It can be one of your table classes, or any other class whose public properties match the column returned by the query. For instance, we could rewrite the above query as:

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);
}

You can perform low-level updates of the database using the Execute method.

Asynchronous API

The asynchronous library uses the Task Parallel Library (TPL). As such, normal use of Task objects, and the async and await keywords will work for you.

Once you have defined your entity, you can automatically generate tables by calling CreateTableAsync:

// Get an absolute path to the database file
var databasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MyData.db");

var db = new SQLiteAsyncConnection(databasePath);

await db.CreateTableAsync<Stock>();

Console.WriteLine("Table created!");

You can insert rows in the database using Insert. If the table contains an auto-incremented primary key, then the value for that key will be available to you after the insert:

var stock = new Stock()
{
	Symbol = "AAPL"
};

await db.InsertAsync(stock);

Console.WriteLine("Auto stock id: {0}", stock.Id);

Similar methods exist for UpdateAsync and DeleteAsync.

Querying for data is most straightforwardly done using the Table method. This will return an AsyncTableQuery instance back, whereupon you can add predicates for constraining via WHERE clauses and/or adding ORDER BY. The database is not physically touched until one of the special retrieval methods - ToListAsync, FirstAsync, or FirstOrDefaultAsync - is called.

var query = db.Table<Stock>().Where(s => s.Symbol.StartsWith("A"));

var result = await query.ToListAsync();

foreach (var s in result)
	Console.WriteLine("Stock: " + s.Symbol);

There are a number of low-level methods available. You can also query the database directly via the QueryAsync method. Over and above the change operations provided by InsertAsync etc you can issue ExecuteAsync methods to change sets of data directly within the database.

Another helpful method is ExecuteScalarAsync. This allows you to return a scalar value from the database easily:

var count = await db.ExecuteScalarAsync<int>("select count(*) from Stock");

Console.WriteLine(string.Format("Found '{0}' stock items.", count));

Manual SQL

sqlite-net is normally used as a light ORM (object-relational-mapper) using the methods CreateTable and Table. However, you can also use it as a convenient way to manually execute queries.

Here is an example of creating a table, inserting into it (with a parameterized command), and querying it without using ORM features.

db.Execute ("create table Stock(Symbol varchar(100) not null)");
db.Execute ("insert into Stock(Symbol) values (?)", "MSFT");
var stocks = db.Query<Stock> ("select * from Stock");

Using SQLCipher

You can use an encrypted database by using the sqlite-net-sqlcipher NuGet package.

The database key is set in the SqliteConnectionString passed to the connection constructor:

var options = new SQLiteConnectionString(databasePath, true,
	key: "password");
var encryptedDb = new SQLiteAsyncConnection(options);

If you need set pragmas to control the encryption, actions can be passed to the connection string:

var options2 = new SQLiteConnectionString (databasePath, true,
	key: "password",
	preKeyAction: db => db.Execute("PRAGMA cipher_default_use_hmac = OFF;"),
	postKeyAction: db => db.Execute ("PRAGMA kdf_iter = 128000;"));
var encryptedDb2 = new SQLiteAsyncConnection (options2);

Thank you!

Thank you to the .NET community for embracing this project, and thank you to all the contributors who have helped to make this great.

Thanks also to Tirza van Dijk (@tirzavdijk) for the great logo!

sqlite-net's People

Contributors

cherron-aptera avatar clancey avatar csm101 avatar damirarh avatar ericsink avatar fstokke avatar geertvanhorrik avatar gtbx avatar heyzooi avatar inforithmics avatar jamesmontemagno avatar jstedfast avatar koush avatar ljw1004 avatar luckyducko avatar mjmeans avatar mkuckert avatar patrikahlenius avatar peterhuene avatar praeclarum avatar pythonic-rainbow avatar rubenv avatar seancross avatar shiena avatar sjlombardo avatar thomaslevesque avatar timheuer avatar tofutim avatar xavierap avatar xperiandri avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sqlite-net's Issues

DateTime as strings

Is there a reason DateTimes are stored as strings rather than ticks? I just converted in my local copy and my main query went from 00.3255005 to 00.0833972, thats a pretty small dataset too. 172 rows with two datetime cols per a row.

Let me know if I'm missing something, otherwise I'll send you a pull request with the change.

Column names not respected in LINQ-like queries

Given this table definition:

[Table("foo")]
public class Foo
{
    [Column("baz")]
    public int Bar { get; set; }
}

With a row in the table with baz = 42, perform this query:

connection.Table<Foo>().Where(f => f.Bar == 42).FirstOrDefault()

Expected results:
The query should return the row with baz = 42.

Actual results:
The return value is always null.

Issue:
The underlying query uses "Bar" for the column name and not "baz".

Offending code (in TableQuery<T>.CompileExpr, line 2108 in SQLite.cs):

return new CompileResult { CommandText = "\"" + mem.Member.Name + "\"" };

The code in question is using the member name (i.e. the "Bar" property name) and not looking up the property's ColumnAttribute Name property.

Workaround:
Use SQLiteConnection.Query<T> and manually specify the column names.

Support for .Contains/.StartsWith/.EndsWith missing

Hi there,

A linq query including a clause like: "...where row.STREET.Contains(street)..." fails with SQLIteException in method Prepare2.

Code not setup to generate SQL Like clauses from .Contains or .StartsWith or .EndsWith. Corrected code in CompileExpr as below.

Hope this helps

Robert

private CompileResult CompileExpr (Expression expr, List<object> queryArgs)
{
if (expr == null) {
    throw new NotSupportedException ("Expression is NULL");
} else if (expr is BinaryExpression) {
    var bin = (BinaryExpression)expr;

    var leftr = CompileExpr (bin.Left, queryArgs);
    var rightr = CompileExpr (bin.Right, queryArgs);

    //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null")
    string text;
    if (leftr.CommandText == "?" && leftr.Value == null)
        text = CompileNullBinaryExpression(bin, rightr);
    else if (rightr.CommandText == "?" && rightr.Value == null)
        text = CompileNullBinaryExpression(bin, leftr);
    else
        text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")";
    return new CompileResult { CommandText = text };
} else if (expr.NodeType == ExpressionType.Call) {

    var call = (MethodCallExpression)expr;
    var args = new CompileResult[call.Arguments.Count];
    var obj = call.Object != null ? CompileExpr (call.Object, queryArgs) : null;

    for (var i = 0; i < args.Length; i++) {
        args [i] = CompileExpr (call.Arguments [i], queryArgs);
    }

    var sqlCall = "";

    if (call.Method.Name == "Like" && args.Length == 2) {
        sqlCall = "(" + args [0].CommandText + " like " + args [1].CommandText + ")";
    } else if (call.Method.Name == "Contains" && args.Length == 2) {
        sqlCall = "(" + args [1].CommandText + " in " + args [0].CommandText + ")";
    } else if (call.Method.Name == "Contains" && args.Length == 1) {
        //sqlCall = "(" + args [0].CommandText + " in " + obj.CommandText + ")";
        sqlCall = "(" + obj.CommandText + "like '%" + args[0].Value + "%')";        //[RSC] Make Linq Contains/StartsWith/EndsWith translate to Sql Like
    } else if (call.Method.Name == "StartsWith" && args.Length == 1)
    {
        sqlCall = "(" + obj.CommandText + "like '" + args[0].Value + "%')";
    } else if (call.Method.Name == "EndsWith" && args.Length == 1)
    {
        sqlCall = "(" + obj.CommandText + "like '%" + args[0].Value + "')";
    }
    else {
        sqlCall = call.Method.Name.ToLower() + "(" + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")";
    }
    return new CompileResult { CommandText = sqlCall };

Windows 8 background task with SQLite

When i create a C# project to host my background task, if i compile it in "AnyCPU" the background task works but if i set it to "x86" it doesn't works.

The problem is that to use SQLite i have to set "x86" mode on the project, so how to use SQLite in a background task project?

Cannot access ApplicationSuspended method

In Metro-style, we need to tell the connection pool that we're suspending. However this method is inaccessible, or rather the class is.

Propose adding a static ApplicationSuspended method to SQLiteAsyncConnection.

Insert not returning autoincremented ID

The insert function does not seem to work as given in the wiki/readme examples. They suggest the function will return an object containing the row values from which the autoincremented ID can be obtained, however when I use it I'm getting back an integer rather than an object which is always 1.

Delete method takes an unnecessary type parameter?

The Delete method requires a type parameter, whereas Update does not. Having to pass the Delete parameter in seems unnecessary as the type is evaluated from the value passed in.

If you remove the , it seems to work fine:

    public int Delete(object obj)
    {
        var map = GetMapping(obj.GetType());
        var pk = map.PK;
        if (pk == null)
        {
            throw new NotSupportedException("Cannot delete " + map.TableName + ": it has no PK");
        }
        var q = string.Format("delete from \"{0}\" where \"{1}\" = ?", map.TableName, pk.Name);
        return Execute(q, pk.GetValue(obj));
    }

nuget and changes

So if I'm using nuget, and make changes... how do I propagate that back to the source? Maybe I should not be using nuget.

NullReferenceException in apps on Windows 8 RTM

I migrate an app from windows 8 RP to RTM.

I didn't have problem on RP but on RTM SQLite throw very often an exception when my app launch.

Here is the exception details:

  System.NullReferenceException was unhandled by user code
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=mscorlib
  StackTrace:
       at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
       at System.Collections.Generic.Dictionary`2.set_Item(TKey key, TValue value)
       at SQLite.SQLiteConnection.GetMapping(Type type) in \SQLite.cs:line 234
       at SQLite.SQLiteConnection.CreateTable(Type ty) in \SQLite.cs:line 308
       at SQLite.SQLiteAsyncConnection.<>c__DisplayClass1.<CreateTablesAsync>b__0() in \SQLiteAsync.cs:line 

94
       at System.Threading.Tasks.Task`1.InnerInvoke()
       at System.Threading.Tasks.Task.Execute()

Can you investigate on it?

StocksTouch sample crash

The sample crashes when you touch "Add" on the AddStockView ViewController. The crash is caused by the TickersSource "ds" being GC'd in the StockView ViewController. The definition "db" should be moved from the ViewDidLoad method to be a class level definition and the problem is solved.

Thanks for your great work with SQLite-Net and sharing it!

LIKE and CASE INSENSITIVE search

var data = "xxxx";

return (from s in me.Table ()
where s.Nombre.ToLowerInvariant().Contains(data )
select s).ToList();

ToLower or ToLowerInvariant

Implement DeleteAll

public int DeleteAll<T>()
{
    var map = GetMapping (typeof (T));
    var query = string.Format("delete from \"{0}\"", map.TableName);
    return Execute (query);
}

enum defined as byte can not be deserialized

This is working:
public enum ColorType {Blue = 1, Red = 2, Green = 4, White = 8 }

This is NOT working:
public enum ColorType : byte {Blue = 1, Red = 2, Green = 4, White = 8 }

ExecuteQuery for unknown # of fields

I have a certain scenario where I generate SQL statements on the fly - the fields inside may vary. Is there anyway I can query for this without building a class ahead of time?

I'm looking for ExecuteQuery() without the .

Async tests do not use proper async/await notation

In the CP, unit tests always succeed if they use async and await. This is a bug in the VS11 CP test runner.

This is a placeholder case for the RP drop. Once RP is released the tests will be re-written to use proper notation.

IgnoreForCreate attribute

Would be great if I could have an entity like this:

class Client
{
string IdClient;

 [IgnoreForCreate]
 string otherDate;

}

So I could do a select with inner join and fill otherDate but not create it into database. It's like a ignore but not for select.

Test "TestGetWithExpression" fails

This test fails.

    [Test]
    public void TestGetWithExpression()
    {
        var db = CreateDb();

        db.Insert (new Product {
            Name = "A",
            Price = 20,
        });

        db.Insert (new Product {
            Name = "B",
            Price = 10,
        });

        db.Insert(new Product
        {
            Name = "C",
            Price = 5,
        });

        Assert.AreEqual (2, db.Table<Product> ().Count ());

        var r = db.Get<Product>(x => x.Price == 10);
        Assert.IsNotNull(r);
        Assert.AreEqual ("A", r.Name);
    }

Will change to assert the count as "3", and assert the name as "B".

Column named cid does not get created

I have tables that have a property/column 'public int cid { get; set; }'. During table creation in the TableMapping method that property has a CanWrite value of 'false' so that column is never added. This works fine on the simulator but not when deployed to the device. This was not a problem up until we upgraded our SQLite class earlier this month.

Example table structure:

public partial class MyClass : BaseSyncable, IDisposable
{
public bool MyBool { get; set;}
public bool MyInt { get; set; }
}

public abstract class BaseSyncable : BaseLocalData where T : new()
{
[Indexed]
public long ServerId { get; set;}
[Indexed]
public SyncState SyncState { get; set;}

public DateTime LastModified { get; set; }
...
}

public abstract class BaseLocalData where T : new()
{
[PrimaryKey, AutoIncrement]
public int cid {get; set;}
...
}

The right way to do prepared statements

How do I use sqlite-net to properly do prepared statements? For a while I was doing

cmd = conn.CreateCommand (....);

cmd.Bind("@var", "some value");
cmd.ExecuteNonQuery();
cmd.Bind("@var", "another value");
cmd.ExecuteNonQuery();

After about 2000 times, there is general badness, because now if you look at the command, there are 2000 bindings! It just adds it to the list. Do I need to somehow clear the Bind? Should it check and replace internally?

FindColumnWithPropertyName fails and crash, why?

In Monotouch, I get this error using SQLite-net:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object
  at SQLite.TableQuery`1[MyApp.MyVocabEntry].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List`1 queryArgs) [0x00520] in /Users/Emanuele/Projects/DictionaryForIPhone/SQLite.cs:2211 

This is the code:

using(SQLiteConnection sqlcon = new SQLiteConnection(dBFilePath))
                {
                        var results=    from s in sqlcon.Table<MyVocabEntry> ()
                            where s.Word == text_to_search
                            select s;
                }

the error is in this lines of SQLite.cs (MonoDevelop stops on the FindColumnWithPropertyName line):

} else if (expr.NodeType == ExpressionType.MemberAccess) {
                var mem = (MemberExpression)expr;

                if (mem.Expression.NodeType == ExpressionType.Parameter) {
                    //
                    // This is a column of our table, output just the column name
                    // Need to translate it if that column name is mapped
                    //
                    var columnName = Table.FindColumnWithPropertyName (mem.Member.Name).Name;
                    return new CompileResult { CommandText = "\"" + columnName + "\"" };

String storage in SQLite

According to the SQLite-net documentation (https://github.com/praeclarum/sqlite-net/wiki/Features), "strings are stored using varchars with a maximum size specified by the MaxLength attribute. If the attribute isn't specified, the max length defaults to 140".

According to the SQLite documentation (http://sqlite.org/datatype3.html), varchars are mapped onto the Text type and numeric arguments are ignored. My understanding of the documentation is that a text column in a SQLite table can be of any length up to the max length limit compiled into the code.

Have I correctly understood the SQLite documentation and is the length specified in SQLite-net therefore not necessary?

Thanks.

Philip

Where queries break with nullable ints

I've got classes that look similar to the following:

public class A
{
[ AutoIncrement, PrimaryKey]
public int ID { get; set; }
public string AddressLine { get; set; }

    [Indexed]
    public int? ClassB { get; set; }
    [Indexed]
    public int? ClassC { get; set; }

}

public class B
{
[ AutoIncrement, PrimaryKey]
public int ID { get; set; }
public string CustomerName { get; set; }
}

public class C
{
[ AutoIncrement, PrimaryKey]
public int ID { get; set; }
public string SupplierName { get; set; }
}

(This is a vastly simplified example just to demonstrate the principle of what I'm trying to achieve).

When the records are created, a new class A has either the ClassB or the ClassC field set to the ID value for the appropriate parent class.

To retrieve the matching class A record for a given class B record, I'm trying to do this:

var query = db.Table().Where(p => p.ClassB == id);

However, when I then try to use that query, e.g. query.Count(), there is an exception because the SQLite-net code cannot cope with the fact that p.ClassB is an int? but id is an int.

I've tried to work around this by changing the query to

p => (p.ClassB.HasValue == true) && ((int)p.ClassB == id))

but that just breaks SQLite-net in a different place :-(.

It looks like the only way I can get this to execute safely is if I use this query:

p => (int)p.ClassB == id

and that appears to work but I'm bit uncertain about it because what does (int)null convert to? I guess at the very least it won't convert to a positive integer, which all of the valid IDs will be, but it doesn't sit well with me.

Thanks.

Philip

Executing a delete without a TableMapping results in failure during close

Maybe I'm missing something but the following will fail during Close on the foreach insertcommand:

    using (var db = new SQLiteConnection("northwind.sqlite"))
    {
        db.Trace = true;
        //db.Table<Employees>(); uncommenting this line allows this to succeed
        var affected = db.Execute("delete from Employees where EmployeeID = ?", 3);
    }

How to use sqlite.net in Windows Phone?

Hello Frank,

If I understand correctly, sqlite.net supports Windows Phone.

The overview of sqlite.net says that It has 0 dependencies aside from
a [http://www.sqlite.org/download.html compiled form of the sqlite3
library].

But I haven't found a dll for Windows Phone there. How can I use
sqlite.net from Windows Phone?

Thanks!

Alexei

CannotOpen on second UPDATE statement in async transaction

Today I've encountered a strange error while executing multiple UPDATE statements inside a single async transaction. On the second statement SQLiteException: CannotOpen is thrown.

I managed to create a minimal test reproducing the issue:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

#if NETFX_CORE
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute;
using TearDown = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestCleanupAttribute;
using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
#else
using NUnit.Framework;
using System.IO;
#endif

namespace SQLite.Tests
{
    public class Settlement
    {
        [PrimaryKey, MaxLength(50)]
        public string DamagedObjectId { get; set; }
        public bool Completed { get; set; }
    }

    public class LocalDataServiceTest
    {
        protected SQLiteAsyncConnection db;

        public LocalDataServiceTest()
        {
#if NETFX_CORE
            string connectionString = "db.sqlite";
#else
            string connectionString = Path.Combine(Path.GetTempPath(), "db.sqlite");
            File.Delete(connectionString);
#endif        
            db = new SQLiteAsyncConnection(connectionString);
        }

        [SetUp]
        public void InitializeDatabase()
        {
            db.CreateTableAsync<Settlement>().Wait();
        }

        [TearDown]
        public void CleanDatabase()
        {
            db.DropTableAsync<Settlement>().Wait();
        }

        [TestFixture]
        public class MarkSettlementsCompleteAsync : LocalDataServiceTest
        {
            [Test]
            public void CompleteMultiple()
            {
                var settlements = new Settlement[]
                {
                    new Settlement
                    {
                        DamagedObjectId = "Id1",
                        Completed = false
                    },
                    new Settlement
                    {
                        DamagedObjectId = "Id2",
                        Completed = false
                    }
                };

                db.InsertAllAsync(settlements).Wait();

                settlements = new Settlement[]
                {
                    new Settlement { DamagedObjectId = "Id1" },
                    new Settlement { DamagedObjectId = "Id2" }
                };

                db.RunInTransactionAsync(tran =>
                {
                    foreach (var settlement in settlements)
                    {
                        tran.Execute("UPDATE Settlement SET Completed = 1 WHERE DamagedObjectId = ?", settlement.DamagedObjectId);
                    }
                }).Wait();
            }
        }
    }
}

The exception is thrown on the second Execute call in the foreach loop.

I can only reproduce the bug in a Metro project. In a .NET project the same code work flawlessly. I am using the lastest version of sqlite3.dll from the SQLite Download Page.

multi-line sqlite statement

Sometimes I have a multi-line statement, for example,

       db.Execute("CREATE TABLE test1 (test); CREATE TABLE test2 (test)");

Seems that only the first statement is processed. Help!

sqlite3.dll remains locked after running the tests

After I run all the tests in the SQLite.csproj project there remains a lock on sqlite3.dll file preventing me from rebuilding or rerunning the tests until I restart Visual Studio. Curiously enough, I don't encounter this problem running the same tests from SQLiteMetroTests.csproj. This is the error I get:

Unable to copy file "C:\Users\Damir\Documents\GitHub\sqlite-net\lib\x86\sqlite3.dll" to "bin\Debug\sqlite3.dll". The process cannot access the file 'bin\Debug\sqlite3.dll' because it is being used by another process.

I'm using Visual Studio 2012 RC built-in test runner with NUnit Test Adapter (Beta 2) v0.92. Is anyone else encountering this issue? Could it be a bug in Visual Studio or the adapter?

Different ENum storage definition

This is more of the feature request, but not sure where to post it:

Add support for different types on Enum storage. For example, they can be stored as int, char or string

SQLiteNet attributes for ENum types

public class EnumCharAffinityAttribute : Attribute  //Stored as char(1)
{
}
public class EnumStringAffinityAttribute : Attribute  //Stored as varchar(50) -> string name of ENum value
{
}
public class EnumInt32AffinityAttribute : Attribute  // stored as integer
{
}

Code Declaration:

public enum PersonType {Child = 'C', Adult = 'A', Senior = 'S'}
public enum PersonAge {ChildAge = 0, AdultAge = 21, SeniorAge = 40}

Sample class declaration:

public class Person
{
public Person () { }
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

[EnumCharAffinity]
public PersonType Type {get; set;}
[EnumInt32Affinity]
public PersonAge Age {get; set;}

}

Make partial classes

I was thinking of how someone might use this and want to augment their own methods, but never alter the core of SQLite-net. If they use the code files or NuGet package for instance, we wouldn't want them to modify those directly (if their goal was to always have the latest). If the core classes were partial classes then I could add SQLite-net to my project and have my own class that adds some specific methods or whatever.

Windows and UTF-8 in TEXT columns

Hi there.

I was having a problem on windows because the data containing UTF-8 characters in a TEXT column was not being stored properly.

I ended up changing the DllImport for BindText to be:
[DllImport("sqlite3", EntryPoint = "sqlite3_bind_text16", CallingConvention=CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern int BindText (IntPtr stmt, int index, string val, int n, IntPtr free);

and this made it work for me. Not sure if you want this change, so I'll leave it up to you.

Thanks!

Invalid Member call for NETFX_CORE

In CompileExpr there is a condition where it might throw NotSupportedException but the use of Member.MemberType is not valid for NETFX_CORE

Virtual Tables using FTS3/FTS4/RTREE

class Page {
  public string Title { get; set; }
  public string Body { get; set; }
}

var db = new SQLiteConnection (...);
db.Execute ("CREATE VIRTUAL TABLE Page USING fts4(Title, Body)");
var pages = db.Query<Page> ("SELECT * FROM Page WHERE Body MATCH ?", "something");

http://www.sqlite.org/fts3.html

Reintroduce Metro-style test project

I think it's worth reintroducing a solution and project that's setup as a VS2012 and Metro-style test project. It's hard for me to gain confidence that the changes work in Metro-style without having to go away and build a Metro-style test project anyway.

Named parameters

I used to use named parameters with System.Data.SQLite. Is this possible with sqlite-net? For example,

                        SqliteCommand cmdInsertFields = conn.CreateCommand();
                        cmdInsertFields.CommandText = string.Format(SQLiteDictCmds.InsertField, this.DbName);

                        SqliteParameter pFieldId = new SqliteParameter("@fieldid");
                        cmdInsertFields.Parameters.Add(pFieldId);
                        SqliteParameter pName = new SqliteParameter("@name");
                        cmdInsertFields.Parameters.Add(pName);
                        SqliteParameter pInternalName = new SqliteParameter("@internalname");
                        cmdInsertFields.Parameters.Add(pInternalName);
                        SqliteParameter pDataType = new SqliteParameter("@datatype");
                        cmdInsertFields.Parameters.Add(pDataType);
                        SqliteParameter pDisplayType = new SqliteParameter("@displaytype");
                        cmdInsertFields.Parameters.Add(pDisplayType);

How do I create a virtual table?

I'd like to create virtual tables using FTS4. Can I do that using sqlite-net - or is some modification necessary?

Thanks,
tim

contains method works only with constants

    [Test]
    public void Contains()
    {
        int n = 20;
        var cq =from i in Enumerable.Range(1, n)
                select new TestObj() {
            Name = i.ToString()
        };

        var db = new TestDb(Path.GetTempFileName());

        db.InsertAll(cq);

        db.Trace = true;

        var tensq = new string[] { "0", "10", "20" };           
        var tens = (from o in db.Table<TestObj>() where tensq.Contains(o.Name) select o).ToList();
        Assert.AreEqual(2, tens.Count);

        var moreq = new string[] { "0", "x", "99", "10", "20", "234324" };          
        var more = (from o in db.Table<TestObj>() where moreq.Contains(o.Name) select o).ToList();
        Assert.AreEqual(2, more.Count);

    }

If the values for "contains" method are fetched dynamically from the database (e.g in case of a many-to-many relation), the query returns error.

How to reproduce:

var moreq2 = moreq.ToList();

var more = (from o in db.Table() where moreq2.Contains(o.Name) select o).ToList();

BeginTransaction/Commit cannot be nested.

The transaction functions exposed by the API simply execute "begin transaction"/"commit"/"rollback". These functions are also understandably called by internal code (e.g. InsertAll).

Unfortunately, this implementation means that

database.BeginTransaction();
for( var i = 0; i < 10000; ++i )
{
    database.InsertAll(...);
}
database.Commit();

will actually create 10,000 transactions, which has both different semantics, and is far slower than what it appears to be doing.

The code should be changed to support nesting of transactions (since SQLite doesn't support it by default) by e.g. keeping a counter of the number of calls to BeginTransaction, and only call Commit when that counter reaches zero. If I, as a user of the API, create a transaction, I expect that further calls into the API will be executed in that transaction.

RunInTransaction documentation

I'd like to add some documentation on correct usage of RunInTransaction methods (both synchronous and asynchronous).

I'm not sure what would be the correct location for it. Currenlty the documentation seems to be in two places: the Wiki pages and the README.mdown file.

What's the preffered location, i.e. where should I put the additional documentation?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.