WebSurfer's Home

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

LocalDB で Northwind と Pubs を利用

by WebSurfer 2017年5月16日 20:43

Microsoft が提供するサンプルデータベース Northwind と Pubs を LocalDB にアタッチして使うにはどうすればいいかということを書きます。

VS2015 から Pubs に接続

今年の 1 月に買った Windows 10 Pro 64-bit のノート PC に Visual Studio 2015 Communuty Update 3(以下、VS2015 と書きます)をインストールして使い始めました。

自分の環境では、VS2015 をインストールした際 SQL Server 2016 Express LocalDB(以下、LocalDB と書きます)も同時にインストールされたので、特に何もしていないのですが LocalDB が使えます。

VS2015 のテンプレートを使ってフォーム認証用の ASP.NET プロジェクトを作ると、ASP.NET Identity 用のデータベース(.mdf, .ldf ファイル)が EF Code First と LocalDB を使って App_Data フォルダに自動生成されるということで、LocalDB を使うのが VS2015 でのデフォルトのようです。

というわけで、少なくとも開発の初期段階では LocalDB を使うのが便利だと思って自分も使い始めました。

でも、実は最近になって、SQL Server Express が使えれば、LocalDB を使う必要はなさそうだと思い始めているのですが。LocalDB の使い方を勉強する時間がもったいないかも。(笑)

(上に書いた EF Code First で DB を生成するのは SQL Server Express でもできます。プロジェクトが生成された直後に web.config の接続文字列を SQL Server Express を使うように変更すれば、DB を生成して SQL Server Express の既定のインスタンス(または名前付きインスタンス)にアタッチしてくれます)

SQL Server Express が使えれば、LocalDB で Northwind と Pubs を使う必要はなさそうです。でも、せっかく考えたので書いておきます。この先 LocalDB しか使えないという環境もあるかもしれませんし。

さて、Northwind と Pubs ですが、それらは Microsoft が無償で提供している SQL Server 2000 用のサンプルデータベースです。MSDN ライブラリなどのチュートリアルでよく利用されており、自分もお世話になっています。

ファイルは Microsoft のダウンロードサイト Northwind and pubs Sample Databases for SQL Server 2000 から SQL2000SampleDb.msi というインストーラー形式で入手できます。

インストーラーを実行すると C:\SQL Server 2000 Sample Databases というフォルダ下に .mdf ファイル、.ldf ファイル、.sql ファイルが生成されます。

VS2015 から LocalDB を利用する場合、MSSQLLocalDB という名前の自動インスタンス(他に名前付きインスタンスというのもあるそうです)に特定の .mdf ファイル名を接続文字列の AttachDbFileName に指定してアタッチし、それに接続するのが一般的だと思います。

しかしながら、ダウンロードした NORTHWND.MDF や PUBS.MDF をアタッチしようとすると、SQL Server 2000 の .mdf ファイルなので SQL Server 2016 と互換性がないため、以下のようなエラーとなって失敗します。(この画像の前に「データベースを今すぐアップグレードしますか?」と出るので、そこで[はい]をクリックした結果です)

エラーメッセージ

ダウンロードした NORTHWND.MDF や PUBS.MDF を SQL Server 2016 と互換性を持つようにアップグレードできないかいろいろ調べましたが、自分が調べた限りでは方法は見つかりませんでした。

上の画像のエラーメッセージ "You must re-create the database" の通りデーターベースを作り直す他方法はなさそうです。

NORTHWND.MDF や PUBS.MDF と一緒にダウンロードされたスクリプトファイル instnwnd.sql(Northwind 用)と instpubs.sql(Pubs 用)を使えば作り直すことが可能です。問題はどのようにスクリプトを実行するかです。

実は知らなかったのですが、SQL Server Management Studio(以下、SSMS と書きます)を LocalDB に接続できるのでした。SSMS を利用すれば容易にスクリプトを実行できます。

下の画像は SQL Server 2008 の SSMS ですが、LocalDB に接続し、赤丸で囲った[ファイルを開く]アイコンをクリックして instnwnd.sql を開いたところです。

SSMS を LocalDB に接続

スクリプトには SQL Server 2016 では使用できないストアドプロシージャ sp_dboption が使われていますので、実行する前にその部分の修正が必要です(instnwnd.sql に 2 行、instpubs.sql に 1 行あります)。上の画像の赤の四角で囲った部分が instnwnd.sql の場合の訂正箇所です。

ストアドプロシージャの説明は MSDN ライブラリの sp_dboption (Transact-SQL) を見てください。チュートリアルに使うだけならコメントアウトするだけでもいいと思います。

同等の設定にするなら、alter database <データベース名> set recovery simple に書き換えればよさそうです。

訂正してから[実行(X)]をクリックするとスクリプトが走ってデーターベースが生成され、SSMS でデータベースを開いて操作できるようになります。

データベースが生成されると VS2015 からも接続できるようになります。下の画像は VS2015 のサーバーエクスプローラーからデータ接続の追加で、LocalDB 上に生成してアタッチされた Pubs に接続しているところです。

VS2015 を LocalDB に接続

上の画像で[データソース(S)]が既定のインスタンス(または名前付きインスタンス)に接続するためのものになっており、[サーバー名(E)]が LocalDB の MSSQLLocalDB という名前の自動インスタンスになっている点に注意してください。

それらが正しく選択されていれば[データベース名の選択または入力(D)]に上の画像のように接続可能な候補一覧が表示されるはずです。ここで Pubs を選択して[OK]をクリックした結果が一番上の画像です。

もちろんアプリケーションからも接続できます。既定のインスタンス(または名前付きインスタンス)に接続する時と同様な接続文字列で、Data Source を (LocalDB)\MSSQLLocalDB にすれば OK です。

Tags: , ,

DevelopmentTools

jQuery.ajax で JSONP

by WebSurfer 2017年5月3日 14:30

jQuery.ajax を使うと、JSONP(JSON with Padding・・・script タグを使用してクロスドメインでデータを取得する仕組み)を利用してデータを取得するのがかなり簡単にできるという話を書きます。

JSONP の応答を alert に表示

何が簡単になるかというと以下のことを jQuery.ajax が自動的にやってくれることです。

  1. jQuery.ajax を呼び出した時点で script タグを生成し DOM ツリーへ追加。(本来は、src 属性に呼出先の URL を設定した script タグを生成して DOM ツリーに追加するためのスクリプトを自力で書かなければなりません)
  2. 呼出先の URL にコールバックの名前を指定するクエリ文字列 &callback=jQuery... を追加。
  3. 応答が返ってくるとコールバックが呼び出され、引数に設定された JSON 文字列が JavaScript オブジェクトにパースされ、success: function (data) の data に渡される。

以下に具体例を書きます。MVC を例にとっていますが、もちろん Web Forms でも同様なことは可能です。

まず、ブラウザからの要求を受けて応答を返す窓口を作ります。MVC アプリの場合は、以下のようにアクションメソッドを使うのが簡単そうです。

具体的にどういう操作をしているかはコメントに書きましたのでそちらを見てください。

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using AdventureWorksLT;
using System.Web.Script.Serialization;

namespace Mvc5App.Controllers
{
  public class AddressesController : Controller
  {
    // サンプルデータベース AdventureWorksLT をベースに
    // Visual Studio のウィザードで作った EDM を利用。
    // AdventureWorksLTEntities は DbContext を継承
    private AdventureWorksLTEntities db = 
                            new AdventureWorksLTEntities();

    // JSONP が呼び出すアクションメソッド
    public ActionResult Jsonp(int? id, string callback)
    {
      if (id == null)
      {
          return new HttpStatusCodeResult(
                                 HttpStatusCode.BadRequest);
      }

      // Address テーブルから指定された AddressID(主キー)
      // でレコードを検索。
      // 当該レコードの AddressID, AddressLine1, City フィー
      // ルドのデータを匿名クラスのオブジェクトとして取得
      var address = (from a in db.Address
         where a.AddressID == id
         select new { a.AddressID, a.AddressLine1, a.City }).
         FirstOrDefault();

      if (address == null)
      {
          return HttpNotFound();
      }

      // 取得したオブジェクトを JSON 文字列にシリアライズし
      // 変数 callback に名前が指定されたコールバックメソッ
      // ドの引数に設定。
      // code は「コールバック(JSON 文字列)」という文字列に
      // なる
      JavaScriptSerializer ser = new JavaScriptSerializer();
      string code = string.Format("{0}({1})", 
                          callback, ser.Serialize(address));

      // 文字列「コールバック(JSON 文字列)」を返す。その際
      // ヘッダに Content-Type: application/x-javascript; が
      // 付与される
      return JavaScript(code);
    }
    // ・・・中略・・・
  }
}

上記のアクションメソッドを、例えば /Addresses/Jsonp?id=25&callback=name で呼び出すと、以下の応答が返ってきます。

name({"AddressID":25,"AddressLine1":"9178 Jumping St.","City":"Dallas"})

呼び出し側(View)のコードは以下のようになります。上にも書きましたが、script 要素を DOM に追加するコードを書く必要はありません。以下のコードだけで jQuery.ajax が自動的にやってくれます。

<input type="text" id="tb1" />
<input type="button" value="検索" onclick="btn_click()" />

@section Scripts {
  <script type="text/javascript">
  //<![CDATA[
    function btn_click() {
      var address = '/Addresses/Jsonp?id=' + $("#tb1").val();

      $.ajax({
          url: address,
          dataType: 'jsonp',
          success: function (data) {
              alert(data.AddressID + ', ' +
                    data.AddressLine1 + ', ' + 
                    data.City);
          }
      });
    }
  //]]>
  </script>    
}

上記には jQuery の外部スクリプトファイルの参照が書いてありませんが、Visual Studio 2015 のテンプレートで自動生成した _Layout.cshtml を利用していますので、デフォルトで取り込まれるようになっています。

_Layout.cshtml を利用していますので、インラインのスクリプトは、上記のように View に @section Scripts { ... } を追加して、その中に書くのが適当です。header タグ内に書くと jQuery の外部スクリプトファイルが取り込まれる前になってしまいますので注意してください。

コールバックのメソッド名は、上にも書きましたが、jQuery.ajax がクエリ文字列として自動的に自動的にデフォルトの名前を追加しますので、それを利用しています。(デフォルトの名前では不都合がある場合は指定することも可能です)

data には、コールバックの引数の JSON 文字列が JavaScript オブジェクトに変換されて渡されます。なので、上記のようにプロパティを使ってデータを取得することができます。

Tags: ,

AJAX

IIS Express と gzip 圧縮

by WebSurfer 2017年4月24日 23:38

Visual Studio で ASP.NET Web アプリを開発する際に使用される IIS Express はデフォルトで gzip 圧縮された応答を返すという話を書きます。

(Visual Studio 2015 Community Update 3 と一緒にデフォルトでインストールされる IIS 10.0 Express の話です。他のバージョンは不明です)

Fiddler によるキャプチャ結果

Visual Studio 2010ではデフォルトで ASP.NET 開発サーバーを使用します。IIS Express も、先の記事「IIS Express をインストールしました」に書きましたように、別途ダウンロードしてインストールすれば使用可能です。

しかしながら、Visual Studio 2015 では ASP.NET 開発サーバーを使用できませんので、IIS Express またはローカル IIS のいずれかを使うことになります。

当然ながらローカル IIS より IIS Express の方が手軽かつ便利ですし、以下の理由もあって、少なくとも開発の初期には IIS Express を使わざるを得ません。

  1. EF Code First + LocalDB の機能を使ってユーザー情報のストア(.mdf ファイル)を App_Data フォルダに生成するというところがローカル IIS ではできません。
  2. LocalDB を動かすにはユーザープロファイルが必要なので IIS Express を使わざるを得ません。(ローカル IIS は Windows Service として動くのでユーザープロファイルを持たない)

ローカル IIS を使うには、IIS 上でのアプリケーションの設定とフォルダの権限の設定はもちろん、EF Code First + LocalDB の機能で App_Data フォルダに生成された .mdf ファイルをコピーして SQL Server にアタッチし、Web アプリから SQL Server に接続できるようにするという設定の変更が必要になります。

ということで、Visual Studio 2015 を使っての ASP.NET Web アプリの開発には、自分もやむを得ず(?)ほとんど使ったことがない IIS Express を使い始めました。

ところが IIS Express とローカル IIS ではデフォルトの設定が違っているようで、まず気が付いたのが gzip 圧縮です。

IIS で静的コンテンツの圧縮をかけるにには、MSDN Blog の記事「IIS7 以降の静的コンテンツの圧縮について」によると、役割サービスで [静的コンテンツの圧縮] を有効にするなどの設定が必要とのことです。

ローカル IIS にはそのような設定はしてないので gzip 圧縮はかかりません。ところが、IIS Express ではデフォルトで gzip 圧縮がかかります。上の画像を見てください。

IIS Express の ApplicationHost.config を調べてみると以下の設定がありました。これの、<dynamicTypes> から </staticTypes> までをコメントアウトすると gzip 圧縮はかからなくなります。

<httpCompression 
  directory="%TEMP%\iisexpress\IIS Temporary Compressed Files">
  <scheme name="gzip" dll="%IIS_BIN%\gzip.dll" />
  <dynamicTypes>
    <add mimeType="text/*" enabled="true" />
    <add mimeType="message/*" enabled="true" />
    <add mimeType="application/javascript" enabled="true" />
    <add mimeType="application/atom+xml" enabled="true" />
    <add mimeType="application/xaml+xml" enabled="true" />
    <add mimeType="*/*" enabled="false" />
  </dynamicTypes>
  <staticTypes>
    <add mimeType="text/*" enabled="true" />
    <add mimeType="message/*" enabled="true" />
    <add mimeType="image/svg+xml" enabled="true" />
    <add mimeType="application/javascript" enabled="true" />
    <add mimeType="application/atom+xml" enabled="true" />
    <add mimeType="application/xaml+xml" enabled="true" />
    <add mimeType="*/*" enabled="false" />
  </staticTypes>
</httpCompression>

まだ調べてませんけど、gzip 圧縮以外にも違うところがありそうです。重大な違いに気が付いたら別途記事を書くつもりです。

Tags: ,

DevelopmentTools

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  2017年7月  >>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

View posts in large calendar