WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

OleDb + JET 用で名前付きパラメータは使えるか?

by WebSurfer 2021年5月16日 12:39

ADO.NET + JET (または ACE) + OleDb プロバイダで Access を操作する場合、この記事の一番下に書いたサンプルコードのように SQL 文に用いるパラメータには疑問符 (?) で指定される位置パラメータマーカーを使用することになっています。そこを名前付きパラメータを使ったらどうなるかという話を書きます。

実行結果1

エラーになると思っていたのですが、そうはならず少なくとも見かけは期待通り動いている例がみられたので、ちょっと調べてみた次第です。

Microsoft のドキュメント「パラメーターおよびパラメーターのデータ型の構成 (ADO.NET)」に概略が書いてありますが、SQL 文をパラメータ化する場合、パラメータのプレースホルダーの構文はデータソースとプロバイダに依存するそうです。

ADO.NET で Access を操作する際、プロバイダには .NET Framework Data Provider for OLE DB を利用するのが普通と思います。

その場合、SQL 文には疑問符 (?) で指定される位置パラメータマーカーを使用するということになっています。Microsoft のドキュメント OleDbCommand.Parameters Property(日本語版は翻訳がアレです)に以下のように書いてあります。

"Remarks: The OLE DB .NET Provider does not support named parameters for passing parameters to an SQL statement or a stored procedure called by an OleDbCommand when CommandType is set to Text. In this case, the question mark (?) placeholder must be used."

"must" は書いてあることが仕様の絶対的要件であることを意味するそうです。

それに反して名前付きパラメータを使ったらどうなるか試してみました。下のコードの INSERT 文で、...VALUES (?, ?) のところを ...VALUES (Info1, Info2) に変えてみます。実行結果は上の画像と同様に問題なしでした。

しかし、...VALUES (Info, Info) とか ...VALUES (a, a) というように同じ名前を使うと、[Info1], [Info2] には最初のパラメータ(下のコード例では "Info1" と名付けた方)に代入した値のみしか INSERT されないという不可解な動きになります。その結果が下の画像です。

実行結果2

個人的には、疑問符 (?) が must ならそれに反することをしたら即エラーにするのが良いと思うのですがどうでしょう? エラーも出さないで不可解な結果になって、それに気が付かないということもあるでしょうから。

以下にこの記事を書くのに使った .NET Framework 4.8 のコンソールアプリのサンプルコードを載せておきます。

using System;
using System.Data.OleDb;

namespace ConsoleAccess
{
    class Program
    {
        static void Main(string[] args)
        {
            var path = @"C:\Users\surfe\...\Access.mdb";
            var connString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path;
            var sqlInsert = "INSERT INTO [XXX] ([Info1], [Info2]) VALUES (?, ?)";

            using (var connection = new OleDbConnection(connString))
            {
                connection.Open();
                using (var command = new OleDbCommand())
                {
                    command.Connection = connection;
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = sqlInsert;
                    
                    // パラメータ名を付けるのは以下のような使い方をする場合必要
                    command.Parameters.Add(new OleDbParameter("Info1", OleDbType.Char));
                    command.Parameters.Add(new OleDbParameter("Info2", OleDbType.Char));
                    
                    // コードの並び順を変えても名前で指定したパラメータに代入される
                    command.Parameters["Info2"].Value = "info2";
                    command.Parameters["Info1"].Value = "info1";

                    var i = command.ExecuteNonQuery();

                    Console.WriteLine($"Affected Rows: {i}");
                }

                int id = -1;
                using (var command = new OleDbCommand("SELECT @@IDENTITY", connection))
                {
                    object obj = command.ExecuteScalar();
                    if (obj != null && obj.GetType() != typeof(DBNull))
                    {
                        id = (int)obj;
                    }
                    Console.WriteLine($"New id: {id}");
                }

                var sqlSelect = "SELECT [ID], [Info1], [Info2] FROM [XXX] WHERE ID = ?";
                using (var command = new OleDbCommand())
                {
                    command.Connection = connection;
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = sqlSelect;

                    command.Parameters.Add(new OleDbParameter("ID", OleDbType.Integer));
                    command.Parameters["ID"].Value = id;

                    using (var reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            Console.WriteLine($"ID: {reader[0]}, " +
                                $"Info1: { reader[1]}, Info2; {reader[2]} ");
                        }
                    }
                }
            }
        }
    }
}

Tags: , ,

ADO.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年3月  >>
252627282912
3456789
10111213141516
17181920212223
24252627282930
31123456

View posts in large calendar