よく実装を忘れるのでメモ
DBで、複合的なデータの場合、最近はJSONを放り込んで管理しています。C#言語で、取得時にJSONをデコード、書き込み時にJSONをエンコードするための設定。マイグレが嫌いなので、手書きでかくことが多い。でも、よく忘れる。
例外が発生する(JSONオブジェクトが違う)場合の対処はどうすれ良いかは、まだ調査中。定義が違う場合とかね。
あと、受け取りたいパラメータが動的型になる場合はどうすればいいのかな。
WPのwp_metaみたいな構造をJSON化したいんだよね...(これは、また別の機会で)
前準備
JSONをデコード・エンコードするためのヘルパークラスを作成
JsonSerializeOptions の形式はお好きに改変する
public static class JsonConveter
{
/// <summary>
/// 日本語表記のままにして圧縮する
/// </summary>
public static JsonSerializerOptions jsonOptions = new JsonSerializerOptions
{
// Unicodeをそのままにする(エンコードすると文字数増えるので)
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
// スペースは余分な文字数が増えるので入れない
WriteIndented = false,
};
/// <summary>
/// オブジェクトをJSON文字列に変換する
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static string? ToStringJsonConvert<T>(this T? obj) =>
obj != null ? JsonSerializer.Serialize<T>(obj, jsonOptions) : null;
/// <summary>
/// 文字列を指定のオブジェクトに変換
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="json"></param>
/// <returns></returns>
public static T? ToObjectJsonConvert<T>(this string? json) =>
json != null ? JsonSerializer.Deserialize<T>(json) : default(T);
}
DbContextで定義
OnMOdelCreating オーバーライドメソッド内で、変換したいフィールドで定義する
利用するメソッドは、Entity<>()
メソッド、Property()
メソッド, HasConversion()
メソッドです
Entity<>()
メソッドで、対象のテーブルを指定します
Property()
メソッドで、対象のフィールドを指定します
HasConversion()
メソッドで、変換する形式を指定します
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Test>()
.Property(g => g.Prices)
.HasConversion(
c => c.ToStringJsonConvert<PricesJson>(),
c => c.ToObjectJsonConvert<PricesJson>());
}
HasConversion()
メソッドでは、
- 一つ目のアクション引数に、オブジェクトをJSON文字列に戻すためのコード
- 二つ目のアクション引数に、JSON文字列をオブジェクト変換するコード
を指定します。
これで、簡単にJSONをDBへ書き込み、読み込むことが出来ます。HasConversion
メソッドの処理を変えれば、他の方式でも可能ですね。
var item = db.Test.Select().First()
var price = item.PricesJson.Price;
var sale = item.PricesJson.SalePrice;
var add = new Test {
Name = "hogehoge",
Prices = new PricesJson {
Price = 10,
SalePrice = 5
}
}
db.Test.Add(add);
db.SaveChange();