Xamarin.iOS の System.Data

Xamarin.iOS 8.10 では、Mono.Data.Sqlite.dll ADO.NET プロバイダーを含む System.Data のサポートが追加されています。 サポートには、次のアセンブリの追加が含まれます。

  • System.Data.dll
  • System.Data.Service.Client.dll
  • System.Transactions.dll
  • Mono.Data.Tds.dll
  • Mono.Data.Sqlite.dll

次のプログラムによって Documents/mydb.db3 でデータベースが作成され、データベースが以前に存在しなかった場合は、サンプル データが設定されます。 次に、データベースに対してクエリが実行され、出力が stderr に書き込まれます。

参照の追加

まず、[参照] ノードを右クリックし、[参照の編集...] を選択してから、System.DataMono.Data.Sqlite を選択します。

Adding new references

サンプル コード

次のコードは、埋め込み SQL コマンドを使用してテーブルを作成し、行を挿入する簡単な例を示しています。

using System;
using System.Data;
using System.IO;
using Mono.Data.Sqlite;

class Demo {
    static void Main (string [] args)
    {
        var connection = GetConnection ();
        using (var cmd = connection.CreateCommand ()) {
            connection.Open ();
            cmd.CommandText = "SELECT * FROM People";
            using (var reader = cmd.ExecuteReader ()) {
                while (reader.Read ()) {
                    Console.Error.Write ("(Row ");
                    Write (reader, 0);
                    for (nint i = 1; i < reader.FieldCount; ++i) {
                        Console.Error.Write(" ");
                        Write (reader, i);
                    }
                    Console.Error.WriteLine(")");
                }
            }
            connection.Close ();
        }
    }

    static SqliteConnection GetConnection()
    {
        var documents = Environment.GetFolderPath (
                Environment.SpecialFolder.Personal);
        string db = Path.Combine (documents, "mydb.db3");
        bool exists = File.Exists (db);
        if (!exists)
            SqliteConnection.CreateFile (db);
        var conn = new SqliteConnection("Data Source=" + db);
        if (!exists) {
            var commands = new[] {
            "CREATE TABLE People (PersonID INTEGER NOT NULL, FirstName ntext, LastName ntext)",
            // WARNING: never insert user-entered data with embedded parameter values
            "INSERT INTO People (PersonID, FirstName, LastName) VALUES (1, 'First', 'Last')",
            "INSERT INTO People (PersonID, FirstName, LastName) VALUES (2, 'Dewey', 'Cheatem')",
            "INSERT INTO People (PersonID, FirstName, LastName) VALUES (3, 'And', 'How')",
            };
            conn.Open ();
            foreach (var cmd in commands) {
                using (var c = conn.CreateCommand()) {
                    c.CommandText = cmd;
                    c.CommandType = CommandType.Text;
                    c.ExecuteNonQuery ();
                }
            }
            conn.Close ();
        }
        return conn;
    }

    static void Write(SqliteDataReader reader, int index)
    {
        Console.Error.Write("({0} '{1}')",
                reader.GetName(index),
                reader [index]);
    }
}

重要

上記のコード サンプルで説明したように、SQL コマンドに文字列を埋め込むのは不適切な方法です。これは、コードが SQL インジェクションに対して脆弱になるためです。

コマンド パラメーターの使用

次のコードは、コマンド パラメータを使用して、(テキストに単一アポストロフィのような特殊な SQL 文字が含まれている場合でも) ユーザーが入力したテキストをデータベースに安全に挿入する方法を示しています。

// user input from Textbox control
var fname = fnameTextbox.Text;
var lname = lnameTextbox.Text;
// use command parameters to safely insert into database
using (var addCmd = conn.CreateCommand ()) {
    addCmd.CommandText = "INSERT INTO [People] (PersonID, FirstName, LastName) VALUES (@COL1, @COL2, @COL3)";
    addCmd.CommandType = System.Data.CommandType.Text;
    addCmd.AddParameterWithValue ("@COL1", 1);
    addCmd.AddParameterWithValue ("@COL2", fname);
    addCmd.AddParameterWithValue ("@COL3", lname);
    addCmd.ExecuteNonQuery ();
}

不足している機能

System.DataMono.Data.Sqlite の両方に一部の機能がありません。

System.Data

System.Data.dll に不足している機能は、次のもので構成されます。

Mono.Data.Sqlite

Mono.Data.Sqlite.dll ではソース コードの変更は発生しませんでしたが、Mono.Data.Sqlite.dll によって SQLite 3.5 がバインドされるため、代わりに多くの "ランタイム" の問題を発生させる可能性があります。 一方、iOS 8 には SQLite 3.8.5 が付属しています。 あえて言うなら、2 つのバージョン間でいくつかの変更が行われています。

前のバージョンの iOS には、次のバージョンの SQLite が付属しています。

  • iOS 7 - バージョン 3.7.13。
  • iOS 6 - バージョン 3.7.13。
  • iOS 5 - バージョン 3.7.7。
  • iOS 4 - バージョン 3.6.22。

最も一般的な問題は、データベース スキーマのクエリに関連しているようです。たとえば、Mono.Data.Sqlite.SqliteConnection.GetSchema (DbConnection.GetSchema のオーバーライド) や Mono.Data.Sqlite.SqliteDataReader.GetSchemaTable (DbDataReader.GetSchemaTable のオーバーライド) など、特定のテーブルに存在する列を実行時に決定する場合などです。 つまり、DataTable を使用するものが機能する可能性は低いようです。

データ バインディング

現時点では、データ バインディングはサポートされていません。