WebSurfer's Home

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

Access 2007 の DB を利用するアプリ開発

by WebSurfer 2011年11月8日 22:37

注意 1:
2010, 2013 用のドライバには 32/64-bit 版の両方があります(2007 用は 32-bit のみ)。Visual Studio は 32-bit ですので、ドライバに 64-bit 版を使うと、この記事に書いたような Visual Studio の Access DB への接続はできませんので注意してください。

注意 2:
下にリンクを張ったダウンロードページ「Microsoft Access データベース エンジン 2010 再頒布可能コンポーネント」の「詳細」にある条件に "Jet の全般的な代替としての使用" はできないと書いてあります。一方 Microsoft Access 2010 を使用したデータ プログラミングには JET は非推奨だから ACE を使おうという意味のことが書いてあります。一体どうしろと言うのでしょうね。(汗)

Access 2007 をインストールしていない開発環境でも、Access 2007 データベース(accdb ファイル)を使用するアプリケーションを開発できます。

Microsoft.ACE.OLEDB.12.0 プロバイダの選択

Access 2003 以前で使用されていた JET (Joint Engine Technology) データベースエンジンは、Access 2007 では ACE (Access Connectivity Engine) データベースエンジンに代わったそうです。そのため、ACE データベースエンジン用のドライバが必要になります。

Microsoft ダウンロードセンターの 2007 Office system ドライバ: データ接続コンポーネントから AccessDatabaseEngine.exe をダウンロードして開発マシンにインストールすれば、ACE データベースエンジン用の OLEDB ドライバと ODBC ドライバが利用可能になります。

2019/6/24 追記: Office 2007 がサポートされなくなったためか、上の 2007 用のページはリンク切れとなってしまいました。探しても見つからないので、今現在は 2010 以降用を使うほかなさそうです。2010 用は以下からダウンロードできます。

Microsoft Access データベース エンジン 2010 再頒布可能コンポーネント

(ちなみに、JET 4.0 データベースエンジン用の OLEDB プロバイダ、ODBC ドライバは Windows OS 同梱で提供されているのでインストールは不要だそうです。Jet データベース エンジンを使用するアプリケーションの開発/動作環境 を参照ください)

インストールすると、Visual Studio 2010 を Access 2007 のデータベース(accdb ファイル)に接続できるようになります。

上の画像は、Microsoft が提供しているサンプルデータベース "Northwind 2007.accdb" を Web アプリケーションルート直下の App_Data フォルダにコピーして、Visual Studio 2010 のサーバーエクスプローラーの「接続の追加」メニューから「詳細設定」を開き、"Northwind 2007.accdb" に接続しているところです。

接続できれば、Access 2003 の mdb ファイルと同様に、AccessDataSource や ObjectDataSource を利用して Access 2007 データベース(.accdb ファイル)を操作するアプリケーションを、ウィザードベースで作成できるようになります。

Tags: ,

ADO.NET

ビューから Entity Data Model 生成

by WebSurfer 2011年4月24日 13:12

Visual Studio のデザイナを使って、テーブルではなくビューから Entity Data Model(以下、EDM と書きます)を作成する時の話です。

ビューから EDM を作成

ビューもしくは主キーを持たないテーブルから EDM を作成しようとすると、以下のようなエラーメッセージが出て、有効な EDM が生成されないことがあります。

「テーブル/ビュー 'xxxxx' に主キーが定義されておらず、有効な主キーを推論できませんでした。このテーブル/ビューは除外されました。エンティティを使用するには、スキーマを確認し、正しいキーを追加して、コメントを解除する必要があります。」

検索して調べてみると、そのあたりのことは The table/view does not have a primary key defined というページに詳しく書いてありました。要約すると、以下のとおりです。

EDM の各 Entity は Key を持つ必要があり、ビューや主キーのないテーブルの場合は、デザイナが NULL 不許可の列を主キーとして推定して EDM を生成します。

しかしながら、ビューが取得する全列が NULL 許可の場合、デザイナは主キーを推定できず、有効な EDM を生成できないので、上記のエラーメッセージが出るということだそうです。

その場合でも、関係する SSDL, CSDL, MSL は edmx ファイルの中に生成されていますが、SSDL 部分がコメントアウトされていたり、その他 CSDL, MSL も不完全な内容となってます。

以下の例は、すべての列が NULL 許可のビューから作成した EDM の中身です(xml ファイルなのでメモ帳で開くことができます)。

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="2.0" 
  xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx">
  <!-- EF Runtime content -->
  <edmx:Runtime>
    <!-- SSDL content -->
    <edmx:StorageModels>
      <Schema ・・・中略・・・

  <!--生成中に見つかったエラー:
  警告 6013: テーブル/ビュー 'xxxxx' に主キーが定義されてお
  らず、有効な主キーを推論できませんでした。このテーブル/ビ
  ューは除外されました。エンティティを使用するには、スキー
  マを確認し、正しいキーを追加して、コメントを解除する必要が
  あります。
      
  <EntityType Name="ViewForEdmTest">
    <Property Name="ContactName" Type="nvarchar" MaxLength="30" />
    <Property Name="ContactTitle" Type="nvarchar" MaxLength="30" />
    <Property Name="Address" Type="nvarchar" MaxLength="60" />
    <Property Name="City" Type="nvarchar" MaxLength="15" />
    <Property Name="Region" Type="nvarchar" MaxLength="15" />
    <Property Name="PostalCode" Type="nvarchar" MaxLength="10" />
    <Property Name="Country" Type="nvarchar" MaxLength="15" />
  </EntityType>-->

      </Schema>
    </edmx:StorageModels>

    <!-- CSDL content -->
    <edmx:ConceptualModels>
      ・・・中略・・・
    </edmx:ConceptualModels>

    <!-- C-S mapping content -->
    <edmx:Mappings>
      ・・・中略・・・
    </edmx:Mappings>
  </edmx:Runtime>

  <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
  <Designer ・・・中略・・・
  </Designer>
</edmx:Edmx>

エラーメッセージの「正しいキーを追加して、コメントを解除・・・」というのは、それを書き直せということで、上に紹介したページの First Solution のことを言っています。

edmx ファイルをメモ帳で開いて、関係する SSDL, CSDL, MSL を書き直せば、確かに EDM 本体は有効になります。上の画像は、SSDL, CSDL, MSL を書き直したあと、edmx ファイルを Visual Studio で開いたもので、有効な EDM として表示されています(直す前は何も表示されません)。

ただし、Xxxxx.Designer.cs の定義が不完全なままなので、結局直した EDM はアプリケーションで利用できなかったのですが(自分が試した限りです)。

edmx ファイルを自力で書き直す以外の解決方法は以下の通りです。

  1. ビューが取得するフィールドに主キー列を含める。
  2. ISNULL 関数を利用する。

ビューにはもともと主キーなどはありませんが、ビューが取得するフィールドに主キー列が含まれていると、その列が NULL 不許可となり(デザイナがその列を主キーとして推定し)、EDM の生成に成功します。

2 番目の解決策は、上に紹介したページの Second Solution です。例えば、以下のように ID 列を追加してやります。なお、ROW_NUMBER() だけではダメで、ISNULL が必要ですので注意してください。

SELECT ISNULL((ROW_NUMBER() OVER (ORDER BY ContactName ASC)), 0) AS ID, ContactName, ContactTitle, Address, City, Region
FROM   dbo.Customers

なお、上記 1, 2 のいずれの場合も、EDM 生成時に以下のメッセージが出ますが、xxxxx.edmx ファイルは、xxxxx.Designer.cs を含めて、問題なく生成されているはずです。

「テーブル/ビュー 'xxxxx' には主キーが定義されていません。主キーは推論され、定義は読み取り専用のテーブル/ビューとして作成されました。」

Tags: , ,

ADO.NET

Access の更新

by WebSurfer 2010年9月4日 20:01

Visual Studio のウィサードを使うと、SQL Server や Access のテーブルを表示して、レコードを INSERT, DELETE, UPDATE するプログラムが簡単に作れます。

ただし、Access でオートナンバー(SQL Server で言うと IDENTITY)を使っている場合、INSERT した時に DB 側で設定したオートナンバー値を DataSet に書き込むところまでは面倒を見てくれません。(SQL Server の場合は面倒見てくれます)

これは、JET データベースエンジン(Microsoft Access およびその他の小規模アプリケーションで使用されている)では、単一バッチで複数のステートメントを実行できないということが理由のようです。

詳しくは、MSDN ライブラリの @@IDENTITY クライシスを管理する の「Microsoft Access/JET の問題」のセクションを参照してください。

ここでは、DataAdapter の RowUpdated イベントを使用して自動生成されたコードとは別のクエリを実行し、オートナンバー値を DataSet に書き込む具体的な例を紹介します。

まず、いつもの手順で型付 DataSet を作り、データソースウィンドウからテーブルを Form にドラッグ&ドロップしてアプリケーションを作ります。以下の画像がその例です。ここまではコードは一行も書く必要がありません。

Visual Studio でのアプリ作成

ただし、ここまでの実装では、新しいレコードを INSERT したとき、オートナンバーとなっている ID の値が DataSet に書き戻されていないので、DataGridView に表示されている ID 値は正しくありません。

そこで、INSERT 直後に発生する DataAdapter の RowUpdated イベントのハンドラで、"SELECT @@IDENTITY" クエリを使って新規 ID 値を取得し、それを DataSet に書き込んでやります。

具体的には、TableAdapter を partial class を使って拡張します。ソリューションにクラスファイルを追加して、以下のようなコードを実装します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;

namespace AccessWithAutoNumberAndDataSet.DataSet1TableAdapters 
{
  public partial class XXXTableAdapter
  {
    public void SetHandler()
    {
      this.Adapter.RowUpdated += 
        new OleDbRowUpdatedEventHandler(Adapter_RowUpdated);
    }

    private OleDbCommand cmd = 
      new OleDbCommand("SELECT @@IDENTITY", null);

    private void Adapter_RowUpdated(Object sender, OleDbRowUpdatedEventArgs e)
    {
      cmd.Connection = e.Command.Connection;
      cmd.Transaction = e.Command.Transaction;

      if (e.StatementType == StatementType.Insert && 
        e.Status == UpdateStatus.Continue)
      {
        object obj = cmd.ExecuteScalar();

        if (obj != null && obj.GetType() != typeof(DBNull))
        {
          e.Row["ID"] = (int)obj;
          e.Row.AcceptChanges();
        }
      }
    }
  }
}

これだけでは、ハンドラがイベントにアタッチされていないので、自動生成された Form のコードのコンストラクタに、上記 partial class で定義した SetHandler メソッドを追記します。以下のような感じです。

namespace AccessWithAutoNumberAndDataSet
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();

      // これを追加。
      this.xXXTableAdapter.SetHandler();
    }

これで、新規 ID 値が DataSet に書き込まれ、DataGridView に表示されるようになります。

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