give IT a try

プログラミング、リモートワーク、田舎暮らし、音楽、etc.

C#からAccess MDBのパススルークエリ情報を取得するサンプルコード

続いてAccess用のサンプルコードを紹介します。


事前にCOMの「Microsoft Access 11.0 Object Library」みたいなのを参照設定しておきます。
MS AccessがローカルPCにインストールされてある必要があります。


で、こんな感じのコードで情報が取得できます。

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Access;
using dao;

class AccessAgent
{
    //パススルークエリの情報を自作のDTOオブジェクトに詰めて返却するメソッド
    //注) PassThroughQueryが自作のDTOクラス。
    IList<PassThroughQuery> GetPassThroughQueries(string filePath)
    {
        IList<PassThroughQuery> queries = new List<PassThroughQuery>();        
        Application objAccess = new Application();
        Database currentDb = null;
        try
        {
            objAccess.OpenCurrentDatabase(filePath, false, "");
            currentDb = objAccess.CurrentDb();
            foreach (QueryDef queryDef in currentDb.QueryDefs)
            {
                //Connectに何か情報が入っていればきっとパススルークエリ
                if (!string.IsNullOrEmpty(queryDef.Connect))
                {
                    PassThroughQuery query = new PassThroughQuery();
                    queries.Add(query);

                    query.QueryName = queryDef.Name;
                    query.MdbFilePath = filePath;
                    query.QueryString = queryDef.SQL;
                }
            }
        }
        finally
        {
            // 2011.01.29 Accessの開放処理を一部修正
            if (currentDb != null)
            {
                currentDb.Close();
            }
            objAccess.CloseCurrentDatabase();
            objAccess.Quit(AcQuitOption.acQuitSaveNone);
        }
        return queries;
    }
}
2011.01.29 追記

Accessの開放処理について、以前のロジックと新しいロジックを以下のようなテストコードで確認してみました。
確かに違いが出ているようです。

using System;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Access;
using dao;
using NUnit.Framework;

[TestFixture]
public class MyTest
{
    [Test]
    public void currentDbをCloseする場合()
    {
        string filePath = @"c:\temp\test.mdb";
        Application objAccess = new Application();
        Database currentDb = null;
        try
        {
            objAccess.OpenCurrentDatabase(filePath, false, "");
            currentDb = objAccess.CurrentDb();
        }
        finally
        {
            if (currentDb != null)
            {
                currentDb.Close();
            }
            objAccess.CloseCurrentDatabase();
            objAccess.Quit(AcQuitOption.acQuitSaveNone);
        }
        // このAssertは成功する
        Assert.Throws<COMException>(
            delegate { object queryDefs = currentDb.QueryDefs; },
            "Accessは完全に終了していて呼び出しに失敗するはず");
    }

    [Test]
    public void currentDbをCloseしない場合()
    {
        string filePath = @"c:\temp\test.mdb";
        Application objAccess = new Application();
        Database currentDb = null;
        try
        {
            objAccess.OpenCurrentDatabase(filePath, false, "");
            currentDb = objAccess.CurrentDb();
        }
        finally
        {
            objAccess.CurrentDb().Close();
            objAccess.Quit(AcQuitOption.acQuitSaveNone);
        }
        // このAssertは失敗する
        Assert.Throws<COMException>(
            delegate { object queryDefs = currentDb.QueryDefs; },
            "Accessは完全に終了していて呼び出しに失敗するはず");
    }
}