Azure.Data.Tables の TableClient を使って、プロパティが null のエンティティを検索しようと思いましたが、その方法がわからずに悩んだのでメモしておきます。
先に結論
Odata の $filter でも同様に使えるテクニックかと思います。
$filter=not(Hogehoge ne '')
これで null のプロパティを検索できます。
プロパティがnullのエンティティを検索できない件
Azure Table Storage に nullable なプロパティがあるオブジェクトを記録しようとしていました。
例えばこんな感じに、恋人の ID を nullable にしたとします。
using Azure;
using Azure.Data.Tables;
public class Person : ITableEntity
{
public Person() { }
public Person(int id, string name, int? loverId = null)
{
Id = id;
Name = name;
LoverId = loverId;
PartitionKey = id.ToString();
RowKey = "__PERSON__"; // 思いつかないので決め打ち
}
public int Id { get; set; }
public string Name { get; set; }
// nullable な恋人 ID
public int? LoverId { get; set; }
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
}
public class Program
{
static async Task Main()
{
var tableClient = new TableClient("<ConnectionStrings>", "Person");
await tableClient.CreateIfNotExistsAsync();
var persons = new Person[]
{
new Person(1, "太郎", 4),
new Person(2, "次郎"),
new Person(3, "花子", 5),
new Person(4, "加代子", 1),
new Person(5, "小春", 3)
};
foreach (var person in persons)
{
await tableClient.AddEntityAsync(person);
}
}
}
これを実行すると、以下のようにエンティティが追加されます。
次郎さんだけ “独り” ですねw ()
なんか百合が発生してますがサンプルなので
で、そのあと
“独り” を探そうとしたときに躓きました。
Azure.RequestFailedException: 'One of the request inputs is not valid.
というエラーが。
飛ばしたクエリは愚直に
LoverId eq null
です。
プロパティがnullのエンティティを検索する方法
意味わかんないのでいろいろ試した感じ、
var filter = "LoverId eq null"; // Azure.RequestFailedException: 'One of the request inputs is not valid.
var filter = "LoverId eq ''"; // 検索該当なし (プロパティがstring 型でも同様)
var filter = "not(LoverId ne '')"; // これだとうまくいく
上の最後の行のフィルタで動くようです。
以下に検証用のコードの全体を示します。
using Azure;
using Azure.Data.Tables;
public class Person : ITableEntity
{
public Person() { }
public Person(int id, string name, int? loverId = null)
{
Id = id;
Name = name;
LoverId = loverId;
PartitionKey = id.ToString();
RowKey = "__PERSON__"; // 思いつかないので決め打ち
}
public int Id { get; set; }
public string Name { get; set; }
// nullable な恋人 ID
public int? LoverId { get; set; }
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
}
public class Program
{
static async Task Main()
{
var tableClient = new TableClient("<ConnectionStrings>", "Person");
var filter = "LoverId eq null"; // Azure.RequestFailedException: 'One of the request inputs is not valid.
//var filter = "LoverId eq ''"; // 検索該当なし (プロパティがstring 型でも同様)
//var filter = "not(LoverId ne '')"; // これだとうまくいく
// クエリ
var queryResults = tableClient.QueryAsync<Person>(filter);
// 取得したものを一覧する
await foreach (var entity in queryResults)
{
Console.WriteLine($"{entity.Id}:{entity.Name}");
}
}
}
なぜ not(hoge ne ”) でプロパティがnullのエンティティを検索できるのか
正直分かりません。
おそらく、Azure Table Storage は 内部でエンティティを JSON に近い形式で保存していて、null のオブジェクトを Add しようとするとき、TableClient.AddEntity() が null のプロパティを書き出さないせいで、プロパティを検索しようとしたときに、そんなものねえよってなるんですかね
でも、エラーが One of the request inputs is not valid. だし、なんかクエリ自体が無効な記述なようなきもする。単に無いプロパティでフィルタしようとしてるから駄目だぜ!ってこと???
Odata詳しい方いたら教えてほしいです。
コメント