2018年7月22日日曜日

DataReader で null 値を扱いやすくする


ADO.NET の DataReader でフィールドの値を取得するとき、null 値かどうかを考慮する必要があります。
// nullの場合は例外が発生する
int value = reader.GetInt32(0);

// IsDBNullメソッドで判断してから値を取得する
if (!reader.IsDBNull(0))
{
    int value = reader.GetInt32(0);
}

.NET Framework の初期バージョンでは nullable 構造体はありませんでしたので、DataReader には nullable 構造体を用いたメソッドはありません。その後のバージョンアップでもそのような機能は追加されていません。そのため、私は次のような拡張メソッドを定義しています。
public static int? GetInt32OrNull(this IDataRecord record, int index)
{
    if (record.IsDBNull(index)) { return null; }
    return record.GetInt32(index);
}

public static int GetInt32OrDefault(this IDataRecord record, int index)
{
    if (record.IsDBNull(index)) { return 0; }
    return record.GetInt32(index);
}

これらの拡張メソッドを用いると、フィールドの値の取得を簡潔かつタイプセーフに実装できます。
// nullable構造体で受け取る
int? value = reader.GetInt32OrNull(0);

// nullの場合には0が格納される
int value = reader.GetInt32OrDefault(0);


拡張メソッドでなくユーティリティメソッドにする場合は次のようにします。
public static class DataRecordUtility
{
    public static int? GetInt32OrNull(IDataRecord record, int index)
    {
        if (record.IsDBNull(index)) { return null; }
        return record.GetInt32(index);
    }

    public static int GetInt32OrDefault(IDataRecord record, int index)
    {
        if (record.IsDBNull(index)) { return 0; }
        return record.GetInt32(index);
    }
}

// nullable構造体で受け取る
int? value = DataRecordUtility.GetInt32OrNull(reader, 0);

// nullの場合には0が格納される
int value = DataRecordUtility.GetInt32OrDefault(reader, 0);


なぜ今更このような記事を書いたかというと、今でも nullable 構造体が活用されていないソースコードを見かけることが少なくないためです。 .NET Framework 1 時代やそれよりも前(VisualBasic)のソースコードを流用した開発が繰り返され、その間に積極的な改善や工夫が行われないまま今に至っていることが原因にあると考えています。 そのようなソースコードでは null の可能性がある数値や日付を object 型や string 型で表しており、それによって型変換エラーやパフォーマンスの劣化を引き起こしていたりします。

List<T> などのジェネリックコレクションではなく ArrayList が使われ続けていたりするのも同じような原因だと思います。この記事を見て思い当たる節があるプログラマーの方は少し視野を拡げてみてください。その分のリターンは十分に得られると思います。

2018年7月16日月曜日

今一度 ADO.NET について考えてみる

.NET のデータアクセス API である ADO.NET について、私が普段考えていること実施していることをまとめてみます。


2018年5月19日土曜日

gRPC (C#) に追加されたインターセプターの使用方法

「試験的」と銘打たれてはいますが、gRPC C# 1.10 でインターセプターが追加されました。どのように使うのかを確認してみました。

gRPC 1.12.0 がリリースされていました

5/16 に gRPC 1.12.0 がリリースされました。大きな機能追加はないものの、最近リリース間隔が短くなってきています。

2018年5月12日土曜日

gRPC ヘルパーライブラリ(C#)に機能を追加しました


先日公開した gRPC のヘルパーライブラリに機能を追加しました。

  1. ASP.NET Core 用の HttpGateway
  2. 任意のサービスに Heartbeat 用メソッドを追加する機能
  3. 拡張メソッドの追加

1. ASP.NET Core 用の HttpGateway


JSON で受け取ったリクエストをデシリアライズして RPC メソッドを呼び出し、レスポンスを JSON にシリアライズしてクライアントへ返します。
ストリーミングには対応していません。ServerStreaming, DuplexStreaming ではリクエストの配列をシリアライズした JSON を受け取り、ClientStreaming, DuplexStreaming ではレスポンスの配列をシリアライズした JSON を返します。


2. 任意のサービスに Heartbeat 用メソッドを追加する機能


DuplexStreaming による Heartbeat を行うためのメソッドをサービスに追加することができる機能と、そのメソッドをクライアントから簡単に呼び出せる機能を追加します。


3. 拡張メソッドの追加


AsyncClientStreamingCall, AsyncServerStreamingCall, AsyncDuplexStreamingCall のレスポンスを別の型にコンバートしてから実行結果として返すメソッドなど、新たな拡張メソッドを追加します。


GitHub

https://github.com/mxProject/gRPCHelper

NuGet Gallery

mxProject.Helpers.Grpc.Common:共通ライブラリ
mxProject.Helpers.Grpc.Client:クライアント用ライブラリ
mxProject.Helpers.Grpc.Server:サーバー用ライブラリ
mxProject.Helpers.Grpc.AspNetGateway:ASP.NET Core 用 HttpGateway ライブラリ


2018年5月7日月曜日

Protocol Buffers オブジェクトを MongoDB に格納する 2

Protocol Buffers の IDL で定義された型のオブジェクトを MongoDB に格納できるかどうかを検証しています。前回 に続き、今回は Map や Any について調べました。
MongoDB 公式の C# 実装である MongoDB.Driver (2.5.1) を使用しています。

2018年5月2日水曜日

Protocol Buffers オブジェクトを MongoDB に格納する


Protocol Buffers の IDL で定義された型のオブジェクトを MongoDB に格納できるかどうかを検証しています。gRPC で受け取ったオブジェクトをそのまま MongoDB に格納するようなストーリーを想定しています。
単純な型であれば特に問題なく格納できるのですが、やはりいろいろな前提や制限があるようです。

paiza のスキルチェックをやってみました

いまさら感はありますが、 paiza のスキルチェックをやってみました。指定された時間内にコードを書いてユニットテストにかけ、その結果を基に評価を数値化してくれるというものですが、ゲーム感覚で空き時間を見つけて進めていこうと考えています。 どうやら時間が短いほど高い評価を得...