Pages

Friday, November 29, 2013

SQL Azure の ID がジャンプする件ほか

最近、ひとに名刺を渡しつつ、申し訳程度に書いているこの Blog の URL なのだが、少しはまともなメモをたまには書かなければと思う今日この頃。そんなわけで、思いつき程度にさきほど気になったことをメモ。というか、むしろ淡々と技術的な備忘録にしちゃえばいいんじゃないかと思ったり。


Windows Azure の SQL サーバー サービスを使っていると、なぜかテーブルの ID たる int の自動生成カラムのシードがジャンプすることがある。

こんな感じ。どうやら、これは仕様らしくて、詳細はここでみつけた: Azure data transfer Identity Column Seed Jumped by 10,000

超要約すると、SQL の運用チームが「このほうが効率いいんじゃね?」って思って導入したということらしいのだが、それも今となっては「やっぱビミョー」だそうで、いつの日にか「やっぱやーめた」となる可能性があるということらしい。はい。


もう一件。Entity Framework を使っている人は、なんだかデータベースに接続するときに接続文字列が昔に比べてややこしいことにお気づきかと。具体的には、たとえば App.config にこんな感じの文字列がはいってらっしゃる:

metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string="hoge fuga piyo"
これの意味を再考せねばならない事態がおこるのが、次のようなとき:
これは、テスト用につくったソリューションだが、あるライブラリにデータベース接続用の EF モデルを作った。それを画面中のソースコードで使おうとしているが、次のような例外が発生している。

An unhandled exception of type 'System.Data.Entity.Core.MetadataException' occurred in EntityFramework.dll

Additional information: Unable to load the specified metadata resource.

どう見てもお怒りである。これは、*.edmx ファイルに書いてある EF モデルがうまく読み込めていない、とのことである。先ほどの接続文字列に戻ってみると、最初に metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl という記述がある。これがミソで、この例外が示すところは、このメタデータが読めてない、ということである。さて、このメタデータなのだが、実は *.edmx ファイルの構成を見てみれば、何をさしているのかわかる。たいてい、以下のような構成になっているはずだ。

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
  <!-- EF Runtime content -->
  <edmx:Runtime>
    <!-- SSDL content -->
    <edmx:StorageModels>
      <Schema Namespace="Model.Store" Alias="Self" Provider="System.Data.SqlClient">
        データベースの物理的構成がここに。
      </Schema>
    </edmx:StorageModels>
    <!-- CSDL content -->
    <edmx:ConceptualModels>
      <Schema Namespace="Model" Alias="Self">
        データベースの論理的構成がここに。
      </Schema>
    </edmx:ConceptualModels>
    <!-- C-S mapping content -->
    <edmx:Mappings>
      <Mapping Space="C-S">
        物理構成と論理構成の間のマッピングがここに。
      </Mapping>
    </edmx:Mappings>
  </edmx:Runtime>
  <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
  <edmx:Designer>
    細かいオプションとか、デザイナでの表示とかがここに。
  </edmx:Designer>
</edmx:Edmx>

細かいことはさておき、*.edmx ファイルのこの 3 つのコンポーネントが、コンパイル時にアセンブリ内にデフォルトでリソースとして埋め込まれる。それらがそれぞれ、Model.csdl, Model.ssdl, Model.msl という名前であり、さきほどの接続文字列はそれをさしていたのである。なお、細かいことが気になる人はこの記事が大変良く参考になる。

ではなぜ今回うごかなかったのかというと、Library のアセンブリを見てみるとき、良く見るとモデルが DB というフォルダ内に入っている。この場合、必ずしもアセンブリに埋め込まれるリソース名が上記のようにはならないのだ。

このとおり。そんなわけで、そういう場合には接続文字列を直してやる必要がある。ちなみに、res://*/ の * は、現在のアプリケーション ドメイン内で読み込まれているアセンブリすべてから当該名称を持つリソースを探すよ、という意味である。アセンブリ名が分かっているなら、当然指定したほうが早いらしい。参考まで。

No comments:

Post a Comment