【问题标题】:SQLite.Net-PCL Strange select behaviourSQLite.Net-PCL 奇怪的选择行为
【发布时间】:2014-11-07 09:58:39
【问题描述】:

使用任何 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();
            }
        }
    }
}

Entity 只是一个简单的 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);
        }
    }
}

因此,我能够使其工作的唯一方法是首先将 where 强制放入内存中......在我们可能拥有包含我们不感兴趣的 BLOB 等数据的情况下,这很糟糕。

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

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 这很有效,因为您仍在将对象加载到内存中。我的问题是当我尝试在将对象带入内存之前选择字段时。
      猜你喜欢
      • 1970-01-01
      • 2013-01-29
      • 2014-05-28
      • 1970-01-01
      • 2011-08-19
      • 2013-04-27
      • 2015-07-13
      • 2012-10-17
      • 1970-01-01
      相关资源
      最近更新 更多