SQLite.Net-PCL奇怪的选择行为

时间:2014-11-07 09:58:39

标签: c# sqlite xamarin cross-platform portable-class-library

使用任何NuGet包:SQLite.Net-PCL - Win32平台,SQLite.Net-PCL - XamarinIOS平台或SQLite.Net-PCL XamarinAndroid平台我一般都遇到选择问题。特别是每当我从LINQ或原始SQL中的数据库中选择时,我都会回到看似包含默认值的对象。

这是一个示例控制台应用程序来演示我的问题:

using System;
using System.Linq;
using SQLite.Net;
using SQLite.Net.Platform.Win32;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            // Open a connection to the database
            using (var database = new SQLiteConnection(new SQLitePlatformWin32(), "db.db"))
            {
                // Create a simple table
                database.CreateTable<Entity>();

                // Add a simple record to it each time we start the application
                database.Insert(new Entity { Data = Guid.NewGuid().ToString(), BoolData = true, IntData = 5 });

                Console.WriteLine("---------> Inserted item:");

                // Display all our records
                foreach (var e in database.Table<Entity>())
                {
                    Console.WriteLine(e);
                }

                Console.WriteLine(Environment.NewLine);
                Console.WriteLine("---------> Linq select Ids:");

                // For every record we'll select the Id field - this is not working
                foreach (var e in database.Table<Entity>().Select(e => e.Id))
                {
                    Console.WriteLine(e);
                }

                Console.WriteLine(Environment.NewLine);
                Console.WriteLine("---------> Id by scalar query:");

                // Let's try going after a value explicitly - this is fine
                var r1 = database.ExecuteScalar<int>("SELECT Id FROM Entity WHERE Id == 1");

                Console.WriteLine(r1);
                Console.WriteLine(Environment.NewLine);
                Console.WriteLine("---------> Ids by query:");

                // So lets try going after our Id field from a query - this still dosen't work
                foreach (var e in database.Query<int>("SELECT Id FROM Entity"))
                {
                    Console.WriteLine(e);
                }

                Console.WriteLine(Environment.NewLine);
                Console.WriteLine("---------> Linq select Ids after force to memory:");

                // Now lets try forcing a where to execute before performing the select - this works but it's bad
                foreach (var e in database.Table<Entity>().Where(e => e.IntData == 5).ToList().Select(e => e.Id))
                {
                    Console.WriteLine(e);
                }

                Console.ReadKey();
            }
        }
    }
}

实体只是一个简单的POD:

using SQLite.Net.Attributes;

namespace ConsoleApplication1
{
    public class Entity
    {
        public Entity() { }

        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }

        public string Data { get; set; }

        public int IntData { get; set; }

        public bool BoolData { get; set; }

        public override string ToString()
        {
            return string.Format("Id: {0}, Data: {1}, IntData: {2}, BoolData: {3}", Id, Data, IntData, BoolData);
        }
    }
}

所以我能够让它工作的唯一方法就是先将内存强制放入内存中......在我们可能拥有包含BLOB等的数据的情况下,这是不好的,我们对此不感兴趣。

这种行为是故意还是我错过了什么?

2 个答案:

答案 0 :(得分:0)

嗯它可能返回结果(你的映射对象),无论是否找到记录,或者因为实体类中的字段是非引用类型,它们都采用默认值。在我的应用程序中,我以不同的方式选择记录,也许我做错了(表现明智)但从未遇到过类似的问题。基本上我的查询看起来像

int id = GetID();
using(var connection = Db.getConnection())
{
    var result = connection.Table<Entity>().where(x=> x.id == id).firsOrDefault();
    if(result != null)
    { 
        //record found
    }
    else
    {
        //not found
    }
}

答案 1 :(得分:0)

我通过使用包含我通过SQLIteConnection.Query(“Some SQL query”)方法查询的离散字段的POD类来解决这个问题。其中T是包含感兴趣的字段的特定POD。只要字段名称与SELECT之后列出的字段匹配,就可以映射它们。

我仍然认为这仍然不太理想,因为我们不想创建一堆类来表示每个查询结果。我们可能会对Anonymous Types做些什么,但在运行时可能会很麻烦且费用昂贵。