3

アプリケーションでSqlite.Netを使用していXamarin.Formsます。これまでのところ、オブジェクトが次のようなクラスである場合、オブジェクトのリストを返すのはうまくいきました。

SqliteDatabase.Connection.Query<Customer>("Select * from Customers");

DataSetクエリから動的に同等のものを返したいと思います

SqliteDatabase.Connection.Query("Select * from Customers inner join Calls on Customers.Id=Calls.CustomerId")

DataSet2 番目のクエリから、オブジェクトのリストではなくを返したいと思います。Customersandの列を組み合わせた新しいオブジェクトを作成できることはわかっていCallsますが、データベースにクエリを実行するたびにオブジェクトを作成する必要はありません。

またはを動的に返すことは可能ですDatasetObject?

4

5 に答える 5

4

最終的に、任意のクエリを実行し、行をリスト内の項目として、列を配列内のオブジェクトとして返すメソッドを実際に思いつくことができました。

    public List<object[]> RunSql(string sqlString, bool includeColumnNamesAsFirstRow)
    {
        var lstRes = new List<object[]>();
        SQLitePCL.sqlite3_stmt stQuery = null;
        try
        {
            stQuery = SQLite3.Prepare2(fieldStrikeDatabase.Connection.Handle, sqlString);
            var colLenght = SQLite3.ColumnCount(stQuery);

            if (includeColumnNamesAsFirstRow)
            {
                var obj = new object[colLenght];
                lstRes.Add(obj);
                for (int i = 0; i < colLenght; i++)
                {
                    obj[i] = SQLite3.ColumnName(stQuery, i);
                }
            }

            while (SQLite3.Step(stQuery) == SQLite3.Result.Row)
            {
                var obj = new object[colLenght];
                lstRes.Add(obj);
                for (int i = 0; i < colLenght; i++)
                {
                     var columnType = SQLitePCL.raw.sqlite3_column_decltype(stQuery, i);

                     switch (columnType)
                     {
                         case "text":
                              obj[i] = SQLite3.ColumnString(stQuery, i);
                              break;
                         case "int":
                               obj[i] = SQLite3.ColumnInt(stQuery, i);
                               break;
                         case "real":
                               obj[i] = SQLite3.ColumnDouble(stQuery, i);
                               break;
                         case "blob":
                               obj[i] = SQLite3.ColumnBlob(stQuery, i);
                               break;
                         case "null":
                               obj[i] = null;
                               break;
                      }
                }
            }
            return lstRes;
        }
        catch (Exception)
        {
            return null;
        }
        finally
        {
            if (stQuery != null)
            {
                SQLite3.Finalize(stQuery); 
            }
        }
    }
于 2017-03-24T09:18:31.713 に答える
1

SQLite.NET PCL は、sqlite の .NET ラッパーです。

したがって、クエリよりも LINQ または Lambda で結合を使用して、EF と同様のクエリを実行できます。ラッパーは、sqlite クエリへの変換を処理します。

その後、結合された型または動的型の新しいデータ型を返すことができます。

: 結合は sqlite では直接サポートされていません (詳細)。回避策については、こちらを参照してください。

サンプルコード:

var conn = new SQLiteConnection(sqlitePlatform, "foofoo");
var query = from customer in conn.Table<Customers>().ToList()
            join call in conn.Table<Calls>().ToList()
                         on customer.ID equals call.CustomerId                
            select new { Customer = customer , Calls = call };

ラムダのバージョン:

conn.Table<Customer>().ToList().Join
(conn.Table<Call>().ToList(),
customer => customer.Id,
call => call.CustomerId, 
(customer, call) => new { Customer = customer, Calls = call });
于 2016-08-23T19:59:56.423 に答える
0

@Fabian Monkemoller とは異なり、@User1 のコードをすぐに動作させることができませんでした。これは、null 許容参照型とメソッドの入れ子を利用して、try-catch ブロックからメインコードを分離する修正バージョンです。

     public static object?[][]? ToDataSet(this SQLiteConnection sqlConnection, string query , bool includeColumnNamesAsFirstRow = true)
    {
        var stQuery = SQLite3.Prepare2(sqlConnection.Handle, query );
        var colLength = SQLite3.ColumnCount(stQuery);
        try
        {
            return SelectRows().ToArray();
        }
        catch (Exception e)
        {
            return null;
        }
        finally
        {
            if (stQuery != null)
            {
                SQLite3.Finalize(stQuery);
            }
        }

        IEnumerable<object?[]> SelectRows()
        {
            if (includeColumnNamesAsFirstRow)
            {
                yield return SelectColumnNames(stQuery, colLength).ToArray();
            }

            while (SQLite3.Step(stQuery) == SQLite3.Result.Row)
            {
                yield return SelectColumns(stQuery, colLength).ToArray();
            }

            static IEnumerable<object> SelectColumnNames(SQLitePCL.sqlite3_stmt stQuery, int colLength)
            {
                for (int i = 0; i < colLength; i++)
                {
                    yield return SQLite3.ColumnName(stQuery, i);
                }
            }

            static IEnumerable<object?> SelectColumns(SQLitePCL.sqlite3_stmt stQuery, int colLength)
            {
                for (int i = 0; i < colLength; i++)
                {
                    var x = SQLitePCL.raw.sqlite3_column_decltype(stQuery, i);
                    yield return x switch
                    {
                        "text" => SQLite3.ColumnString(stQuery, i),
                        "integer" => SQLite3.ColumnInt(stQuery, i),
                        "bigint" => SQLite3.ColumnInt64(stQuery, i),
                        "real" => SQLite3.ColumnDouble(stQuery, i),
                        "blob" => SQLite3.ColumnBlob(stQuery, i),
                        "null" => null,
                        _ => throw new Exception($"Unexpected type encountered in for query {stQuery}")
                    };
                }
            }
        }
    }
于 2020-04-15T18:17:16.663 に答える