none
中身が空のテーブルをクエリした場合の挙動 RRS feed

  • 質問

  •  中身が空のテーブルをクエリするとします。

    ● CASE1:where句無しのクエリ式 結果: "0"
    context.IgnoreResourceNotFoundException = true;
    var query = from n in context.CreateQuery<TableServiceEntity>("Delme001") select n;
    int count = 0;
    foreach (var n in query) count++;
    Label1.Text = count.ToString();

    ● CASE2:where句追加 結果: 例外
    context.IgnoreResourceNotFoundException = true;
    var query = from n in context.CreateQuery<TableServiceEntity>("Delme001") where true select n;
    int count = 0;
    foreach (var n in query) count++;
    Label1.Text = count.ToString();

     これは、こういうものなのでしょうか?
     どのようなテーブルもサイズゼロからスタートする可能性があるので、初期状態の振る舞いはとても気になります。
     ならば、テーブルが空であることの判定方法は以下でも良いのでしょうか?

    ※ Class1はTableServiceEntityを継承した実クラスとして

    var query = from n in context.CreateQuery<Class1>("Delme001") select n;
    if( query.FirstOrDefault() != null ) ……

    2011年2月6日 6:02

すべての返信

  • こんにちはbird982000です。

    すいません。直接の回答になりませんが、時間が経っているので解決の一助になればと思い書き込みます。

    おそらく、今回の内容はSDKの中の動作になるので、外部からはわからない気がします。

    ですが、ストレージアクセスは最終的にRESTに変換されてアクセスされるので、Fiddlerなどでレスポンスを確認してみることで解決の一助になるかもしれません。

    ストレージでのFiddlerの使い方は以下をご参照ください。

    http://codezine.jp/article/detail/5596?p=3

    もしくは、USのフォーラムで質問してみるのもアリかもしれません。向こうでは開発部署とつながっていて、既に幾つかのバグが見つかっていて今後の修正を約束されています。

    あまりお役に立ててないのですが、参考になれば嬉しいです。

    2011年2月8日 9:28
  • autumn009さん

    こんばんは。
    Mayomayoです。

    > これは、こういうものなのでしょうか?

    恐らく開発環境(Storage Emulator)で作業されているのではないかなという前提でお話致します。

    現状のSDKですとデータを一回も登録した事がないTable Storageにクエリを発行しますと例外が発生するようです。
    Microsoft のTable を使用するサンプルコードには、その例外を回避する為の開発(Debugビルド)時のみ Table 作成時に適当なデータを一件追加してすぐに削除するコードが書かれてました。
    ( Traingin Kit の ASP.NET の Session を使用するサンプルの TableStorageExtensionMethods 拡張メソッド内 )

    これに習い開発環境ではTable作成時に同様の事を行なえば無用なトラブルは避けられるかと思います。
    ( テーブルの作成処理は重めですので、一度作成したら次回からは作成処理を実行しないように工夫されるのがよいかと思われます。)

    本番 Storage では例外は発生しかったと思いますが、記憶が曖昧ですので実際に試して頂ければと思います。


    > テーブルが空であることの判定方法は以下でも良いのでしょうか?

    良いと思います。
    ただし、その後ToArray等で複数のエンティティを取得予定なら次の書き方の方がいいかもしれません。

    hoge[] hogeArray =  query.ToArray();
    //0件の場合hogeArray は、要素0の配列としてインスタンス化されている
    if ( hogeArray.Count() > 0 )
     ・・・

    こちらも動かしてご確認頂ければと思います。

    2011年2月8日 10:00
  •  bird982000さん、Mayomayoさん、お返事ありがとうございます。
     とりあえず、Fiddlerでストレージのトラフィックを見てみようと思ったのですが、上手く行きません。
     テーブルへのアクセスは記録されておらず、以下のようなエラーがWebブラウザに表示されてしまいます。

    > '/' アプリケーションでサーバー エラーが発生しました。
    > --------------------------------------------------------------------------------
    > リモート名を解決できませんでした。: 'ipv4.fiddler'

     他の雑用も山ほど詰まってしまったので、あとでまた調べてみます。

    2011年2月9日 4:48
  • autumn009さん、こんばんは。
    Mayomayoです。

    一点見落としがございましたので追記させて下さい。
    WCF DataServces のコードで問題があることに気づきました。

    今回の場合は where 句の部分に列(プロパティ)指定がされていないのが原因かと思われます。
    この条件ですとhttpリクエストが、
    http://ストレージ/Delme001()?$filter=True
    に変換され結果Delme001エンティティの True 列に関する検索条件になってしまい例外が発生しているのではないでしょうか。

    こちらを修正された後、もしこの where 句の部分に標準で存在しない列(PartitionKey, RowKey等)を指定してクエリを実行すると先に私が触れました問題が発生致します。

    もう一点、多分こちらはフォーラム掲載用にソースコードを変更された為と思われますが、
    context.CreateQuery<TableServiceEntity>
    と抽象クラスのインスタンス化になってしまっております。
    こちらも例外が発生致します。


    bird982000さんが勧められている Fiddler はデバッグするのに強力で私も使っております。
    もしautumn009さんの環境で動作しない場合はStorage Emulator のログを出力も試されてみては如何でしょうか。
    Storage Emulator までhttpリクエストが届いていたらログが記録されます。

    設定方法は、SDKインストール先のファイルを次のように変更すれば出力されます。
    お時間のある時にご利用頂ければと思います。

    ◇ファイル
    [Azure SDKのインストールパス]\Windows Azure SDK\v1.3\bin\devstore\DSService.exe.config

    ◇設定 

    <configuration>
     ・・・
     </developmentStorageConfig>
    
     <!-- ログ出力の設定 -->
     <system.diagnostics>
     <sources>
     <source name="System.Net" tracemode="includehex" maxdatasize="1024">
     <listeners>
     <add name="System.Net"/>
     </listeners>
     </source>
     <source name="System.Net.Sockets">
     <listeners>
     <add name="System.Net"/>
     </listeners>
     </source>
     <source name="System.Net.Cache">
     <listeners>
     <add name="System.Net"/>
     </listeners>
     </source>
     <source name="System.Net.HttpListener">
     <listeners>
     <add name="System.Net"/>
     </listeners>
     </source>
     </sources>
     <switches>
     <add name="System.Net" value="Verbose"/>
     <add name="System.Net.Sockets" value="Verbose"/>
     <add name="System.Net.Cache" value="Verbose"/>
     <add name="System.Net.HttpListener" value="Verbose"/>
     </switches>
     <sharedListeners>
     <add name="System.Net"
     type="System.Diagnostics.TextWriterTraceListener"
     initializeData="c:\temp\devstorage_network.log" ←ここでログの出力先を設定します。
     />
     </sharedListeners>
     <trace autoflush="true"/>
     </system.diagnostics>
    
    </configuration>
    
    
    
    2011年2月9日 13:16
  •  Mayomayoさま。
     遅くなって済みません。いろいろバタバタと用件があるほか、どうしてもFiddlerが上手く機能しなかったので。

    > where 句の部分に列(プロパティ)指定がされていないのが原因かと思われます
     クラウド環境のストレージでは動きますので、おそらく違う原因と思います。

    > と抽象クラスのインスタンス化になってしまっております。
     継承して抽象ではないクラスを指定しても結果は同じです。どのみちインスタンス化されることは無いので、おそらく関係ありません。(テーブルのサイズが0の場合の話です)

     Storage Emulator のログを出力はこれから試させて頂きます。

     Fiddlerについては、どうしても上手く動きません。ローカルで動くAzureアプリから開発用ストレージでは無くクラウド環境のストレージを指定しても同じです。マシンを再起動後、クラウドのストレージへのアクセスを1回だけ記録できているようですが、詳細は良く分かりません。
     この点は是非ともFiddlerでAzureアプリのトラフィックを上手く監視できているか、皆さんにもお聞きしたいところです。(環境も含め)

    2011年2月14日 2:59
  • autumn009 様

    こんばんは、Mayomayoです。
    色々とお忙しいと思いますので、ご返信については気になさらないで下さい。

    私の環境での Fiddler の動作についてお伝えします。
    Fiddler 起動後ブラウザから次のURLを開くと、Fiddlerが動作している事が確認できます。
    http://ipv4.fiddler:8889/
    ポート8889 は、メニューの[Tools]→[Fiddler Options]→[Connections]タブの[Fiddler listens on port:]で設定しています。
    プロキシサーバーは使用しておりません。

    ローカルのアドレス127.0.0.1 ですとFiddlerでキャプチャされませんので、開発時はOSの hosts ファイルに別名をつけてStorage Emurator にアクセスするようにしています。
    試していませんが、Fiddlerではメニューの[Tools]→[HOSTS] からでも設定できそうです。


    ご存知かもしてませんが、Azure のストレージとStorage Emulator では動作が異なります。
    http://msdn.microsoft.com/en-us/library/gg433135.aspx
    上記のページには記述されていない違いもございます。
    例えば、本番ではテーブルストレージを削除して同名のテーブルを再作成する場合、おおよそ1分ぐらい間隔が必要です(開けないと例外が発生します)。開発環境ではこの問題は発生しません。他にもいくつか悩まされる現象が発生していますので、経験則として開発と本番の双方で動作を確認するのが宜しいかと思われます。

    2011年2月16日 12:16
  • Mayomayoさま、お返事ありがとうございます。

     fiddlerは相変わらずAzureの開発中プログラムの通信「のみ」監視できません。
     しかし、ログ出力でおおむね問題点の要点は見えてきました。

    ・空のテーブルをクエリした際、例外が起きるケースがある (起きないケースもある)
    ・開発版ストレージのみで起こる (クラウドのストレージでは起こらない。例外あり)

    ・例外が起きないケースその1
    var query = from n in context.CreateQuery<Class1>("Delme001") select n;
    Label1.Text = (query.FirstOrDefault()!=null).ToString();
    →発行されるRESTリクエスト http://127.0.0.1:10002/devstoreaccount1/Delme001()?$top=1#609901088

    ・例外が起きないケースその2
    Label1.Text = query.ToArray().Count().ToString();
    →発行されるRESTリクエスト (クエリは発行されない。丸ごとコピーをもらうから)

    ・例外が起きないケースその3
    var query = from n in context.CreateQuery<TableServiceEntity>("Delme001") where n.Timestamp == DateTime.MinValue select n;
    →発行されるRESTリクエスト http://127.0.0.1:10002/devstoreaccount1/Delme001()?$filter=Timestamp eq datetime'0001-01-01T00:00:00'&$top=1#-190635800

    ・例外が起きるケースその1
    var query = from n in context.CreateQuery<TableServiceEntity>("Delme001") where true select n;
    Label1.Text = (query.FirstOrDefault()!=null).ToString();
    →発行されるRESTリクエスト http://127.0.0.1:10002/devstoreaccount1/Delme001()?$filter=true&$top=1#-1353064008

    ・例外が起きるケースその2 (クラウドストレージでもNG)
    Label1.Text = query.Count().ToString();
    →発行されるRESTリクエスト
    http://127.0.0.1:10002/devstoreaccount1/Delme001()/$count#212768682

     まとめると、

    ・開発版ストレージは$filter=を含み、式がtrueのみ等の単純な形態だと例外が起きる
    ・$countを空のテーブルに対してクエリすると開発版クラウド版共に例外が起きる
    ・where句を含まずFirstOrDefaultで処理するクエリ式は"$top=1"のクエリをRESTレベルで発行しており、これは安全である

     これは単純に、開発版ストレージとクラウド版ストレージの間に多くある挙動の差の1つとして理解した方が良さそうだと思いました。避けて通れればそれで十分です。今のところは。

    2011年2月17日 3:30
  • こんにちは。

    まったくフォローできてなくてすみませんでした。ほぼほぼ解決されたようですが、Fiddlerについての追加情報です。

    まだ試していないのですが、1.3になるとFiddlerが使えない現象はUSでも報告されているようです。

    対策が紹介されていましたので、ご参考まで。

    http://social.msdn.microsoft.com/Forums/en-US/windowsazuredevelopment/thread/14a5875c-f9ca-45be-9141-56c378669401

    2011年2月17日 4:31
  • まだ試していないのですが、1.3になるとFiddlerが使えない現象はUSでも報告されているようです。

    bird982000様。ありがとうございます。

    ipv4.fiddlerが発見できないというエラーは解消されました。ただ、相変わらずアクセスが記録されない現象が残りますが、ここから先はツールの使いこなしの問題でAzureの問題では無いと思います。

    ※ やはり、Azure SDK 1.3はいろいろな面でお騒がせバージョンになっているようですね。

    2011年2月17日 7:37
  • autumn009様

    Mayomayoです。
    調査が進んで何よりです。

    現状Azure Storage の特性上 Count 以外にも制限されているAPIがございます。
    MSDNに対応表がございますのでよかったらご利用下さい。

    Query Operators (Table Service Support)
    http://msdn.microsoft.com/en-us/library/dd135725.aspx
    Querying Tables and Entities
    http://msdn.microsoft.com/en-us/library/dd894031.aspx


    私の開発環境では次の設定でFlddlerが動作しております。ご参考までに…
    ServiceConfiguration.cscfg ファイルの接続文字列
    <Setting name="DataConnectionString"
       value="UseDevelopmentStorage=true;DevelopmentStorageProxyUri=http://(Hostsで設定したローカルホストの別名)" />


    bird982000様

    こういった事例もあるのですね。
    勉強になります。

    2011年2月17日 13:03