Share via


Android での ADO.NET の使用

Xamarin には、Android で使用でき、使い慣れた ADO.NET に似た構文を使って公開できる SQLite データベースのサポートが組み込まれています。 これらの API を使用するには、SQLite によって処理される SQL ステートメント (CREATE TABLEINSERTSELECT ステートメントなど) を記述する必要があります。

アセンブリ参照

ADO.NET 経由で SQLite へのアクセスを使用するには、次に示すように、Android プロジェクトに System.Data および Mono.Data.Sqlite 参照を追加する必要があります。

[参照] > [参照の編集...] を右クリックし、必要なアセンブリをクリックして選択します。

Mono.Data.Sqlite について

Mono.Data.Sqlite.SqliteConnection クラスを使って空のデータベース ファイルを作成し、データベースに対して SQL 命令を実行するために使用できる SqliteCommand オブジェクトをインスタンス化します。

空のデータベースの作成 – 有効な (つまり、書き込み可能な) ファイル パスを使用して、CreateFile メソッドを呼び出します。 このメソッドを呼び出す前にファイルが既に存在するかどうかを確認する必要があります。そうしないと、新しい (空の) データベースが古いものの上に作成され、古いファイル内のデータが失われます。 Mono.Data.Sqlite.SqliteConnection.CreateFile (dbPath);dbPath 変数は、このドキュメントで前述した規則に従って決定する必要があります。

データベース接続の作成 – SQLite データベース ファイルが作成された後、データにアクセスするための接続オブジェクトを作成できます。 接続は、次に示すように、Data Source=file_path の形式を取る接続文字列で構成されます。

var connection = new SqliteConnection ("Data Source=" + dbPath);
connection.Open();
// do stuff
connection.Close();

前述のように、異なるスレッド間で接続を再利用しないでください。 不明な場合は、必要に応じて接続を作成し、完了したら閉じます。しかし、これは必要以上に頻繁に行うことに注意してください。

データベース コマンドの作成と実行 – 接続ができたら、それに対して任意の SQL コマンドを実行できます。 次のコードは、実行中の CREATE TABLE ステートメントを示しています。

using (var command = connection.CreateCommand ()) {
    command.CommandText = "CREATE TABLE [Items] ([_id] int, [Symbol] ntext, [Name] ntext);";
    var rowcount = command.ExecuteNonQuery ();
}

データベースに対して SQL を直接実行するときは、既に存在するテーブルの作成を試行するなど、無効な要求を行わないように通常の予防措置を講じる必要があります。 SqliteExceptionSQLite エラー テーブル [項目] が既に存在する などの が発生しないように、データベースの構造を追跡します。

基本的なデータ アクセス

このドキュメントの DataAccess_Basic サンプル コードは、Android で実行するときは次のようになります。

Android ADO.NET sample

次のコードは、単純な SQLite 操作を実行する方法を示しており、結果がアプリケーションのメイン ウィンドウにテキストとして表示されます。

次の名前空間を含める必要があります。

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

次のコード サンプルは、データベース全体の相互作用を示しています。

  1. データベース ファイルを作成する
  2. データの挿入
  3. データのクエリ

これらの操作は通常、コード全体で複数の場所に示されます。たとえば、アプリケーションの初回起動時にデータベース ファイルとテーブルを作成し、アプリの個々の画面でデータの読み取りと書き込みを実行できます。 次の例では、単一のメソッドにグループ化されています。

public static SqliteConnection connection;
public static string DoSomeDataAccess ()
{
    // determine the path for the database file
    string dbPath = Path.Combine (
        Environment.GetFolderPath (Environment.SpecialFolder.Personal),
        "adodemo.db3");

    bool exists = File.Exists (dbPath);

    if (!exists) {
        Console.WriteLine("Creating database");
        // Need to create the database before seeding it with some data
        Mono.Data.Sqlite.SqliteConnection.CreateFile (dbPath);
        connection = new SqliteConnection ("Data Source=" + dbPath);

        var commands = new[] {
            "CREATE TABLE [Items] (_id ntext, Symbol ntext);",
            "INSERT INTO [Items] ([_id], [Symbol]) VALUES ('1', 'AAPL')",
            "INSERT INTO [Items] ([_id], [Symbol]) VALUES ('2', 'GOOG')",
            "INSERT INTO [Items] ([_id], [Symbol]) VALUES ('3', 'MSFT')"
        };
        // Open the database connection and create table with data
        connection.Open ();
        foreach (var command in commands) {
            using (var c = connection.CreateCommand ()) {
                c.CommandText = command;
                var rowcount = c.ExecuteNonQuery ();
                Console.WriteLine("\tExecuted " + command);
            }
        }
    } else {
        Console.WriteLine("Database already exists");
        // Open connection to existing database file
        connection = new SqliteConnection ("Data Source=" + dbPath);
        connection.Open ();
    }

    // query the database to prove data was inserted!
    using (var contents = connection.CreateCommand ()) {
        contents.CommandText = "SELECT [_id], [Symbol] from [Items]";
        var r = contents.ExecuteReader ();
        Console.WriteLine("Reading data");
        while (r.Read ())
            Console.WriteLine("\tKey={0}; Value={1}",
                              r ["_id"].ToString (),
                              r ["Symbol"].ToString ());
    }
    connection.Close ();
}

より複雑なクエリ

SQLite では任意の SQL コマンドをデータに対して実行できるため、任意の CREATEINSERTUPDATEDELETE、または SELECT ステートメントを実行できます。 SQLite でサポートされている SQL コマンドについては、SQLite Web サイトで確認できます。 SQL ステートメントは、SqliteCommand オブジェクトで次の 3 つのメソッドのいずれかを使用して実行されます。

  • ExecuteNonQuery – 通常、テーブルの作成またはデータの挿入に使用されます。 一部の操作の戻り値は、影響を受ける行の数です。それ以外の場合は -1 です。

  • ExecuteReader – 行のコレクションを SqlDataReader として返す必要がある場合に使用されます。

  • ExecuteScalar – 単一の値 (集計など) を取得します。

EXECUTENONQUERY

INSERTUPDATEDELETE ステートメントからは、影響を受ける行の数が返されます。 他のすべての SQL ステートメントからは -1 が返されます。

using (var c = connection.CreateCommand ()) {
    c.CommandText = "INSERT INTO [Items] ([_id], [Symbol]) VALUES ('1', 'APPL')";
    var rowcount = c.ExecuteNonQuery (); // rowcount will be 1
}

EXECUTEREADER

次のメソッドは、SELECT ステートメントの WHERE 句を示しています。 コードでは完全な SQL ステートメントが作成されるため、文字列を囲む引用符 (') などの予約文字をエスケープする際には注意が必要です。

public static string MoreComplexQuery ()
{
    var output = "";
    output += "\nComplex query example: ";
    string dbPath = Path.Combine (
        Environment.GetFolderPath (Environment.SpecialFolder.Personal), "ormdemo.db3");

    connection = new SqliteConnection ("Data Source=" + dbPath);
    connection.Open ();
    using (var contents = connection.CreateCommand ()) {
        contents.CommandText = "SELECT * FROM [Items] WHERE Symbol = 'MSFT'";
        var r = contents.ExecuteReader ();
        output += "\nReading data";
        while (r.Read ())
            output += String.Format ("\n\tKey={0}; Value={1}",
                    r ["_id"].ToString (),
                    r ["Symbol"].ToString ());
    }
    connection.Close ();

    return output;
}

ExecuteReader メソッドが SqliteDataReader オブジェクトを返します。 この例に示す Read メソッドに加え、他にも次のような便利なプロパティがあります。

  • RowsAffected – クエリの影響を受ける行の数。

  • HasRows – 行が返されたかどうか。

EXECUTESCALAR

これは、単一の値 (集計など) を返す SELECT ステートメントに使用します。

using (var contents = connection.CreateCommand ()) {
    contents.CommandText = "SELECT COUNT(*) FROM [Items] WHERE Symbol <> 'MSFT'";
    var i = contents.ExecuteScalar ();
}

ExecuteScalar メソッドの戻り値の型は object です。データベース クエリに応じて結果をキャストする必要があります。 結果は、COUNT クエリからの整数、または単一列の SELECT クエリの文字列である場合があります。 これは、リーダー オブジェクトまたは影響を受ける行数を返す他の Execute メソッドとは異なることに注意してください。