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

ブラウザによる URL のエンコーディング

by WebSurfer 2011年11月7日 22:08

クエリ文字列に日本語を使用している場合、それをブラウザのアドレスバーから直接入力して要求をかけるのは問題がありそうです。

以下のような、日本語を含む URL をブラウザのアドレスバーに直接打ち込んで要求をかけると、ブラウザはどのような文字列をサーバーに送るでしょうか?

http://www.abc.com/日本語.aspx?data=日本語

下の画像は IE9 の場合で、Fiddler を使って HTTP-GET 要求をキャプチャし、HexView で表示したものです。サーバーに送信したバイト列を 16 進数で表したものと、その 16 進数に相当する ASCII コードの文字が表示されています。

Fiddler によるキャプチャ画面

ファイル名の "日本語" の方は UTF-8 が URL エンコード(ASCII 文字で %E6%97%A5 ... %AA%9E)されますが、クエリ文字列の方の "日本語" は Shift_JIS そのまま(反転表示したバイト列 93 FA 96 7B 8C EA)になっているのが見えるでしょうか。

IE9, Firefox 7, Chrome 15 で試してみましたが、ファイル名の方はいずれも UTF-8 の URL エンコードで同じ結果になりましたが、クエリ文字列の方はそれぞれ以下のように結果が異なりました。

ブラウザ クエリ文字列
IE9 Shift_JIS そのまま
Firefox 7 Shift_JIS を URL エンコード
Chrome 15 UTF-8 を URL エンコード

ということは、サーバーが受信した文字列を UTF-8 として解釈する場合(ASP.NET のデフォルト)、上記のブラウザのうち Chrome しかクエリ文字列を正しく送信できないということになるようです。

では、アドレスバー直打ちではなく、以下のようなハイパーリンクをクリックするとブラウザはどのような要求をサーバーに送るでしょうか?

<a href="default.aspx?data=日本語">リンク</a>

IE は文字コードのバイト列を生のまま送ります。例えば、"日本語" というクエリ文字列の場合、ハイパーリンクのあるページのエンコーディングが Shift_JIS なら 93 fa 96 7b 8c ea、UTF-8 なら e6 97 a5 e6 9c ac e8 aa 9e となります。

Firfox と Chrome は URL エンコードしてから送ります。ただし、Shift_JIS の場合、2 バイト目が ASCII の非予約文字のときは、その文字をそのまま使用します。"日本語" の場合、"本" の 2 バイト目 7b が ASCII 文字で '{' に該当するので、結果は "%93%FA%96{%8C%EA" になります。

特殊な例かもしれませんが、BlogEngine.NET の場合 '{' という文字が問題で、内部で URL の書き換えを行う際に例外がスローされてサーバーエラーになってしまうという問題がありました。

このような予期しない問題を避けるために、サーバー側できちんと UrlEncode メソッドを使って URL エンコーディングした文字列("本" は "%96%7b" になります)を使うのがよさそうです。(ただし、アドレスバー直打ちされた場合はどうしようもありませんが)

ちなみに、URL 本体('?' の左側の文字列)は、アドレスバーへの直打ち、ハイパーリンクへの設定、ページに使用されているエンコーディングの違い、ブラウザの違い(IE9, Firefox 7, Chrome 15 しか試してませんが)などに関係なく UTF-8 の URL エンコーディングになります。

なので、BlogEngine.NET 2.0 の Tag cloud の問題日本語の著者名の問題 で書��ましたように、URL 本体の文字に URL エンコードしない日本語の文字列を使っていますが、今までのところ期待通りに動いています。運よく問題に遭遇していないだけという可能性は排除しきれませんが。(笑)

Tags: ,

その他

長い日本語の添付ファイル名が文字化け

by WebSurfer 2011年10月30日 22:00

.NET Framework 4 の SmtpClient を使用すると、添付ファイルに長い日本語のファイル名を使うと文字化けするという問題があります。(.NET 3.5 以前では問題なし)

原因はファイル名が二重エンコーディングされてしまうからで、そのメカニズムは このブログ に詳しく書いてあります。

この問題は、米国の MSDN フォーラムでも報告されており、原因が .NET Framework 4 のバグであることは Microsoft も認識しているようです。

その時の Microsoft の人の回答(2010/7/23 付けの記事参照)では、次のリリースを待つか、短い名前にするしかないということでした。

とは言え、現実に問題ない PC があるのは確かですので(自分の開発マシンがそうです)、何らかの更新プログラムがリリースされていて、問題が発生しない PC には適用されているはずと思って調べたら、Connect のページ に、Hotfix KB2183292 によってファイル名の二重にエンコーディングの問題も解決されるとの話がありました。

試しに、二重エンコーディングの問題の出ていた PC に、Hotfix KB2183292 をダウンロードしてインストールすると問題が解決しました。

Windows Update でインストールされる .NET Framework 4 用の更新プログラム で Hotfix KB2183292 が置き換えられると書いてありましたので、この更新プログラムによって二重エンコーディングの問題も解決されているのかと思いましたが、どうもそうではないようです。

実際、.NET Framework 4 用の更新プログラム がインストールされている PC でも二重エンコーディングの問題が発生しました。

というわけで、Windows Update で解決されているのではなさそうなので、次期リリース(.NET 4.5 ?)でこの問題が解決されるまでは、長い日本語のファイル名を添付ファイルに使う場合は、何らかの対策が必要なようです。

問題は、Attachment コンストラクタ (String, ContentType) で長い日本語のファイル名を使用すると二重エンコーディングされるということなので、代わりに Attachment コンストラクタ (Stream, ContentType) を使用し、Content-Disposition の filename の方にファイル名を設定することで問題を回避できるはずです。

以下のような感じです。

private string EncodeHeader(string str, Encoding enc)
{
  string ret = 
    System.Convert.ToBase64String(enc.GetBytes(str));
  ret = string.Format("=?{0}?B?{1}?=", enc.BodyName, ret);
  return ret;
}

private void button2_Click(object sender, EventArgs e)
{
  System.Text.Encoding enc = 
    System.Text.Encoding.GetEncoding("utf-8");

  string mailAddress = this.userName + "@" + this.host;

  MailAddress to = 
    new MailAddress(mailAddress, EncodeHeader("日本花子", enc));
  MailAddress from = 
    new MailAddress(mailAddress, EncodeHeader("日本太郎", enc));

  MailMessage mailMessage = new MailMessage(from, to);

  mailMessage.Subject = textBox1.Text;
  mailMessage.Body = textBox2.Text;

  // 添付ファイル
  file = "テスト用の長めのファイル名です.pdf";
  FileStream fs = 
    new FileStream(file, FileMode.Open, FileAccess.Read);

  Attachment data = 
    new Attachment(fs, MediaTypeNames.Application.Octet);
  ContentDisposition disposition = data.ContentDisposition;
  disposition.FileName = 
    EncodeHeader(System.IO.Path.GetFileName(file), enc);

  mailMessage.Attachments.Add(data);

  SmtpClient smtpClient = new SmtpClient();
  smtpClient.Host = host;
  smtpClient.Port = portSmtp;

  try
  {
    smtpClient.Send(mailMessage);
    MessageBox.Show("Your mail was sent.");
  }
  catch (SmtpException ex)
  {
    SmtpStatusCode status = ex.StatusCode;
    MessageBox.Show("SmtpException: " + ex.Message + 
      "\nSmtpStatusCode: " + status.ToString());
  }
  catch (Exception ex)
  {
    MessageBox.Show("Exception: " + ex.Message);
  }
  finally
  {
    mailMessage.Dispose();
  }
}

こうすると、以下のように Content-Type の name は application/octet-stream となり、Content-Disposition の filename にファイル名が設定され、正しいファイル名を取得できます(メーラーによってはダメかもしれませんが)。

Content-Type: application/octet-stream;
 name="application/octet-stream"
Content-Transfer-Encoding: base64

Content-Disposition: attachment;
 filename="=?utf-8?B?44OG44...BkZg==?="

なお、一旦 Cotent-Type の name が二重エンコーディングされたものになってしまうと、Content-Disposition の filename にファイル名を設定しても、何故かそちらは無視されてしまいます。メーラーにもよると思いますが Windows メールはダメでした。

という訳で、上記のコード方法が次期バージョンがリリースされるまでの Workaround としては適当なようです(ただし、filename のところが、一行で 76 文字の制限を越えてしまいますので、メーラーによっては対応が必要かもしれません)。

Tags: ,

.NET Framework

About this blog

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

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar