[{"data":1,"prerenderedAt":3557},["ShallowReactive",2],{"content-query-dHukI9lKsv":3,"link-card-/articles/tech/blazor/messagepack-pim-format":3554},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"rowTypeId":18,"sitemap":19,"body":20,"_type":3548,"_id":3549,"_source":3550,"_file":3551,"_stem":3552,"_extension":3553},"/articles/tech/blazor/indexeddb-blazor-interop","blazor",false,"","C#オブジェクトがIndexedDBに着くまで｜Blazor WASM永続化のデータ形式の旅","Blazor WebAssembly で C# のオブジェクトを IndexedDB に保存する際、データは MessagePack バイナリや Uint8Array と形を変えながら各レイヤーを通過します。PICOMでの実装を例に、境界ごとの責務分担と keyPath なしストア設計を解説します。","2026-04-20",[12,13,14,15,16,17],"Blazor","WebAssembly","IndexedDB","JS Interop","C#","PICOM",1,{"loc":4,"lastmod":10,"priority":18},{"type":21,"children":22,"toc":3531},"root",[23,31,54,67,107,112,117,151,156,162,197,689,730,736,741,750,755,909,934,940,951,985,998,1554,1582,1628,1634,1670,1683,2028,2040,2189,2194,2200,2225,2231,2249,2439,2457,2491,2569,2574,2580,2585,2875,2880,2889,2894,2906,2932,3057,3078,3465,3470,3521,3525],{"type":24,"tag":25,"props":26,"children":28},"element","h2",{"id":27},"はじめに",[29],{"type":30,"value":27},"text",{"type":24,"tag":32,"props":33,"children":34},"p",{},[35,37,43,45,52],{"type":30,"value":36},"PICOMはオフラインで動く楽譜エディタなので、楽曲データはブラウザ内の",{"type":24,"tag":38,"props":39,"children":41},"tooltip",{"content":40},"ブラウザに組み込まれたNoSQLデータベース。構造化データやバイナリを大量に保存できる",[42],{"type":30,"value":14},{"type":30,"value":44},"に保存しています。C#の ",{"type":24,"tag":46,"props":47,"children":49},"code",{"className":48},[],[50],{"type":30,"value":51},"Music",{"type":30,"value":53}," オブジェクトをそこまで落とすには、データは何段階かの形式変換を経る必要があります。",{"type":24,"tag":32,"props":55,"children":56},{},[57,59,65],{"type":30,"value":58},"この記事では、書き込み経路を追いながら、",{"type":24,"tag":60,"props":61,"children":62},"strong",{},[63],{"type":30,"value":64},"データがどういう姿で各レイヤーを通過し、C#/JS境界で誰が何に責任を持っているか",{"type":30,"value":66},"を解説します。",{"type":24,"tag":68,"props":69,"children":70},"summary-box",{},[71],{"type":24,"tag":32,"props":72,"children":73},{},[74,76,81,83,89,91,97,99,105],{"type":30,"value":75},"C#の ",{"type":24,"tag":46,"props":77,"children":79},{"className":78},[],[80],{"type":30,"value":51},{"type":30,"value":82}," は「MessagePackモデル → ",{"type":24,"tag":46,"props":84,"children":86},{"className":85},[],[87],{"type":30,"value":88},"byte[]",{"type":30,"value":90}," → (C#/JS境界) → ",{"type":24,"tag":46,"props":92,"children":94},{"className":93},[],[95],{"type":30,"value":96},"Uint8Array",{"type":30,"value":98}," → IndexedDB」のレイヤーを経て永続化されます。各境界の責務分担、",{"type":24,"tag":46,"props":100,"children":102},{"className":101},[],[103],{"type":30,"value":104},"keyPath",{"type":30,"value":106},"なしでストアを設計した理由などを解説します。",{"type":24,"tag":25,"props":108,"children":110},{"id":109},"データの旅の全体像",[111],{"type":30,"value":109},{"type":24,"tag":32,"props":113,"children":114},{},[115],{"type":30,"value":116},"書き込み時、楽曲データが通過する形式の変化を示します。",{"type":24,"tag":118,"props":119,"children":120},"ol",{},[121,127,132,141,146],{"type":24,"tag":122,"props":123,"children":124},"li",{},[125],{"type":30,"value":126},"C# Music (ドメイン)",{"type":24,"tag":122,"props":128,"children":129},{},[130],{"type":30,"value":131},"C# MusicDataModel (MessagePack用のオブジェクト)",{"type":24,"tag":122,"props":133,"children":134},{},[135,137],{"type":30,"value":136},"C# byte",{"type":24,"tag":138,"props":139,"children":140},"span",{},[],{"type":24,"tag":122,"props":142,"children":143},{},[144],{"type":30,"value":145},"JS Uint8Array",{"type":24,"tag":122,"props":147,"children":148},{},[149],{"type":30,"value":150},"IndexedDB musics ストア",{"type":24,"tag":32,"props":152,"children":153},{},[154],{"type":30,"value":155},"読み込みはこの逆順です。以降、各レイヤーで何が起きているかを順に追います。",{"type":24,"tag":25,"props":157,"children":159},{"id":158},"レイヤー1-ドメインオブジェクト-messagepackモデル",[160],{"type":30,"value":161},"レイヤー1 ドメインオブジェクト → MessagePackモデル",{"type":24,"tag":32,"props":163,"children":164},{},[165,167,172,174,180,182,187,189,195],{"type":30,"value":166},"出発点の ",{"type":24,"tag":46,"props":168,"children":170},{"className":169},[],[171],{"type":30,"value":51},{"type":30,"value":173}," クラスは ",{"type":24,"tag":46,"props":175,"children":177},{"className":176},[],[178],{"type":30,"value":179},"ObservableObject",{"type":30,"value":181}," を継承していて、プロパティ変更通知やイベント、他のドメインオブジェクトへの参照を持ちます。このまま直列化するとイベント購読の内部状態まで引きずってしまうので、",{"type":24,"tag":60,"props":183,"children":184},{},[185],{"type":30,"value":186},"シリアライズ専用のDTO",{"type":30,"value":188},"に詰め直します。それが ",{"type":24,"tag":46,"props":190,"children":192},{"className":191},[],[193],{"type":30,"value":194},"MusicDataModel",{"type":30,"value":196}," です。",{"type":24,"tag":198,"props":199,"children":203},"pre",{"className":200,"code":201,"language":202,"meta":7,"style":7},"language-csharp shiki shiki-themes vitesse-dark","private static MusicDataModel ToDataModel(Music music)\n{\n    return new MusicDataModel\n    {\n        Version = 3,\n        Id = music.Id,\n        Metadata = new MusicMetadataModel\n        {\n            Title = music.Metadata.Title,\n            LastModified = DateTime.UtcNow,\n        },\n        Settings = new MusicSettingsModel\n        {\n            Tempo = music.Settings.Tempo,\n            Numerator = music.Settings.Numerator,\n            Denominator = music.Settings.Denominator,\n        },\n        Tracks = music.Tracks.Select(TrackToV2).ToArray(),\n    };\n}\n","csharp",[204],{"type":24,"tag":46,"props":205,"children":206},{"__ignoreMap":7},[207,254,263,283,292,318,349,371,380,419,450,459,481,489,528,566,604,612,671,680],{"type":24,"tag":138,"props":208,"children":210},{"class":209,"line":18},"line",[211,217,222,228,234,240,244,249],{"type":24,"tag":138,"props":212,"children":214},{"style":213},"--shiki-default:#CB7676",[215],{"type":30,"value":216},"private",{"type":24,"tag":138,"props":218,"children":219},{"style":213},[220],{"type":30,"value":221}," static",{"type":24,"tag":138,"props":223,"children":225},{"style":224},"--shiki-default:#5DA994",[226],{"type":30,"value":227}," MusicDataModel",{"type":24,"tag":138,"props":229,"children":231},{"style":230},"--shiki-default:#80A665",[232],{"type":30,"value":233}," ToDataModel",{"type":24,"tag":138,"props":235,"children":237},{"style":236},"--shiki-default:#666666",[238],{"type":30,"value":239},"(",{"type":24,"tag":138,"props":241,"children":242},{"style":224},[243],{"type":30,"value":51},{"type":24,"tag":138,"props":245,"children":246},{"style":230},[247],{"type":30,"value":248}," music",{"type":24,"tag":138,"props":250,"children":251},{"style":236},[252],{"type":30,"value":253},")\n",{"type":24,"tag":138,"props":255,"children":257},{"class":209,"line":256},2,[258],{"type":24,"tag":138,"props":259,"children":260},{"style":236},[261],{"type":30,"value":262},"{\n",{"type":24,"tag":138,"props":264,"children":266},{"class":209,"line":265},3,[267,273,278],{"type":24,"tag":138,"props":268,"children":270},{"style":269},"--shiki-default:#4D9375",[271],{"type":30,"value":272},"    return",{"type":24,"tag":138,"props":274,"children":275},{"style":213},[276],{"type":30,"value":277}," new",{"type":24,"tag":138,"props":279,"children":280},{"style":224},[281],{"type":30,"value":282}," MusicDataModel\n",{"type":24,"tag":138,"props":284,"children":286},{"class":209,"line":285},4,[287],{"type":24,"tag":138,"props":288,"children":289},{"style":236},[290],{"type":30,"value":291},"    {\n",{"type":24,"tag":138,"props":293,"children":295},{"class":209,"line":294},5,[296,302,307,313],{"type":24,"tag":138,"props":297,"children":299},{"style":298},"--shiki-default:#BD976A",[300],{"type":30,"value":301},"        Version",{"type":24,"tag":138,"props":303,"children":304},{"style":236},[305],{"type":30,"value":306}," =",{"type":24,"tag":138,"props":308,"children":310},{"style":309},"--shiki-default:#4C9A91",[311],{"type":30,"value":312}," 3",{"type":24,"tag":138,"props":314,"children":315},{"style":236},[316],{"type":30,"value":317},",\n",{"type":24,"tag":138,"props":319,"children":321},{"class":209,"line":320},6,[322,327,331,335,340,345],{"type":24,"tag":138,"props":323,"children":324},{"style":298},[325],{"type":30,"value":326},"        Id",{"type":24,"tag":138,"props":328,"children":329},{"style":236},[330],{"type":30,"value":306},{"type":24,"tag":138,"props":332,"children":333},{"style":298},[334],{"type":30,"value":248},{"type":24,"tag":138,"props":336,"children":337},{"style":236},[338],{"type":30,"value":339},".",{"type":24,"tag":138,"props":341,"children":342},{"style":298},[343],{"type":30,"value":344},"Id",{"type":24,"tag":138,"props":346,"children":347},{"style":236},[348],{"type":30,"value":317},{"type":24,"tag":138,"props":350,"children":352},{"class":209,"line":351},7,[353,358,362,366],{"type":24,"tag":138,"props":354,"children":355},{"style":298},[356],{"type":30,"value":357},"        Metadata",{"type":24,"tag":138,"props":359,"children":360},{"style":236},[361],{"type":30,"value":306},{"type":24,"tag":138,"props":363,"children":364},{"style":213},[365],{"type":30,"value":277},{"type":24,"tag":138,"props":367,"children":368},{"style":224},[369],{"type":30,"value":370}," MusicMetadataModel\n",{"type":24,"tag":138,"props":372,"children":374},{"class":209,"line":373},8,[375],{"type":24,"tag":138,"props":376,"children":377},{"style":236},[378],{"type":30,"value":379},"        {\n",{"type":24,"tag":138,"props":381,"children":383},{"class":209,"line":382},9,[384,389,393,397,401,406,410,415],{"type":24,"tag":138,"props":385,"children":386},{"style":298},[387],{"type":30,"value":388},"            Title",{"type":24,"tag":138,"props":390,"children":391},{"style":236},[392],{"type":30,"value":306},{"type":24,"tag":138,"props":394,"children":395},{"style":298},[396],{"type":30,"value":248},{"type":24,"tag":138,"props":398,"children":399},{"style":236},[400],{"type":30,"value":339},{"type":24,"tag":138,"props":402,"children":403},{"style":298},[404],{"type":30,"value":405},"Metadata",{"type":24,"tag":138,"props":407,"children":408},{"style":236},[409],{"type":30,"value":339},{"type":24,"tag":138,"props":411,"children":412},{"style":298},[413],{"type":30,"value":414},"Title",{"type":24,"tag":138,"props":416,"children":417},{"style":236},[418],{"type":30,"value":317},{"type":24,"tag":138,"props":420,"children":422},{"class":209,"line":421},10,[423,428,432,437,441,446],{"type":24,"tag":138,"props":424,"children":425},{"style":298},[426],{"type":30,"value":427},"            LastModified",{"type":24,"tag":138,"props":429,"children":430},{"style":236},[431],{"type":30,"value":306},{"type":24,"tag":138,"props":433,"children":434},{"style":298},[435],{"type":30,"value":436}," DateTime",{"type":24,"tag":138,"props":438,"children":439},{"style":236},[440],{"type":30,"value":339},{"type":24,"tag":138,"props":442,"children":443},{"style":298},[444],{"type":30,"value":445},"UtcNow",{"type":24,"tag":138,"props":447,"children":448},{"style":236},[449],{"type":30,"value":317},{"type":24,"tag":138,"props":451,"children":453},{"class":209,"line":452},11,[454],{"type":24,"tag":138,"props":455,"children":456},{"style":236},[457],{"type":30,"value":458},"        },\n",{"type":24,"tag":138,"props":460,"children":462},{"class":209,"line":461},12,[463,468,472,476],{"type":24,"tag":138,"props":464,"children":465},{"style":298},[466],{"type":30,"value":467},"        Settings",{"type":24,"tag":138,"props":469,"children":470},{"style":236},[471],{"type":30,"value":306},{"type":24,"tag":138,"props":473,"children":474},{"style":213},[475],{"type":30,"value":277},{"type":24,"tag":138,"props":477,"children":478},{"style":224},[479],{"type":30,"value":480}," MusicSettingsModel\n",{"type":24,"tag":138,"props":482,"children":484},{"class":209,"line":483},13,[485],{"type":24,"tag":138,"props":486,"children":487},{"style":236},[488],{"type":30,"value":379},{"type":24,"tag":138,"props":490,"children":492},{"class":209,"line":491},14,[493,498,502,506,510,515,519,524],{"type":24,"tag":138,"props":494,"children":495},{"style":298},[496],{"type":30,"value":497},"            Tempo",{"type":24,"tag":138,"props":499,"children":500},{"style":236},[501],{"type":30,"value":306},{"type":24,"tag":138,"props":503,"children":504},{"style":298},[505],{"type":30,"value":248},{"type":24,"tag":138,"props":507,"children":508},{"style":236},[509],{"type":30,"value":339},{"type":24,"tag":138,"props":511,"children":512},{"style":298},[513],{"type":30,"value":514},"Settings",{"type":24,"tag":138,"props":516,"children":517},{"style":236},[518],{"type":30,"value":339},{"type":24,"tag":138,"props":520,"children":521},{"style":298},[522],{"type":30,"value":523},"Tempo",{"type":24,"tag":138,"props":525,"children":526},{"style":236},[527],{"type":30,"value":317},{"type":24,"tag":138,"props":529,"children":531},{"class":209,"line":530},15,[532,537,541,545,549,553,557,562],{"type":24,"tag":138,"props":533,"children":534},{"style":298},[535],{"type":30,"value":536},"            Numerator",{"type":24,"tag":138,"props":538,"children":539},{"style":236},[540],{"type":30,"value":306},{"type":24,"tag":138,"props":542,"children":543},{"style":298},[544],{"type":30,"value":248},{"type":24,"tag":138,"props":546,"children":547},{"style":236},[548],{"type":30,"value":339},{"type":24,"tag":138,"props":550,"children":551},{"style":298},[552],{"type":30,"value":514},{"type":24,"tag":138,"props":554,"children":555},{"style":236},[556],{"type":30,"value":339},{"type":24,"tag":138,"props":558,"children":559},{"style":298},[560],{"type":30,"value":561},"Numerator",{"type":24,"tag":138,"props":563,"children":564},{"style":236},[565],{"type":30,"value":317},{"type":24,"tag":138,"props":567,"children":569},{"class":209,"line":568},16,[570,575,579,583,587,591,595,600],{"type":24,"tag":138,"props":571,"children":572},{"style":298},[573],{"type":30,"value":574},"            Denominator",{"type":24,"tag":138,"props":576,"children":577},{"style":236},[578],{"type":30,"value":306},{"type":24,"tag":138,"props":580,"children":581},{"style":298},[582],{"type":30,"value":248},{"type":24,"tag":138,"props":584,"children":585},{"style":236},[586],{"type":30,"value":339},{"type":24,"tag":138,"props":588,"children":589},{"style":298},[590],{"type":30,"value":514},{"type":24,"tag":138,"props":592,"children":593},{"style":236},[594],{"type":30,"value":339},{"type":24,"tag":138,"props":596,"children":597},{"style":298},[598],{"type":30,"value":599},"Denominator",{"type":24,"tag":138,"props":601,"children":602},{"style":236},[603],{"type":30,"value":317},{"type":24,"tag":138,"props":605,"children":607},{"class":209,"line":606},17,[608],{"type":24,"tag":138,"props":609,"children":610},{"style":236},[611],{"type":30,"value":458},{"type":24,"tag":138,"props":613,"children":615},{"class":209,"line":614},18,[616,621,625,629,633,638,642,647,651,656,661,666],{"type":24,"tag":138,"props":617,"children":618},{"style":298},[619],{"type":30,"value":620},"        Tracks",{"type":24,"tag":138,"props":622,"children":623},{"style":236},[624],{"type":30,"value":306},{"type":24,"tag":138,"props":626,"children":627},{"style":298},[628],{"type":30,"value":248},{"type":24,"tag":138,"props":630,"children":631},{"style":236},[632],{"type":30,"value":339},{"type":24,"tag":138,"props":634,"children":635},{"style":298},[636],{"type":30,"value":637},"Tracks",{"type":24,"tag":138,"props":639,"children":640},{"style":236},[641],{"type":30,"value":339},{"type":24,"tag":138,"props":643,"children":644},{"style":230},[645],{"type":30,"value":646},"Select",{"type":24,"tag":138,"props":648,"children":649},{"style":236},[650],{"type":30,"value":239},{"type":24,"tag":138,"props":652,"children":653},{"style":298},[654],{"type":30,"value":655},"TrackToV2",{"type":24,"tag":138,"props":657,"children":658},{"style":236},[659],{"type":30,"value":660},").",{"type":24,"tag":138,"props":662,"children":663},{"style":230},[664],{"type":30,"value":665},"ToArray",{"type":24,"tag":138,"props":667,"children":668},{"style":236},[669],{"type":30,"value":670},"(),\n",{"type":24,"tag":138,"props":672,"children":674},{"class":209,"line":673},19,[675],{"type":24,"tag":138,"props":676,"children":677},{"style":236},[678],{"type":30,"value":679},"    };\n",{"type":24,"tag":138,"props":681,"children":683},{"class":209,"line":682},20,[684],{"type":24,"tag":138,"props":685,"children":686},{"style":236},[687],{"type":30,"value":688},"}\n",{"type":24,"tag":32,"props":690,"children":691},{},[692,697,699,705,707,713,715,720,722,728],{"type":24,"tag":46,"props":693,"children":695},{"className":694},[],[696],{"type":30,"value":194},{"type":30,"value":698}," は ",{"type":24,"tag":46,"props":700,"children":702},{"className":701},[],[703],{"type":30,"value":704},"[MessagePackObject]",{"type":30,"value":706}," 属性を持ち、各フィールドが ",{"type":24,"tag":46,"props":708,"children":710},{"className":709},[],[711],{"type":30,"value":712},"[Key(n)]",{"type":30,"value":714}," で番号付けされます。ドメイン側の ",{"type":24,"tag":46,"props":716,"children":718},{"className":717},[],[719],{"type":30,"value":51},{"type":30,"value":721}," は永続化の都合を一切知らず、",{"type":24,"tag":46,"props":723,"children":725},{"className":724},[],[726],{"type":30,"value":727},"PIMRepository",{"type":30,"value":729}," という永続化層がこの変換の責任だけを負います。",{"type":24,"tag":731,"props":732,"children":734},"h3",{"id":733},"なぜドメインモデルを直接永続化しないか",[735],{"type":30,"value":733},{"type":24,"tag":32,"props":737,"children":738},{},[739],{"type":30,"value":740},"ドメインモデルの変化のサイクルと保存形式のデータ構造変化のサイクルは異なるからです。\n例えば、保存に適したデータ構造へ変更したい場合を考えます。分離していないとドメインモデルを直接改良する必要がありますが、分離していれば DTO と詰め替え処理の改善だけで済みます。\nこうすることで、インフラレイヤの変更がドメインレイヤへ波及することを防ぐことができます。",{"type":24,"tag":25,"props":742,"children":744},{"id":743},"レイヤー2-messagepackモデル-byte",[745,747],{"type":30,"value":746},"レイヤー2 MessagePackモデル → byte",{"type":24,"tag":138,"props":748,"children":749},{},[],{"type":24,"tag":32,"props":751,"children":752},{},[753],{"type":30,"value":754},"ここは一行で終わります。",{"type":24,"tag":198,"props":756,"children":758},{"className":200,"code":757,"language":202,"meta":7,"style":7},"public byte[] Write(Music music)\n{\n    var model = ToDataModel(music);\n    var bin = MessagePackSerializer.Serialize(model);\n    return bin;\n}\n",[759],{"type":24,"tag":46,"props":760,"children":761},{"__ignoreMap":7},[762,801,808,843,886,902],{"type":24,"tag":138,"props":763,"children":764},{"class":209,"line":18},[765,770,775,780,785,789,793,797],{"type":24,"tag":138,"props":766,"children":767},{"style":213},[768],{"type":30,"value":769},"public",{"type":24,"tag":138,"props":771,"children":772},{"style":269},[773],{"type":30,"value":774}," byte",{"type":24,"tag":138,"props":776,"children":777},{"style":236},[778],{"type":30,"value":779},"[]",{"type":24,"tag":138,"props":781,"children":782},{"style":230},[783],{"type":30,"value":784}," Write",{"type":24,"tag":138,"props":786,"children":787},{"style":236},[788],{"type":30,"value":239},{"type":24,"tag":138,"props":790,"children":791},{"style":224},[792],{"type":30,"value":51},{"type":24,"tag":138,"props":794,"children":795},{"style":230},[796],{"type":30,"value":248},{"type":24,"tag":138,"props":798,"children":799},{"style":236},[800],{"type":30,"value":253},{"type":24,"tag":138,"props":802,"children":803},{"class":209,"line":256},[804],{"type":24,"tag":138,"props":805,"children":806},{"style":236},[807],{"type":30,"value":262},{"type":24,"tag":138,"props":809,"children":810},{"class":209,"line":265},[811,816,821,825,829,833,838],{"type":24,"tag":138,"props":812,"children":813},{"style":213},[814],{"type":30,"value":815},"    var",{"type":24,"tag":138,"props":817,"children":818},{"style":230},[819],{"type":30,"value":820}," model",{"type":24,"tag":138,"props":822,"children":823},{"style":236},[824],{"type":30,"value":306},{"type":24,"tag":138,"props":826,"children":827},{"style":230},[828],{"type":30,"value":233},{"type":24,"tag":138,"props":830,"children":831},{"style":236},[832],{"type":30,"value":239},{"type":24,"tag":138,"props":834,"children":835},{"style":298},[836],{"type":30,"value":837},"music",{"type":24,"tag":138,"props":839,"children":840},{"style":236},[841],{"type":30,"value":842},");\n",{"type":24,"tag":138,"props":844,"children":845},{"class":209,"line":285},[846,850,855,859,864,868,873,877,882],{"type":24,"tag":138,"props":847,"children":848},{"style":213},[849],{"type":30,"value":815},{"type":24,"tag":138,"props":851,"children":852},{"style":230},[853],{"type":30,"value":854}," bin",{"type":24,"tag":138,"props":856,"children":857},{"style":236},[858],{"type":30,"value":306},{"type":24,"tag":138,"props":860,"children":861},{"style":298},[862],{"type":30,"value":863}," MessagePackSerializer",{"type":24,"tag":138,"props":865,"children":866},{"style":236},[867],{"type":30,"value":339},{"type":24,"tag":138,"props":869,"children":870},{"style":230},[871],{"type":30,"value":872},"Serialize",{"type":24,"tag":138,"props":874,"children":875},{"style":236},[876],{"type":30,"value":239},{"type":24,"tag":138,"props":878,"children":879},{"style":298},[880],{"type":30,"value":881},"model",{"type":24,"tag":138,"props":883,"children":884},{"style":236},[885],{"type":30,"value":842},{"type":24,"tag":138,"props":887,"children":888},{"class":209,"line":294},[889,893,897],{"type":24,"tag":138,"props":890,"children":891},{"style":269},[892],{"type":30,"value":272},{"type":24,"tag":138,"props":894,"children":895},{"style":298},[896],{"type":30,"value":854},{"type":24,"tag":138,"props":898,"children":899},{"style":236},[900],{"type":30,"value":901},";\n",{"type":24,"tag":138,"props":903,"children":904},{"class":209,"line":320},[905],{"type":24,"tag":138,"props":906,"children":907},{"style":236},[908],{"type":30,"value":688},{"type":24,"tag":32,"props":910,"children":911},{},[912,918,920,925,927,932],{"type":24,"tag":46,"props":913,"children":915},{"className":914},[],[916],{"type":30,"value":917},"MessagePackSerializer.Serialize",{"type":30,"value":919}," が ",{"type":24,"tag":46,"props":921,"children":923},{"className":922},[],[924],{"type":30,"value":194},{"type":30,"value":926}," を純粋な ",{"type":24,"tag":46,"props":928,"children":930},{"className":929},[],[931],{"type":30,"value":88},{"type":30,"value":933}," に落とします。ここまでは完全にC#内で完結する話で、interopの世界にはまだ触れていません。なぜJSONではなくMessagePackを選んだのかや、バージョニング戦略は、別記事で詳しく書いているのでそちらを参照してください。",{"type":24,"tag":935,"props":936,"children":939},"link-card",{"label":937,"to":938},"MessagePackで独自バイナリフォーマットをバージョン管理する話はこちら⬇️","/articles/tech/blazor/messagepack-pim-format",[],{"type":24,"tag":25,"props":941,"children":943},{"id":942},"レイヤー3-cjs境界を越える-byteを直接渡す",[944,946,949],{"type":30,"value":945},"レイヤー3 C#/JS境界を越える — byte",{"type":24,"tag":138,"props":947,"children":948},{},[],{"type":30,"value":950},"を直接渡す",{"type":24,"tag":32,"props":952,"children":953},{},[954,956,962,964,969,971,983],{"type":30,"value":955},"ここが記事の中心です。PICOMは.NET 10のBlazor WebAssemblyで動いているので、",{"type":24,"tag":46,"props":957,"children":959},{"className":958},[],[960],{"type":30,"value":961},"IJSRuntime.InvokeVoidAsync",{"type":30,"value":963}," の引数に ",{"type":24,"tag":46,"props":965,"children":967},{"className":966},[],[968],{"type":30,"value":88},{"type":30,"value":970}," を渡すと、",{"type":24,"tag":60,"props":972,"children":973},{},[974,976,981],{"type":30,"value":975},"JSON経由ではなく ",{"type":24,"tag":46,"props":977,"children":979},{"className":978},[],[980],{"type":30,"value":96},{"type":30,"value":982}," として直接",{"type":30,"value":984},"渡されます。これは.NET 6からの機能で、Base64で文字列化する必要はありません。",{"type":24,"tag":32,"props":986,"children":987},{},[988,990,996],{"type":30,"value":989},"境界を越えるコードは ",{"type":24,"tag":46,"props":991,"children":993},{"className":992},[],[994],{"type":30,"value":995},"MusicsDataBase",{"type":30,"value":997}," クラスにあります。",{"type":24,"tag":198,"props":999,"children":1001},{"className":200,"code":1000,"language":202,"meta":7,"style":7},"public class MusicsDataBase(IJSRuntime js)\n{\n    private readonly IJSRuntime _js = js;\n    private IJSObjectReference? _db;\n\n    private async Task\u003CIJSObjectReference> EnsureDbAsync()\n    {\n        if (_db is null)\n        {\n            var dbModule = await _js.InvokeAsync\u003CIJSObjectReference>(\"import\", \"/db.js\");\n            _db = await dbModule.InvokeAsync\u003CIJSObjectReference>(\"useDatabase\");\n        }\n        return _db;\n    }\n\n    public async Task SetAsync(int musicId, byte[] pimData)\n    {\n        var db = await EnsureDbAsync();\n        await db.InvokeVoidAsync(\"setItem\", musicId, pimData);\n    }\n}\n",[1002],{"type":24,"tag":46,"props":1003,"children":1004},{"__ignoreMap":7},[1005,1040,1047,1082,1108,1117,1159,1166,1198,1205,1292,1349,1357,1373,1381,1388,1444,1451,1481,1539,1546],{"type":24,"tag":138,"props":1006,"children":1007},{"class":209,"line":18},[1008,1012,1017,1022,1026,1031,1036],{"type":24,"tag":138,"props":1009,"children":1010},{"style":213},[1011],{"type":30,"value":769},{"type":24,"tag":138,"props":1013,"children":1014},{"style":213},[1015],{"type":30,"value":1016}," class",{"type":24,"tag":138,"props":1018,"children":1019},{"style":224},[1020],{"type":30,"value":1021}," MusicsDataBase",{"type":24,"tag":138,"props":1023,"children":1024},{"style":236},[1025],{"type":30,"value":239},{"type":24,"tag":138,"props":1027,"children":1028},{"style":224},[1029],{"type":30,"value":1030},"IJSRuntime",{"type":24,"tag":138,"props":1032,"children":1033},{"style":230},[1034],{"type":30,"value":1035}," js",{"type":24,"tag":138,"props":1037,"children":1038},{"style":236},[1039],{"type":30,"value":253},{"type":24,"tag":138,"props":1041,"children":1042},{"class":209,"line":256},[1043],{"type":24,"tag":138,"props":1044,"children":1045},{"style":236},[1046],{"type":30,"value":262},{"type":24,"tag":138,"props":1048,"children":1049},{"class":209,"line":265},[1050,1055,1060,1065,1070,1074,1078],{"type":24,"tag":138,"props":1051,"children":1052},{"style":213},[1053],{"type":30,"value":1054},"    private",{"type":24,"tag":138,"props":1056,"children":1057},{"style":213},[1058],{"type":30,"value":1059}," readonly",{"type":24,"tag":138,"props":1061,"children":1062},{"style":224},[1063],{"type":30,"value":1064}," IJSRuntime",{"type":24,"tag":138,"props":1066,"children":1067},{"style":230},[1068],{"type":30,"value":1069}," _js",{"type":24,"tag":138,"props":1071,"children":1072},{"style":236},[1073],{"type":30,"value":306},{"type":24,"tag":138,"props":1075,"children":1076},{"style":298},[1077],{"type":30,"value":1035},{"type":24,"tag":138,"props":1079,"children":1080},{"style":236},[1081],{"type":30,"value":901},{"type":24,"tag":138,"props":1083,"children":1084},{"class":209,"line":285},[1085,1089,1094,1099,1104],{"type":24,"tag":138,"props":1086,"children":1087},{"style":213},[1088],{"type":30,"value":1054},{"type":24,"tag":138,"props":1090,"children":1091},{"style":224},[1092],{"type":30,"value":1093}," IJSObjectReference",{"type":24,"tag":138,"props":1095,"children":1096},{"style":236},[1097],{"type":30,"value":1098},"?",{"type":24,"tag":138,"props":1100,"children":1101},{"style":230},[1102],{"type":30,"value":1103}," _db",{"type":24,"tag":138,"props":1105,"children":1106},{"style":236},[1107],{"type":30,"value":901},{"type":24,"tag":138,"props":1109,"children":1110},{"class":209,"line":294},[1111],{"type":24,"tag":138,"props":1112,"children":1114},{"emptyLinePlaceholder":1113},true,[1115],{"type":30,"value":1116},"\n",{"type":24,"tag":138,"props":1118,"children":1119},{"class":209,"line":320},[1120,1124,1129,1134,1139,1144,1149,1154],{"type":24,"tag":138,"props":1121,"children":1122},{"style":213},[1123],{"type":30,"value":1054},{"type":24,"tag":138,"props":1125,"children":1126},{"style":213},[1127],{"type":30,"value":1128}," async",{"type":24,"tag":138,"props":1130,"children":1131},{"style":224},[1132],{"type":30,"value":1133}," Task",{"type":24,"tag":138,"props":1135,"children":1136},{"style":236},[1137],{"type":30,"value":1138},"\u003C",{"type":24,"tag":138,"props":1140,"children":1141},{"style":224},[1142],{"type":30,"value":1143},"IJSObjectReference",{"type":24,"tag":138,"props":1145,"children":1146},{"style":236},[1147],{"type":30,"value":1148},">",{"type":24,"tag":138,"props":1150,"children":1151},{"style":230},[1152],{"type":30,"value":1153}," EnsureDbAsync",{"type":24,"tag":138,"props":1155,"children":1156},{"style":236},[1157],{"type":30,"value":1158},"()\n",{"type":24,"tag":138,"props":1160,"children":1161},{"class":209,"line":351},[1162],{"type":24,"tag":138,"props":1163,"children":1164},{"style":236},[1165],{"type":30,"value":291},{"type":24,"tag":138,"props":1167,"children":1168},{"class":209,"line":373},[1169,1174,1179,1184,1189,1194],{"type":24,"tag":138,"props":1170,"children":1171},{"style":269},[1172],{"type":30,"value":1173},"        if",{"type":24,"tag":138,"props":1175,"children":1176},{"style":236},[1177],{"type":30,"value":1178}," (",{"type":24,"tag":138,"props":1180,"children":1181},{"style":298},[1182],{"type":30,"value":1183},"_db",{"type":24,"tag":138,"props":1185,"children":1186},{"style":213},[1187],{"type":30,"value":1188}," is",{"type":24,"tag":138,"props":1190,"children":1191},{"style":213},[1192],{"type":30,"value":1193}," null",{"type":24,"tag":138,"props":1195,"children":1196},{"style":236},[1197],{"type":30,"value":253},{"type":24,"tag":138,"props":1199,"children":1200},{"class":209,"line":382},[1201],{"type":24,"tag":138,"props":1202,"children":1203},{"style":236},[1204],{"type":30,"value":379},{"type":24,"tag":138,"props":1206,"children":1207},{"class":209,"line":421},[1208,1213,1218,1222,1227,1231,1235,1240,1244,1248,1253,1259,1265,1269,1274,1279,1284,1288],{"type":24,"tag":138,"props":1209,"children":1210},{"style":213},[1211],{"type":30,"value":1212},"            var",{"type":24,"tag":138,"props":1214,"children":1215},{"style":230},[1216],{"type":30,"value":1217}," dbModule",{"type":24,"tag":138,"props":1219,"children":1220},{"style":236},[1221],{"type":30,"value":306},{"type":24,"tag":138,"props":1223,"children":1224},{"style":213},[1225],{"type":30,"value":1226}," await",{"type":24,"tag":138,"props":1228,"children":1229},{"style":298},[1230],{"type":30,"value":1069},{"type":24,"tag":138,"props":1232,"children":1233},{"style":236},[1234],{"type":30,"value":339},{"type":24,"tag":138,"props":1236,"children":1237},{"style":230},[1238],{"type":30,"value":1239},"InvokeAsync",{"type":24,"tag":138,"props":1241,"children":1242},{"style":236},[1243],{"type":30,"value":1138},{"type":24,"tag":138,"props":1245,"children":1246},{"style":224},[1247],{"type":30,"value":1143},{"type":24,"tag":138,"props":1249,"children":1250},{"style":236},[1251],{"type":30,"value":1252},">(",{"type":24,"tag":138,"props":1254,"children":1256},{"style":1255},"--shiki-default:#C98A7D77",[1257],{"type":30,"value":1258},"\"",{"type":24,"tag":138,"props":1260,"children":1262},{"style":1261},"--shiki-default:#C98A7D",[1263],{"type":30,"value":1264},"import",{"type":24,"tag":138,"props":1266,"children":1267},{"style":1255},[1268],{"type":30,"value":1258},{"type":24,"tag":138,"props":1270,"children":1271},{"style":236},[1272],{"type":30,"value":1273},",",{"type":24,"tag":138,"props":1275,"children":1276},{"style":1255},[1277],{"type":30,"value":1278}," \"",{"type":24,"tag":138,"props":1280,"children":1281},{"style":1261},[1282],{"type":30,"value":1283},"/db.js",{"type":24,"tag":138,"props":1285,"children":1286},{"style":1255},[1287],{"type":30,"value":1258},{"type":24,"tag":138,"props":1289,"children":1290},{"style":236},[1291],{"type":30,"value":842},{"type":24,"tag":138,"props":1293,"children":1294},{"class":209,"line":452},[1295,1300,1304,1308,1312,1316,1320,1324,1328,1332,1336,1341,1345],{"type":24,"tag":138,"props":1296,"children":1297},{"style":298},[1298],{"type":30,"value":1299},"            _db",{"type":24,"tag":138,"props":1301,"children":1302},{"style":236},[1303],{"type":30,"value":306},{"type":24,"tag":138,"props":1305,"children":1306},{"style":213},[1307],{"type":30,"value":1226},{"type":24,"tag":138,"props":1309,"children":1310},{"style":298},[1311],{"type":30,"value":1217},{"type":24,"tag":138,"props":1313,"children":1314},{"style":236},[1315],{"type":30,"value":339},{"type":24,"tag":138,"props":1317,"children":1318},{"style":230},[1319],{"type":30,"value":1239},{"type":24,"tag":138,"props":1321,"children":1322},{"style":236},[1323],{"type":30,"value":1138},{"type":24,"tag":138,"props":1325,"children":1326},{"style":224},[1327],{"type":30,"value":1143},{"type":24,"tag":138,"props":1329,"children":1330},{"style":236},[1331],{"type":30,"value":1252},{"type":24,"tag":138,"props":1333,"children":1334},{"style":1255},[1335],{"type":30,"value":1258},{"type":24,"tag":138,"props":1337,"children":1338},{"style":1261},[1339],{"type":30,"value":1340},"useDatabase",{"type":24,"tag":138,"props":1342,"children":1343},{"style":1255},[1344],{"type":30,"value":1258},{"type":24,"tag":138,"props":1346,"children":1347},{"style":236},[1348],{"type":30,"value":842},{"type":24,"tag":138,"props":1350,"children":1351},{"class":209,"line":461},[1352],{"type":24,"tag":138,"props":1353,"children":1354},{"style":236},[1355],{"type":30,"value":1356},"        }\n",{"type":24,"tag":138,"props":1358,"children":1359},{"class":209,"line":483},[1360,1365,1369],{"type":24,"tag":138,"props":1361,"children":1362},{"style":269},[1363],{"type":30,"value":1364},"        return",{"type":24,"tag":138,"props":1366,"children":1367},{"style":298},[1368],{"type":30,"value":1103},{"type":24,"tag":138,"props":1370,"children":1371},{"style":236},[1372],{"type":30,"value":901},{"type":24,"tag":138,"props":1374,"children":1375},{"class":209,"line":491},[1376],{"type":24,"tag":138,"props":1377,"children":1378},{"style":236},[1379],{"type":30,"value":1380},"    }\n",{"type":24,"tag":138,"props":1382,"children":1383},{"class":209,"line":530},[1384],{"type":24,"tag":138,"props":1385,"children":1386},{"emptyLinePlaceholder":1113},[1387],{"type":30,"value":1116},{"type":24,"tag":138,"props":1389,"children":1390},{"class":209,"line":568},[1391,1396,1400,1404,1409,1413,1418,1423,1427,1431,1435,1440],{"type":24,"tag":138,"props":1392,"children":1393},{"style":213},[1394],{"type":30,"value":1395},"    public",{"type":24,"tag":138,"props":1397,"children":1398},{"style":213},[1399],{"type":30,"value":1128},{"type":24,"tag":138,"props":1401,"children":1402},{"style":224},[1403],{"type":30,"value":1133},{"type":24,"tag":138,"props":1405,"children":1406},{"style":230},[1407],{"type":30,"value":1408}," SetAsync",{"type":24,"tag":138,"props":1410,"children":1411},{"style":236},[1412],{"type":30,"value":239},{"type":24,"tag":138,"props":1414,"children":1415},{"style":269},[1416],{"type":30,"value":1417},"int",{"type":24,"tag":138,"props":1419,"children":1420},{"style":230},[1421],{"type":30,"value":1422}," musicId",{"type":24,"tag":138,"props":1424,"children":1425},{"style":236},[1426],{"type":30,"value":1273},{"type":24,"tag":138,"props":1428,"children":1429},{"style":269},[1430],{"type":30,"value":774},{"type":24,"tag":138,"props":1432,"children":1433},{"style":236},[1434],{"type":30,"value":779},{"type":24,"tag":138,"props":1436,"children":1437},{"style":230},[1438],{"type":30,"value":1439}," pimData",{"type":24,"tag":138,"props":1441,"children":1442},{"style":236},[1443],{"type":30,"value":253},{"type":24,"tag":138,"props":1445,"children":1446},{"class":209,"line":606},[1447],{"type":24,"tag":138,"props":1448,"children":1449},{"style":236},[1450],{"type":30,"value":291},{"type":24,"tag":138,"props":1452,"children":1453},{"class":209,"line":614},[1454,1459,1464,1468,1472,1476],{"type":24,"tag":138,"props":1455,"children":1456},{"style":213},[1457],{"type":30,"value":1458},"        var",{"type":24,"tag":138,"props":1460,"children":1461},{"style":230},[1462],{"type":30,"value":1463}," db",{"type":24,"tag":138,"props":1465,"children":1466},{"style":236},[1467],{"type":30,"value":306},{"type":24,"tag":138,"props":1469,"children":1470},{"style":213},[1471],{"type":30,"value":1226},{"type":24,"tag":138,"props":1473,"children":1474},{"style":230},[1475],{"type":30,"value":1153},{"type":24,"tag":138,"props":1477,"children":1478},{"style":236},[1479],{"type":30,"value":1480},"();\n",{"type":24,"tag":138,"props":1482,"children":1483},{"class":209,"line":673},[1484,1489,1493,1497,1502,1506,1510,1515,1519,1523,1527,1531,1535],{"type":24,"tag":138,"props":1485,"children":1486},{"style":213},[1487],{"type":30,"value":1488},"        await",{"type":24,"tag":138,"props":1490,"children":1491},{"style":298},[1492],{"type":30,"value":1463},{"type":24,"tag":138,"props":1494,"children":1495},{"style":236},[1496],{"type":30,"value":339},{"type":24,"tag":138,"props":1498,"children":1499},{"style":230},[1500],{"type":30,"value":1501},"InvokeVoidAsync",{"type":24,"tag":138,"props":1503,"children":1504},{"style":236},[1505],{"type":30,"value":239},{"type":24,"tag":138,"props":1507,"children":1508},{"style":1255},[1509],{"type":30,"value":1258},{"type":24,"tag":138,"props":1511,"children":1512},{"style":1261},[1513],{"type":30,"value":1514},"setItem",{"type":24,"tag":138,"props":1516,"children":1517},{"style":1255},[1518],{"type":30,"value":1258},{"type":24,"tag":138,"props":1520,"children":1521},{"style":236},[1522],{"type":30,"value":1273},{"type":24,"tag":138,"props":1524,"children":1525},{"style":298},[1526],{"type":30,"value":1422},{"type":24,"tag":138,"props":1528,"children":1529},{"style":236},[1530],{"type":30,"value":1273},{"type":24,"tag":138,"props":1532,"children":1533},{"style":298},[1534],{"type":30,"value":1439},{"type":24,"tag":138,"props":1536,"children":1537},{"style":236},[1538],{"type":30,"value":842},{"type":24,"tag":138,"props":1540,"children":1541},{"class":209,"line":682},[1542],{"type":24,"tag":138,"props":1543,"children":1544},{"style":236},[1545],{"type":30,"value":1380},{"type":24,"tag":138,"props":1547,"children":1549},{"class":209,"line":1548},21,[1550],{"type":24,"tag":138,"props":1551,"children":1552},{"style":236},[1553],{"type":30,"value":688},{"type":24,"tag":32,"props":1555,"children":1556},{},[1557,1559,1564,1566,1572,1574,1580],{"type":30,"value":1558},"3つの ",{"type":24,"tag":46,"props":1560,"children":1562},{"className":1561},[],[1563],{"type":30,"value":1143},{"type":30,"value":1565}," 階層に分かれています。",{"type":24,"tag":46,"props":1567,"children":1569},{"className":1568},[],[1570],{"type":30,"value":1571},"import('/db.js')",{"type":30,"value":1573}," で取得したモジュールと、そのモジュールの ",{"type":24,"tag":46,"props":1575,"children":1577},{"className":1576},[],[1578],{"type":30,"value":1579},"useDatabase()",{"type":30,"value":1581}," が返すDBハンドル、それから各メソッド呼び出し。という流れになります。",{"type":24,"tag":32,"props":1583,"children":1584},{},[1585,1591,1593,1599,1600,1605,1607,1612,1614,1619,1621,1626],{"type":24,"tag":46,"props":1586,"children":1588},{"className":1587},[],[1589],{"type":30,"value":1590},"InvokeVoidAsync(\"setItem\", musicId, pimData)",{"type":30,"value":1592}," の ",{"type":24,"tag":46,"props":1594,"children":1596},{"className":1595},[],[1597],{"type":30,"value":1598},"pimData",{"type":30,"value":698},{"type":24,"tag":46,"props":1601,"children":1603},{"className":1602},[],[1604],{"type":30,"value":88},{"type":30,"value":1606},"。これが ",{"type":24,"tag":46,"props":1608,"children":1610},{"className":1609},[],[1611],{"type":30,"value":1030},{"type":30,"value":1613}," の層で ",{"type":24,"tag":46,"props":1615,"children":1617},{"className":1616},[],[1618],{"type":30,"value":96},{"type":30,"value":1620}," に変換され、JS側の ",{"type":24,"tag":46,"props":1622,"children":1624},{"className":1623},[],[1625],{"type":30,"value":1514},{"type":30,"value":1627}," 関数の引数として届きます。",{"type":24,"tag":25,"props":1629,"children":1631},{"id":1630},"レイヤー4-js側はuint8arrayを受け取ってそのまま使える",[1632],{"type":30,"value":1633},"レイヤー4 JS側はUint8Arrayを受け取ってそのまま使える",{"type":24,"tag":32,"props":1635,"children":1636},{},[1637,1639,1645,1647,1652,1654,1660,1662,1668],{"type":30,"value":1638},"JS側の ",{"type":24,"tag":46,"props":1640,"children":1642},{"className":1641},[],[1643],{"type":30,"value":1644},"db.js",{"type":30,"value":1646}," では、C#から渡ってきた ",{"type":24,"tag":46,"props":1648,"children":1650},{"className":1649},[],[1651],{"type":30,"value":96},{"type":30,"value":1653}," をそのまま IndexedDB に渡せます。",{"type":24,"tag":46,"props":1655,"children":1657},{"className":1656},[],[1658],{"type":30,"value":1659},"atob",{"type":30,"value":1661}," や ",{"type":24,"tag":46,"props":1663,"children":1665},{"className":1664},[],[1666],{"type":30,"value":1667},"Uint8Array.from",{"type":30,"value":1669}," による変換コードは一切ありません。",{"type":24,"tag":32,"props":1671,"children":1672},{},[1673,1675,1681],{"type":30,"value":1674},"コードを見る前に、あとで繰り返し登場する ",{"type":24,"tag":46,"props":1676,"children":1678},{"className":1677},[],[1679],{"type":30,"value":1680},"runTransaction",{"type":30,"value":1682}," というヘルパーを先に定義しておきます。IndexedDB のトランザクションは「open → objectStore 取得 → リクエスト発行 → onsuccess/onerror を受ける」というボイラープレートが毎回必要なので、一度 Promise にラップしてあります。",{"type":24,"tag":198,"props":1684,"children":1688},{"className":1685,"code":1686,"language":1687,"meta":7,"style":7},"language-javascript shiki shiki-themes vitesse-dark","const runTransaction = (mode, fn) =>\n    new Promise((resolve, reject) => {\n        const tx = db.transaction(MUSIC_STORE_NAME, mode);\n        const store = tx.objectStore(MUSIC_STORE_NAME);\n        const request = fn(store);\n        request.onsuccess = () => resolve(request.result);\n        request.onerror = () => reject(request.error);\n    });\n","javascript",[1689],{"type":24,"tag":46,"props":1690,"children":1691},{"__ignoreMap":7},[1692,1737,1784,1836,1877,1910,1967,2020],{"type":24,"tag":138,"props":1693,"children":1694},{"class":209,"line":18},[1695,1700,1705,1709,1713,1718,1722,1727,1732],{"type":24,"tag":138,"props":1696,"children":1697},{"style":213},[1698],{"type":30,"value":1699},"const",{"type":24,"tag":138,"props":1701,"children":1702},{"style":230},[1703],{"type":30,"value":1704}," runTransaction",{"type":24,"tag":138,"props":1706,"children":1707},{"style":236},[1708],{"type":30,"value":306},{"type":24,"tag":138,"props":1710,"children":1711},{"style":236},[1712],{"type":30,"value":1178},{"type":24,"tag":138,"props":1714,"children":1715},{"style":298},[1716],{"type":30,"value":1717},"mode",{"type":24,"tag":138,"props":1719,"children":1720},{"style":236},[1721],{"type":30,"value":1273},{"type":24,"tag":138,"props":1723,"children":1724},{"style":298},[1725],{"type":30,"value":1726}," fn",{"type":24,"tag":138,"props":1728,"children":1729},{"style":236},[1730],{"type":30,"value":1731},")",{"type":24,"tag":138,"props":1733,"children":1734},{"style":236},[1735],{"type":30,"value":1736}," =>\n",{"type":24,"tag":138,"props":1738,"children":1739},{"class":209,"line":256},[1740,1745,1751,1756,1761,1765,1770,1774,1779],{"type":24,"tag":138,"props":1741,"children":1742},{"style":213},[1743],{"type":30,"value":1744},"    new",{"type":24,"tag":138,"props":1746,"children":1748},{"style":1747},"--shiki-default:#B8A965",[1749],{"type":30,"value":1750}," Promise",{"type":24,"tag":138,"props":1752,"children":1753},{"style":236},[1754],{"type":30,"value":1755},"((",{"type":24,"tag":138,"props":1757,"children":1758},{"style":298},[1759],{"type":30,"value":1760},"resolve",{"type":24,"tag":138,"props":1762,"children":1763},{"style":236},[1764],{"type":30,"value":1273},{"type":24,"tag":138,"props":1766,"children":1767},{"style":298},[1768],{"type":30,"value":1769}," reject",{"type":24,"tag":138,"props":1771,"children":1772},{"style":236},[1773],{"type":30,"value":1731},{"type":24,"tag":138,"props":1775,"children":1776},{"style":236},[1777],{"type":30,"value":1778}," =>",{"type":24,"tag":138,"props":1780,"children":1781},{"style":236},[1782],{"type":30,"value":1783}," {\n",{"type":24,"tag":138,"props":1785,"children":1786},{"class":209,"line":265},[1787,1792,1797,1801,1805,1809,1814,1818,1823,1827,1832],{"type":24,"tag":138,"props":1788,"children":1789},{"style":213},[1790],{"type":30,"value":1791},"        const",{"type":24,"tag":138,"props":1793,"children":1794},{"style":298},[1795],{"type":30,"value":1796}," tx",{"type":24,"tag":138,"props":1798,"children":1799},{"style":236},[1800],{"type":30,"value":306},{"type":24,"tag":138,"props":1802,"children":1803},{"style":298},[1804],{"type":30,"value":1463},{"type":24,"tag":138,"props":1806,"children":1807},{"style":236},[1808],{"type":30,"value":339},{"type":24,"tag":138,"props":1810,"children":1811},{"style":230},[1812],{"type":30,"value":1813},"transaction",{"type":24,"tag":138,"props":1815,"children":1816},{"style":236},[1817],{"type":30,"value":239},{"type":24,"tag":138,"props":1819,"children":1820},{"style":298},[1821],{"type":30,"value":1822},"MUSIC_STORE_NAME",{"type":24,"tag":138,"props":1824,"children":1825},{"style":236},[1826],{"type":30,"value":1273},{"type":24,"tag":138,"props":1828,"children":1829},{"style":298},[1830],{"type":30,"value":1831}," mode",{"type":24,"tag":138,"props":1833,"children":1834},{"style":236},[1835],{"type":30,"value":842},{"type":24,"tag":138,"props":1837,"children":1838},{"class":209,"line":285},[1839,1843,1848,1852,1856,1860,1865,1869,1873],{"type":24,"tag":138,"props":1840,"children":1841},{"style":213},[1842],{"type":30,"value":1791},{"type":24,"tag":138,"props":1844,"children":1845},{"style":298},[1846],{"type":30,"value":1847}," store",{"type":24,"tag":138,"props":1849,"children":1850},{"style":236},[1851],{"type":30,"value":306},{"type":24,"tag":138,"props":1853,"children":1854},{"style":298},[1855],{"type":30,"value":1796},{"type":24,"tag":138,"props":1857,"children":1858},{"style":236},[1859],{"type":30,"value":339},{"type":24,"tag":138,"props":1861,"children":1862},{"style":230},[1863],{"type":30,"value":1864},"objectStore",{"type":24,"tag":138,"props":1866,"children":1867},{"style":236},[1868],{"type":30,"value":239},{"type":24,"tag":138,"props":1870,"children":1871},{"style":298},[1872],{"type":30,"value":1822},{"type":24,"tag":138,"props":1874,"children":1875},{"style":236},[1876],{"type":30,"value":842},{"type":24,"tag":138,"props":1878,"children":1879},{"class":209,"line":294},[1880,1884,1889,1893,1897,1901,1906],{"type":24,"tag":138,"props":1881,"children":1882},{"style":213},[1883],{"type":30,"value":1791},{"type":24,"tag":138,"props":1885,"children":1886},{"style":298},[1887],{"type":30,"value":1888}," request",{"type":24,"tag":138,"props":1890,"children":1891},{"style":236},[1892],{"type":30,"value":306},{"type":24,"tag":138,"props":1894,"children":1895},{"style":230},[1896],{"type":30,"value":1726},{"type":24,"tag":138,"props":1898,"children":1899},{"style":236},[1900],{"type":30,"value":239},{"type":24,"tag":138,"props":1902,"children":1903},{"style":298},[1904],{"type":30,"value":1905},"store",{"type":24,"tag":138,"props":1907,"children":1908},{"style":236},[1909],{"type":30,"value":842},{"type":24,"tag":138,"props":1911,"children":1912},{"class":209,"line":320},[1913,1918,1922,1927,1931,1936,1940,1945,1949,1954,1958,1963],{"type":24,"tag":138,"props":1914,"children":1915},{"style":298},[1916],{"type":30,"value":1917},"        request",{"type":24,"tag":138,"props":1919,"children":1920},{"style":236},[1921],{"type":30,"value":339},{"type":24,"tag":138,"props":1923,"children":1924},{"style":230},[1925],{"type":30,"value":1926},"onsuccess",{"type":24,"tag":138,"props":1928,"children":1929},{"style":236},[1930],{"type":30,"value":306},{"type":24,"tag":138,"props":1932,"children":1933},{"style":236},[1934],{"type":30,"value":1935}," ()",{"type":24,"tag":138,"props":1937,"children":1938},{"style":236},[1939],{"type":30,"value":1778},{"type":24,"tag":138,"props":1941,"children":1942},{"style":230},[1943],{"type":30,"value":1944}," resolve",{"type":24,"tag":138,"props":1946,"children":1947},{"style":236},[1948],{"type":30,"value":239},{"type":24,"tag":138,"props":1950,"children":1951},{"style":298},[1952],{"type":30,"value":1953},"request",{"type":24,"tag":138,"props":1955,"children":1956},{"style":236},[1957],{"type":30,"value":339},{"type":24,"tag":138,"props":1959,"children":1960},{"style":298},[1961],{"type":30,"value":1962},"result",{"type":24,"tag":138,"props":1964,"children":1965},{"style":236},[1966],{"type":30,"value":842},{"type":24,"tag":138,"props":1968,"children":1969},{"class":209,"line":351},[1970,1974,1978,1983,1987,1991,1995,1999,2003,2007,2011,2016],{"type":24,"tag":138,"props":1971,"children":1972},{"style":298},[1973],{"type":30,"value":1917},{"type":24,"tag":138,"props":1975,"children":1976},{"style":236},[1977],{"type":30,"value":339},{"type":24,"tag":138,"props":1979,"children":1980},{"style":230},[1981],{"type":30,"value":1982},"onerror",{"type":24,"tag":138,"props":1984,"children":1985},{"style":236},[1986],{"type":30,"value":306},{"type":24,"tag":138,"props":1988,"children":1989},{"style":236},[1990],{"type":30,"value":1935},{"type":24,"tag":138,"props":1992,"children":1993},{"style":236},[1994],{"type":30,"value":1778},{"type":24,"tag":138,"props":1996,"children":1997},{"style":230},[1998],{"type":30,"value":1769},{"type":24,"tag":138,"props":2000,"children":2001},{"style":236},[2002],{"type":30,"value":239},{"type":24,"tag":138,"props":2004,"children":2005},{"style":298},[2006],{"type":30,"value":1953},{"type":24,"tag":138,"props":2008,"children":2009},{"style":236},[2010],{"type":30,"value":339},{"type":24,"tag":138,"props":2012,"children":2013},{"style":298},[2014],{"type":30,"value":2015},"error",{"type":24,"tag":138,"props":2017,"children":2018},{"style":236},[2019],{"type":30,"value":842},{"type":24,"tag":138,"props":2021,"children":2022},{"class":209,"line":373},[2023],{"type":24,"tag":138,"props":2024,"children":2025},{"style":236},[2026],{"type":30,"value":2027},"    });\n",{"type":24,"tag":32,"props":2029,"children":2030},{},[2031,2033,2038],{"type":30,"value":2032},"これを使うと ",{"type":24,"tag":46,"props":2034,"children":2036},{"className":2035},[],[2037],{"type":30,"value":1514},{"type":30,"value":2039}," は次の一行で済みます。",{"type":24,"tag":198,"props":2041,"children":2043},{"className":1685,"code":2042,"language":1687,"meta":7,"style":7},"async function setItem(musicId, pimData) {\n    // pimData は C# 側から Uint8Array として届く\n    await runTransaction(\"readwrite\", (store) => store.put(pimData, musicId));\n}\n",[2044],{"type":24,"tag":46,"props":2045,"children":2046},{"__ignoreMap":7},[2047,2090,2099,2182],{"type":24,"tag":138,"props":2048,"children":2049},{"class":209,"line":18},[2050,2055,2060,2065,2069,2074,2078,2082,2086],{"type":24,"tag":138,"props":2051,"children":2052},{"style":213},[2053],{"type":30,"value":2054},"async",{"type":24,"tag":138,"props":2056,"children":2057},{"style":213},[2058],{"type":30,"value":2059}," function",{"type":24,"tag":138,"props":2061,"children":2062},{"style":230},[2063],{"type":30,"value":2064}," setItem",{"type":24,"tag":138,"props":2066,"children":2067},{"style":236},[2068],{"type":30,"value":239},{"type":24,"tag":138,"props":2070,"children":2071},{"style":298},[2072],{"type":30,"value":2073},"musicId",{"type":24,"tag":138,"props":2075,"children":2076},{"style":236},[2077],{"type":30,"value":1273},{"type":24,"tag":138,"props":2079,"children":2080},{"style":298},[2081],{"type":30,"value":1439},{"type":24,"tag":138,"props":2083,"children":2084},{"style":236},[2085],{"type":30,"value":1731},{"type":24,"tag":138,"props":2087,"children":2088},{"style":236},[2089],{"type":30,"value":1783},{"type":24,"tag":138,"props":2091,"children":2092},{"class":209,"line":256},[2093],{"type":24,"tag":138,"props":2094,"children":2096},{"style":2095},"--shiki-default:#758575DD",[2097],{"type":30,"value":2098},"    // pimData は C# 側から Uint8Array として届く\n",{"type":24,"tag":138,"props":2100,"children":2101},{"class":209,"line":265},[2102,2107,2111,2115,2119,2124,2128,2132,2136,2140,2144,2148,2152,2156,2161,2165,2169,2173,2177],{"type":24,"tag":138,"props":2103,"children":2104},{"style":269},[2105],{"type":30,"value":2106},"    await",{"type":24,"tag":138,"props":2108,"children":2109},{"style":230},[2110],{"type":30,"value":1704},{"type":24,"tag":138,"props":2112,"children":2113},{"style":236},[2114],{"type":30,"value":239},{"type":24,"tag":138,"props":2116,"children":2117},{"style":1255},[2118],{"type":30,"value":1258},{"type":24,"tag":138,"props":2120,"children":2121},{"style":1261},[2122],{"type":30,"value":2123},"readwrite",{"type":24,"tag":138,"props":2125,"children":2126},{"style":1255},[2127],{"type":30,"value":1258},{"type":24,"tag":138,"props":2129,"children":2130},{"style":236},[2131],{"type":30,"value":1273},{"type":24,"tag":138,"props":2133,"children":2134},{"style":236},[2135],{"type":30,"value":1178},{"type":24,"tag":138,"props":2137,"children":2138},{"style":298},[2139],{"type":30,"value":1905},{"type":24,"tag":138,"props":2141,"children":2142},{"style":236},[2143],{"type":30,"value":1731},{"type":24,"tag":138,"props":2145,"children":2146},{"style":236},[2147],{"type":30,"value":1778},{"type":24,"tag":138,"props":2149,"children":2150},{"style":298},[2151],{"type":30,"value":1847},{"type":24,"tag":138,"props":2153,"children":2154},{"style":236},[2155],{"type":30,"value":339},{"type":24,"tag":138,"props":2157,"children":2158},{"style":230},[2159],{"type":30,"value":2160},"put",{"type":24,"tag":138,"props":2162,"children":2163},{"style":236},[2164],{"type":30,"value":239},{"type":24,"tag":138,"props":2166,"children":2167},{"style":298},[2168],{"type":30,"value":1598},{"type":24,"tag":138,"props":2170,"children":2171},{"style":236},[2172],{"type":30,"value":1273},{"type":24,"tag":138,"props":2174,"children":2175},{"style":298},[2176],{"type":30,"value":1422},{"type":24,"tag":138,"props":2178,"children":2179},{"style":236},[2180],{"type":30,"value":2181},"));\n",{"type":24,"tag":138,"props":2183,"children":2184},{"class":209,"line":285},[2185],{"type":24,"tag":138,"props":2186,"children":2187},{"style":236},[2188],{"type":30,"value":688},{"type":24,"tag":32,"props":2190,"children":2191},{},[2192],{"type":30,"value":2193},"たったこれだけです。実装の薄さが interop の真価だと感じる箇所です。",{"type":24,"tag":25,"props":2195,"children":2197},{"id":2196},"レイヤー5-indexeddbに書き込む",[2198],{"type":30,"value":2199},"レイヤー5 IndexedDBに書き込む",{"type":24,"tag":32,"props":2201,"children":2202},{},[2203,2205,2211,2213,2223],{"type":30,"value":2204},"最後のレイヤー、",{"type":24,"tag":46,"props":2206,"children":2208},{"className":2207},[],[2209],{"type":30,"value":2210},"store.put(pimData, musicId)",{"type":30,"value":2212}," が実際にIndexedDBへ書き込みます。ここで少し変わったのは、",{"type":24,"tag":60,"props":2214,"children":2215},{},[2216,2221],{"type":24,"tag":46,"props":2217,"children":2219},{"className":2218},[],[2220],{"type":30,"value":104},{"type":30,"value":2222},"なしのobjectStore",{"type":30,"value":2224},"を使っている点です。",{"type":24,"tag":731,"props":2226,"children":2228},{"id":2227},"keypathなしのストア設計",[2229],{"type":30,"value":2230},"keyPathなしのストア設計",{"type":24,"tag":32,"props":2232,"children":2233},{},[2234,2240,2242,2247],{"type":24,"tag":46,"props":2235,"children":2237},{"className":2236},[],[2238],{"type":30,"value":2239},"createObjectStore",{"type":30,"value":2241}," を呼ぶ際、",{"type":24,"tag":46,"props":2243,"children":2245},{"className":2244},[],[2246],{"type":30,"value":104},{"type":30,"value":2248}," を指定しない形で作っています。",{"type":24,"tag":198,"props":2250,"children":2252},{"className":1685,"code":2251,"language":1687,"meta":7,"style":7},"request.onupgradeneeded = (event) => {\n    const db = event.target.result;\n    if (!db.objectStoreNames.contains(MUSIC_STORE_NAME)) {\n        db.createObjectStore(MUSIC_STORE_NAME);\n    }\n};\n",[2253],{"type":24,"tag":46,"props":2254,"children":2255},{"__ignoreMap":7},[2256,2297,2339,2396,2424,2431],{"type":24,"tag":138,"props":2257,"children":2258},{"class":209,"line":18},[2259,2263,2267,2272,2276,2280,2285,2289,2293],{"type":24,"tag":138,"props":2260,"children":2261},{"style":298},[2262],{"type":30,"value":1953},{"type":24,"tag":138,"props":2264,"children":2265},{"style":236},[2266],{"type":30,"value":339},{"type":24,"tag":138,"props":2268,"children":2269},{"style":230},[2270],{"type":30,"value":2271},"onupgradeneeded",{"type":24,"tag":138,"props":2273,"children":2274},{"style":236},[2275],{"type":30,"value":306},{"type":24,"tag":138,"props":2277,"children":2278},{"style":236},[2279],{"type":30,"value":1178},{"type":24,"tag":138,"props":2281,"children":2282},{"style":298},[2283],{"type":30,"value":2284},"event",{"type":24,"tag":138,"props":2286,"children":2287},{"style":236},[2288],{"type":30,"value":1731},{"type":24,"tag":138,"props":2290,"children":2291},{"style":236},[2292],{"type":30,"value":1778},{"type":24,"tag":138,"props":2294,"children":2295},{"style":236},[2296],{"type":30,"value":1783},{"type":24,"tag":138,"props":2298,"children":2299},{"class":209,"line":256},[2300,2305,2309,2313,2318,2322,2327,2331,2335],{"type":24,"tag":138,"props":2301,"children":2302},{"style":213},[2303],{"type":30,"value":2304},"    const",{"type":24,"tag":138,"props":2306,"children":2307},{"style":298},[2308],{"type":30,"value":1463},{"type":24,"tag":138,"props":2310,"children":2311},{"style":236},[2312],{"type":30,"value":306},{"type":24,"tag":138,"props":2314,"children":2315},{"style":298},[2316],{"type":30,"value":2317}," event",{"type":24,"tag":138,"props":2319,"children":2320},{"style":236},[2321],{"type":30,"value":339},{"type":24,"tag":138,"props":2323,"children":2324},{"style":298},[2325],{"type":30,"value":2326},"target",{"type":24,"tag":138,"props":2328,"children":2329},{"style":236},[2330],{"type":30,"value":339},{"type":24,"tag":138,"props":2332,"children":2333},{"style":298},[2334],{"type":30,"value":1962},{"type":24,"tag":138,"props":2336,"children":2337},{"style":236},[2338],{"type":30,"value":901},{"type":24,"tag":138,"props":2340,"children":2341},{"class":209,"line":265},[2342,2347,2351,2356,2361,2365,2370,2374,2379,2383,2387,2392],{"type":24,"tag":138,"props":2343,"children":2344},{"style":269},[2345],{"type":30,"value":2346},"    if",{"type":24,"tag":138,"props":2348,"children":2349},{"style":236},[2350],{"type":30,"value":1178},{"type":24,"tag":138,"props":2352,"children":2353},{"style":213},[2354],{"type":30,"value":2355},"!",{"type":24,"tag":138,"props":2357,"children":2358},{"style":298},[2359],{"type":30,"value":2360},"db",{"type":24,"tag":138,"props":2362,"children":2363},{"style":236},[2364],{"type":30,"value":339},{"type":24,"tag":138,"props":2366,"children":2367},{"style":298},[2368],{"type":30,"value":2369},"objectStoreNames",{"type":24,"tag":138,"props":2371,"children":2372},{"style":236},[2373],{"type":30,"value":339},{"type":24,"tag":138,"props":2375,"children":2376},{"style":230},[2377],{"type":30,"value":2378},"contains",{"type":24,"tag":138,"props":2380,"children":2381},{"style":236},[2382],{"type":30,"value":239},{"type":24,"tag":138,"props":2384,"children":2385},{"style":298},[2386],{"type":30,"value":1822},{"type":24,"tag":138,"props":2388,"children":2389},{"style":236},[2390],{"type":30,"value":2391},"))",{"type":24,"tag":138,"props":2393,"children":2394},{"style":236},[2395],{"type":30,"value":1783},{"type":24,"tag":138,"props":2397,"children":2398},{"class":209,"line":285},[2399,2404,2408,2412,2416,2420],{"type":24,"tag":138,"props":2400,"children":2401},{"style":298},[2402],{"type":30,"value":2403},"        db",{"type":24,"tag":138,"props":2405,"children":2406},{"style":236},[2407],{"type":30,"value":339},{"type":24,"tag":138,"props":2409,"children":2410},{"style":230},[2411],{"type":30,"value":2239},{"type":24,"tag":138,"props":2413,"children":2414},{"style":236},[2415],{"type":30,"value":239},{"type":24,"tag":138,"props":2417,"children":2418},{"style":298},[2419],{"type":30,"value":1822},{"type":24,"tag":138,"props":2421,"children":2422},{"style":236},[2423],{"type":30,"value":842},{"type":24,"tag":138,"props":2425,"children":2426},{"class":209,"line":294},[2427],{"type":24,"tag":138,"props":2428,"children":2429},{"style":236},[2430],{"type":30,"value":1380},{"type":24,"tag":138,"props":2432,"children":2433},{"class":209,"line":320},[2434],{"type":24,"tag":138,"props":2435,"children":2436},{"style":236},[2437],{"type":30,"value":2438},"};\n",{"type":24,"tag":32,"props":2440,"children":2441},{},[2442,2447,2449,2455],{"type":24,"tag":46,"props":2443,"children":2445},{"className":2444},[],[2446],{"type":30,"value":104},{"type":30,"value":2448}," を指定すると、value に格納するオブジェクトの特定フィールドが自動でキーとして抽出される仕組みになります。多くの入門サンプルはこの方式で、",{"type":24,"tag":46,"props":2450,"children":2452},{"className":2451},[],[2453],{"type":30,"value":2454},"{ musicId: 1, pimData: ... }",{"type":30,"value":2456}," のようなラッパーオブジェクトを value に入れます。",{"type":24,"tag":32,"props":2458,"children":2459},{},[2460,2462,2467,2469,2475,2477,2482,2484,2489],{"type":30,"value":2461},"PICOMは",{"type":24,"tag":46,"props":2463,"children":2465},{"className":2464},[],[2466],{"type":30,"value":104},{"type":30,"value":2468},"なしにしました。こうすると ",{"type":24,"tag":46,"props":2470,"children":2472},{"className":2471},[],[2473],{"type":30,"value":2474},"store.put(value, key)",{"type":30,"value":2476}," の第2引数でキーを外から明示的に渡す",{"type":24,"tag":60,"props":2478,"children":2479},{},[2480],{"type":30,"value":2481},"アウトオブラインキー",{"type":30,"value":2483},"方式になり、value には何でも置けます。PICOMの場合は生の ",{"type":24,"tag":46,"props":2485,"children":2487},{"className":2486},[],[2488],{"type":30,"value":96},{"type":30,"value":2490}," を直接置いています。",{"type":24,"tag":2492,"props":2493,"children":2496},"tradeoff-box",{"cons-label":2494,"pros-label":2495},"keyPathありにしていたら得たもの","keyPathなし（アウトオブラインキー）の得",[2497,2535],{"type":24,"tag":2498,"props":2499,"children":2500},"template",{"v-slot:pros":7},[2501],{"type":24,"tag":2502,"props":2503,"children":2504},"ul",{},[2505,2517,2530],{"type":24,"tag":122,"props":2506,"children":2507},{},[2508,2510,2515],{"type":30,"value":2509},"valueが任意の型でよい（",{"type":24,"tag":46,"props":2511,"children":2513},{"className":2512},[],[2514],{"type":30,"value":96},{"type":30,"value":2516},"そのまま置ける）",{"type":24,"tag":122,"props":2518,"children":2519},{},[2520,2522,2528],{"type":30,"value":2521},"ラッパーオブジェクト ",{"type":24,"tag":46,"props":2523,"children":2525},{"className":2524},[],[2526],{"type":30,"value":2527},"{ musicId, pimData }",{"type":30,"value":2529}," のような構造を挟まずに済む",{"type":24,"tag":122,"props":2531,"children":2532},{},[2533],{"type":30,"value":2534},"PIMバイナリ内にIDが埋まっている現在の設計と相性が良い（二重にIDを持たない）",{"type":24,"tag":2498,"props":2536,"children":2537},{"v-slot:cons":7},[2538,2551],{"type":24,"tag":122,"props":2539,"children":2540},{},[2541,2543,2549],{"type":30,"value":2542},"セカンダリインデックスを張れない（",{"type":24,"tag":46,"props":2544,"children":2546},{"className":2545},[],[2547],{"type":30,"value":2548},"store.createIndex('byTitle', 'title')",{"type":30,"value":2550}," のようなことができない）",{"type":24,"tag":122,"props":2552,"children":2553},{},[2554,2560,2562,2567],{"type":24,"tag":46,"props":2555,"children":2557},{"className":2556},[],[2558],{"type":30,"value":2559},"store.put(value)",{"type":30,"value":2561}," だけでなく必ず ",{"type":24,"tag":46,"props":2563,"children":2565},{"className":2564},[],[2566],{"type":30,"value":2474},{"type":30,"value":2568}," のようにキーを渡す必要がある",{"type":24,"tag":32,"props":2570,"children":2571},{},[2572],{"type":30,"value":2573},"セカンダリインデックスが必要になる場面、たとえば「タイトルで検索」のような機能を今後入れるなら、別ストアを並立させて軽量なメタデータだけを置くのがよいと考えています。現状は楽曲数が個人利用レベルなので、全件取得してC#側でフィルタで十分と判断しました。",{"type":24,"tag":731,"props":2575,"children":2577},{"id":2576},"storage-persistence-api",[2578],{"type":30,"value":2579},"Storage Persistence API",{"type":24,"tag":32,"props":2581,"children":2582},{},[2583],{"type":30,"value":2584},"IndexedDBは容量が逼迫するとブラウザが勝手にデータを消す仕様なので、ストアを開くタイミングで永続化をリクエストしています。",{"type":24,"tag":198,"props":2586,"children":2588},{"className":1685,"code":2587,"language":1687,"meta":7,"style":7},"if (navigator.storage && navigator.storage.persist) {\n    const isPersisted = await navigator.storage.persisted();\n    if (!isPersisted) {\n        const granted = await navigator.storage.persist();\n        console.log(`[Picom] Storage persistence ${granted ? 'granted' : 'denied'}`);\n    }\n}\n",[2589],{"type":24,"tag":46,"props":2590,"children":2591},{"__ignoreMap":7},[2592,2653,2698,2726,2770,2861,2868],{"type":24,"tag":138,"props":2593,"children":2594},{"class":209,"line":18},[2595,2600,2604,2609,2613,2618,2623,2628,2632,2636,2640,2645,2649],{"type":24,"tag":138,"props":2596,"children":2597},{"style":269},[2598],{"type":30,"value":2599},"if",{"type":24,"tag":138,"props":2601,"children":2602},{"style":236},[2603],{"type":30,"value":1178},{"type":24,"tag":138,"props":2605,"children":2606},{"style":298},[2607],{"type":30,"value":2608},"navigator",{"type":24,"tag":138,"props":2610,"children":2611},{"style":236},[2612],{"type":30,"value":339},{"type":24,"tag":138,"props":2614,"children":2615},{"style":298},[2616],{"type":30,"value":2617},"storage",{"type":24,"tag":138,"props":2619,"children":2620},{"style":213},[2621],{"type":30,"value":2622}," &&",{"type":24,"tag":138,"props":2624,"children":2625},{"style":298},[2626],{"type":30,"value":2627}," navigator",{"type":24,"tag":138,"props":2629,"children":2630},{"style":236},[2631],{"type":30,"value":339},{"type":24,"tag":138,"props":2633,"children":2634},{"style":298},[2635],{"type":30,"value":2617},{"type":24,"tag":138,"props":2637,"children":2638},{"style":236},[2639],{"type":30,"value":339},{"type":24,"tag":138,"props":2641,"children":2642},{"style":298},[2643],{"type":30,"value":2644},"persist",{"type":24,"tag":138,"props":2646,"children":2647},{"style":236},[2648],{"type":30,"value":1731},{"type":24,"tag":138,"props":2650,"children":2651},{"style":236},[2652],{"type":30,"value":1783},{"type":24,"tag":138,"props":2654,"children":2655},{"class":209,"line":256},[2656,2660,2665,2669,2673,2677,2681,2685,2689,2694],{"type":24,"tag":138,"props":2657,"children":2658},{"style":213},[2659],{"type":30,"value":2304},{"type":24,"tag":138,"props":2661,"children":2662},{"style":298},[2663],{"type":30,"value":2664}," isPersisted",{"type":24,"tag":138,"props":2666,"children":2667},{"style":236},[2668],{"type":30,"value":306},{"type":24,"tag":138,"props":2670,"children":2671},{"style":269},[2672],{"type":30,"value":1226},{"type":24,"tag":138,"props":2674,"children":2675},{"style":298},[2676],{"type":30,"value":2627},{"type":24,"tag":138,"props":2678,"children":2679},{"style":236},[2680],{"type":30,"value":339},{"type":24,"tag":138,"props":2682,"children":2683},{"style":298},[2684],{"type":30,"value":2617},{"type":24,"tag":138,"props":2686,"children":2687},{"style":236},[2688],{"type":30,"value":339},{"type":24,"tag":138,"props":2690,"children":2691},{"style":230},[2692],{"type":30,"value":2693},"persisted",{"type":24,"tag":138,"props":2695,"children":2696},{"style":236},[2697],{"type":30,"value":1480},{"type":24,"tag":138,"props":2699,"children":2700},{"class":209,"line":265},[2701,2705,2709,2713,2718,2722],{"type":24,"tag":138,"props":2702,"children":2703},{"style":269},[2704],{"type":30,"value":2346},{"type":24,"tag":138,"props":2706,"children":2707},{"style":236},[2708],{"type":30,"value":1178},{"type":24,"tag":138,"props":2710,"children":2711},{"style":213},[2712],{"type":30,"value":2355},{"type":24,"tag":138,"props":2714,"children":2715},{"style":298},[2716],{"type":30,"value":2717},"isPersisted",{"type":24,"tag":138,"props":2719,"children":2720},{"style":236},[2721],{"type":30,"value":1731},{"type":24,"tag":138,"props":2723,"children":2724},{"style":236},[2725],{"type":30,"value":1783},{"type":24,"tag":138,"props":2727,"children":2728},{"class":209,"line":285},[2729,2733,2738,2742,2746,2750,2754,2758,2762,2766],{"type":24,"tag":138,"props":2730,"children":2731},{"style":213},[2732],{"type":30,"value":1791},{"type":24,"tag":138,"props":2734,"children":2735},{"style":298},[2736],{"type":30,"value":2737}," granted",{"type":24,"tag":138,"props":2739,"children":2740},{"style":236},[2741],{"type":30,"value":306},{"type":24,"tag":138,"props":2743,"children":2744},{"style":269},[2745],{"type":30,"value":1226},{"type":24,"tag":138,"props":2747,"children":2748},{"style":298},[2749],{"type":30,"value":2627},{"type":24,"tag":138,"props":2751,"children":2752},{"style":236},[2753],{"type":30,"value":339},{"type":24,"tag":138,"props":2755,"children":2756},{"style":298},[2757],{"type":30,"value":2617},{"type":24,"tag":138,"props":2759,"children":2760},{"style":236},[2761],{"type":30,"value":339},{"type":24,"tag":138,"props":2763,"children":2764},{"style":230},[2765],{"type":30,"value":2644},{"type":24,"tag":138,"props":2767,"children":2768},{"style":236},[2769],{"type":30,"value":1480},{"type":24,"tag":138,"props":2771,"children":2772},{"class":209,"line":294},[2773,2778,2782,2787,2791,2796,2801,2806,2811,2815,2820,2825,2830,2835,2839,2844,2848,2853,2857],{"type":24,"tag":138,"props":2774,"children":2775},{"style":298},[2776],{"type":30,"value":2777},"        console",{"type":24,"tag":138,"props":2779,"children":2780},{"style":236},[2781],{"type":30,"value":339},{"type":24,"tag":138,"props":2783,"children":2784},{"style":230},[2785],{"type":30,"value":2786},"log",{"type":24,"tag":138,"props":2788,"children":2789},{"style":236},[2790],{"type":30,"value":239},{"type":24,"tag":138,"props":2792,"children":2793},{"style":1255},[2794],{"type":30,"value":2795},"`",{"type":24,"tag":138,"props":2797,"children":2798},{"style":1261},[2799],{"type":30,"value":2800},"[Picom] Storage persistence ",{"type":24,"tag":138,"props":2802,"children":2803},{"style":269},[2804],{"type":30,"value":2805},"${",{"type":24,"tag":138,"props":2807,"children":2808},{"style":1261},[2809],{"type":30,"value":2810},"granted ",{"type":24,"tag":138,"props":2812,"children":2813},{"style":213},[2814],{"type":30,"value":1098},{"type":24,"tag":138,"props":2816,"children":2817},{"style":1255},[2818],{"type":30,"value":2819}," '",{"type":24,"tag":138,"props":2821,"children":2822},{"style":1261},[2823],{"type":30,"value":2824},"granted",{"type":24,"tag":138,"props":2826,"children":2827},{"style":1255},[2828],{"type":30,"value":2829},"'",{"type":24,"tag":138,"props":2831,"children":2832},{"style":213},[2833],{"type":30,"value":2834}," :",{"type":24,"tag":138,"props":2836,"children":2837},{"style":1255},[2838],{"type":30,"value":2819},{"type":24,"tag":138,"props":2840,"children":2841},{"style":1261},[2842],{"type":30,"value":2843},"denied",{"type":24,"tag":138,"props":2845,"children":2846},{"style":1255},[2847],{"type":30,"value":2829},{"type":24,"tag":138,"props":2849,"children":2850},{"style":269},[2851],{"type":30,"value":2852},"}",{"type":24,"tag":138,"props":2854,"children":2855},{"style":1255},[2856],{"type":30,"value":2795},{"type":24,"tag":138,"props":2858,"children":2859},{"style":236},[2860],{"type":30,"value":842},{"type":24,"tag":138,"props":2862,"children":2863},{"class":209,"line":320},[2864],{"type":24,"tag":138,"props":2865,"children":2866},{"style":236},[2867],{"type":30,"value":1380},{"type":24,"tag":138,"props":2869,"children":2870},{"class":209,"line":351},[2871],{"type":24,"tag":138,"props":2872,"children":2873},{"style":236},[2874],{"type":30,"value":688},{"type":24,"tag":32,"props":2876,"children":2877},{},[2878],{"type":30,"value":2879},"この処理を加えることで、容量逼迫時でも自動削除されなくなります。",{"type":24,"tag":2881,"props":2882,"children":2883},"caution-box",{},[2884],{"type":24,"tag":32,"props":2885,"children":2886},{},[2887],{"type":30,"value":2888},"ユーザーが明示的にサイトデータを削除すれば当然消えます。クラウド同期など別系統のバックアップは別途検討する価値があります。",{"type":24,"tag":25,"props":2890,"children":2892},{"id":2891},"読み込み側は逆順をたどる",[2893],{"type":30,"value":2891},{"type":24,"tag":32,"props":2895,"children":2896},{},[2897,2899,2904],{"type":30,"value":2898},"読み込みは、書き込みで通った5段階を",{"type":24,"tag":60,"props":2900,"children":2901},{},[2902],{"type":30,"value":2903},"そのまま逆向きに",{"type":30,"value":2905},"降りるだけです。",{"type":24,"tag":32,"props":2907,"children":2908},{},[2909,2910,2916,2917,2923,2925,2930],{"type":30,"value":1638},{"type":24,"tag":46,"props":2911,"children":2913},{"className":2912},[],[2914],{"type":30,"value":2915},"getAllItems",{"type":30,"value":698},{"type":24,"tag":46,"props":2918,"children":2920},{"className":2919},[],[2921],{"type":30,"value":2922},"store.getAll()",{"type":30,"value":2924}," で値（",{"type":24,"tag":46,"props":2926,"children":2928},{"className":2927},[],[2929],{"type":30,"value":96},{"type":30,"value":2931},"）の配列を一括取得します。PIM v3 からはIDがバイナリ内に埋め込まれているので、外側のキーを一緒に返す必要はありません。cursor で1件ずつ走査する必要もなく、一行で済みます。",{"type":24,"tag":198,"props":2933,"children":2935},{"className":1685,"code":2934,"language":1687,"meta":7,"style":7},"async function getAllItems() {\n    // PIM v3 からは ID がバイナリ内に埋め込まれているため、外側のキーは不要。\n    // store.getAll() で値（Uint8Array）配列を一括取得する。\n    return await runTransaction(\"readonly\", (store) => store.getAll());\n}\n",[2936],{"type":24,"tag":46,"props":2937,"children":2938},{"__ignoreMap":7},[2939,2964,2972,2980,3050],{"type":24,"tag":138,"props":2940,"children":2941},{"class":209,"line":18},[2942,2946,2950,2955,2960],{"type":24,"tag":138,"props":2943,"children":2944},{"style":213},[2945],{"type":30,"value":2054},{"type":24,"tag":138,"props":2947,"children":2948},{"style":213},[2949],{"type":30,"value":2059},{"type":24,"tag":138,"props":2951,"children":2952},{"style":230},[2953],{"type":30,"value":2954}," getAllItems",{"type":24,"tag":138,"props":2956,"children":2957},{"style":236},[2958],{"type":30,"value":2959},"()",{"type":24,"tag":138,"props":2961,"children":2962},{"style":236},[2963],{"type":30,"value":1783},{"type":24,"tag":138,"props":2965,"children":2966},{"class":209,"line":256},[2967],{"type":24,"tag":138,"props":2968,"children":2969},{"style":2095},[2970],{"type":30,"value":2971},"    // PIM v3 からは ID がバイナリ内に埋め込まれているため、外側のキーは不要。\n",{"type":24,"tag":138,"props":2973,"children":2974},{"class":209,"line":265},[2975],{"type":24,"tag":138,"props":2976,"children":2977},{"style":2095},[2978],{"type":30,"value":2979},"    // store.getAll() で値（Uint8Array）配列を一括取得する。\n",{"type":24,"tag":138,"props":2981,"children":2982},{"class":209,"line":285},[2983,2987,2991,2995,2999,3003,3008,3012,3016,3020,3024,3028,3032,3036,3040,3045],{"type":24,"tag":138,"props":2984,"children":2985},{"style":269},[2986],{"type":30,"value":272},{"type":24,"tag":138,"props":2988,"children":2989},{"style":269},[2990],{"type":30,"value":1226},{"type":24,"tag":138,"props":2992,"children":2993},{"style":230},[2994],{"type":30,"value":1704},{"type":24,"tag":138,"props":2996,"children":2997},{"style":236},[2998],{"type":30,"value":239},{"type":24,"tag":138,"props":3000,"children":3001},{"style":1255},[3002],{"type":30,"value":1258},{"type":24,"tag":138,"props":3004,"children":3005},{"style":1261},[3006],{"type":30,"value":3007},"readonly",{"type":24,"tag":138,"props":3009,"children":3010},{"style":1255},[3011],{"type":30,"value":1258},{"type":24,"tag":138,"props":3013,"children":3014},{"style":236},[3015],{"type":30,"value":1273},{"type":24,"tag":138,"props":3017,"children":3018},{"style":236},[3019],{"type":30,"value":1178},{"type":24,"tag":138,"props":3021,"children":3022},{"style":298},[3023],{"type":30,"value":1905},{"type":24,"tag":138,"props":3025,"children":3026},{"style":236},[3027],{"type":30,"value":1731},{"type":24,"tag":138,"props":3029,"children":3030},{"style":236},[3031],{"type":30,"value":1778},{"type":24,"tag":138,"props":3033,"children":3034},{"style":298},[3035],{"type":30,"value":1847},{"type":24,"tag":138,"props":3037,"children":3038},{"style":236},[3039],{"type":30,"value":339},{"type":24,"tag":138,"props":3041,"children":3042},{"style":230},[3043],{"type":30,"value":3044},"getAll",{"type":24,"tag":138,"props":3046,"children":3047},{"style":236},[3048],{"type":30,"value":3049},"());\n",{"type":24,"tag":138,"props":3051,"children":3052},{"class":209,"line":294},[3053],{"type":24,"tag":138,"props":3054,"children":3055},{"style":236},[3056],{"type":30,"value":688},{"type":24,"tag":32,"props":3058,"children":3059},{},[3060,3062,3068,3070,3076],{"type":30,"value":3061},"C#側は ",{"type":24,"tag":46,"props":3063,"children":3065},{"className":3064},[],[3066],{"type":30,"value":3067},"List\u003Cbyte[]>",{"type":30,"value":3069}," で受け取り、各バイナリを直接 ",{"type":24,"tag":46,"props":3071,"children":3073},{"className":3072},[],[3074],{"type":30,"value":3075},"MessagePackSerializer.Deserialize\u003CMusicDataModel>",{"type":30,"value":3077}," に渡します。",{"type":24,"tag":198,"props":3079,"children":3081},{"className":200,"code":3080,"language":202,"meta":7,"style":7},"public async Task\u003CList\u003CMusic>> ReadAllFromLocalStorageAsync()\n{\n    var stored = await _storage.GetAllAsync();\n    var musics = new List\u003CMusic>(stored.Count);\n\n    foreach (var bin in stored)\n    {\n        var (result, music) = Read(bin);\n        if (result is ReadResult.Success && music is not null)\n        {\n            musics.Add(music);\n        }\n    }\n\n    return musics;\n}\n",[3082],{"type":24,"tag":46,"props":3083,"children":3084},{"__ignoreMap":7},[3085,3131,3138,3176,3231,3238,3272,3279,3328,3386,3393,3422,3429,3436,3443,3458],{"type":24,"tag":138,"props":3086,"children":3087},{"class":209,"line":18},[3088,3092,3096,3100,3104,3109,3113,3117,3122,3127],{"type":24,"tag":138,"props":3089,"children":3090},{"style":213},[3091],{"type":30,"value":769},{"type":24,"tag":138,"props":3093,"children":3094},{"style":213},[3095],{"type":30,"value":1128},{"type":24,"tag":138,"props":3097,"children":3098},{"style":224},[3099],{"type":30,"value":1133},{"type":24,"tag":138,"props":3101,"children":3102},{"style":236},[3103],{"type":30,"value":1138},{"type":24,"tag":138,"props":3105,"children":3106},{"style":224},[3107],{"type":30,"value":3108},"List",{"type":24,"tag":138,"props":3110,"children":3111},{"style":236},[3112],{"type":30,"value":1138},{"type":24,"tag":138,"props":3114,"children":3115},{"style":224},[3116],{"type":30,"value":51},{"type":24,"tag":138,"props":3118,"children":3119},{"style":236},[3120],{"type":30,"value":3121},">>",{"type":24,"tag":138,"props":3123,"children":3124},{"style":230},[3125],{"type":30,"value":3126}," ReadAllFromLocalStorageAsync",{"type":24,"tag":138,"props":3128,"children":3129},{"style":236},[3130],{"type":30,"value":1158},{"type":24,"tag":138,"props":3132,"children":3133},{"class":209,"line":256},[3134],{"type":24,"tag":138,"props":3135,"children":3136},{"style":236},[3137],{"type":30,"value":262},{"type":24,"tag":138,"props":3139,"children":3140},{"class":209,"line":265},[3141,3145,3150,3154,3158,3163,3167,3172],{"type":24,"tag":138,"props":3142,"children":3143},{"style":213},[3144],{"type":30,"value":815},{"type":24,"tag":138,"props":3146,"children":3147},{"style":230},[3148],{"type":30,"value":3149}," stored",{"type":24,"tag":138,"props":3151,"children":3152},{"style":236},[3153],{"type":30,"value":306},{"type":24,"tag":138,"props":3155,"children":3156},{"style":213},[3157],{"type":30,"value":1226},{"type":24,"tag":138,"props":3159,"children":3160},{"style":298},[3161],{"type":30,"value":3162}," _storage",{"type":24,"tag":138,"props":3164,"children":3165},{"style":236},[3166],{"type":30,"value":339},{"type":24,"tag":138,"props":3168,"children":3169},{"style":230},[3170],{"type":30,"value":3171},"GetAllAsync",{"type":24,"tag":138,"props":3173,"children":3174},{"style":236},[3175],{"type":30,"value":1480},{"type":24,"tag":138,"props":3177,"children":3178},{"class":209,"line":285},[3179,3183,3188,3192,3196,3201,3205,3209,3213,3218,3222,3227],{"type":24,"tag":138,"props":3180,"children":3181},{"style":213},[3182],{"type":30,"value":815},{"type":24,"tag":138,"props":3184,"children":3185},{"style":230},[3186],{"type":30,"value":3187}," musics",{"type":24,"tag":138,"props":3189,"children":3190},{"style":236},[3191],{"type":30,"value":306},{"type":24,"tag":138,"props":3193,"children":3194},{"style":213},[3195],{"type":30,"value":277},{"type":24,"tag":138,"props":3197,"children":3198},{"style":224},[3199],{"type":30,"value":3200}," List",{"type":24,"tag":138,"props":3202,"children":3203},{"style":236},[3204],{"type":30,"value":1138},{"type":24,"tag":138,"props":3206,"children":3207},{"style":224},[3208],{"type":30,"value":51},{"type":24,"tag":138,"props":3210,"children":3211},{"style":236},[3212],{"type":30,"value":1252},{"type":24,"tag":138,"props":3214,"children":3215},{"style":298},[3216],{"type":30,"value":3217},"stored",{"type":24,"tag":138,"props":3219,"children":3220},{"style":236},[3221],{"type":30,"value":339},{"type":24,"tag":138,"props":3223,"children":3224},{"style":298},[3225],{"type":30,"value":3226},"Count",{"type":24,"tag":138,"props":3228,"children":3229},{"style":236},[3230],{"type":30,"value":842},{"type":24,"tag":138,"props":3232,"children":3233},{"class":209,"line":294},[3234],{"type":24,"tag":138,"props":3235,"children":3236},{"emptyLinePlaceholder":1113},[3237],{"type":30,"value":1116},{"type":24,"tag":138,"props":3239,"children":3240},{"class":209,"line":320},[3241,3246,3250,3255,3259,3264,3268],{"type":24,"tag":138,"props":3242,"children":3243},{"style":269},[3244],{"type":30,"value":3245},"    foreach",{"type":24,"tag":138,"props":3247,"children":3248},{"style":236},[3249],{"type":30,"value":1178},{"type":24,"tag":138,"props":3251,"children":3252},{"style":213},[3253],{"type":30,"value":3254},"var",{"type":24,"tag":138,"props":3256,"children":3257},{"style":230},[3258],{"type":30,"value":854},{"type":24,"tag":138,"props":3260,"children":3261},{"style":269},[3262],{"type":30,"value":3263}," in",{"type":24,"tag":138,"props":3265,"children":3266},{"style":298},[3267],{"type":30,"value":3149},{"type":24,"tag":138,"props":3269,"children":3270},{"style":236},[3271],{"type":30,"value":253},{"type":24,"tag":138,"props":3273,"children":3274},{"class":209,"line":351},[3275],{"type":24,"tag":138,"props":3276,"children":3277},{"style":236},[3278],{"type":30,"value":291},{"type":24,"tag":138,"props":3280,"children":3281},{"class":209,"line":373},[3282,3286,3290,3294,3298,3302,3306,3310,3315,3319,3324],{"type":24,"tag":138,"props":3283,"children":3284},{"style":213},[3285],{"type":30,"value":1458},{"type":24,"tag":138,"props":3287,"children":3288},{"style":236},[3289],{"type":30,"value":1178},{"type":24,"tag":138,"props":3291,"children":3292},{"style":230},[3293],{"type":30,"value":1962},{"type":24,"tag":138,"props":3295,"children":3296},{"style":236},[3297],{"type":30,"value":1273},{"type":24,"tag":138,"props":3299,"children":3300},{"style":230},[3301],{"type":30,"value":248},{"type":24,"tag":138,"props":3303,"children":3304},{"style":236},[3305],{"type":30,"value":1731},{"type":24,"tag":138,"props":3307,"children":3308},{"style":236},[3309],{"type":30,"value":306},{"type":24,"tag":138,"props":3311,"children":3312},{"style":230},[3313],{"type":30,"value":3314}," Read",{"type":24,"tag":138,"props":3316,"children":3317},{"style":236},[3318],{"type":30,"value":239},{"type":24,"tag":138,"props":3320,"children":3321},{"style":298},[3322],{"type":30,"value":3323},"bin",{"type":24,"tag":138,"props":3325,"children":3326},{"style":236},[3327],{"type":30,"value":842},{"type":24,"tag":138,"props":3329,"children":3330},{"class":209,"line":382},[3331,3335,3339,3343,3347,3352,3356,3361,3365,3369,3373,3378,3382],{"type":24,"tag":138,"props":3332,"children":3333},{"style":269},[3334],{"type":30,"value":1173},{"type":24,"tag":138,"props":3336,"children":3337},{"style":236},[3338],{"type":30,"value":1178},{"type":24,"tag":138,"props":3340,"children":3341},{"style":298},[3342],{"type":30,"value":1962},{"type":24,"tag":138,"props":3344,"children":3345},{"style":213},[3346],{"type":30,"value":1188},{"type":24,"tag":138,"props":3348,"children":3349},{"style":224},[3350],{"type":30,"value":3351}," ReadResult",{"type":24,"tag":138,"props":3353,"children":3354},{"style":236},[3355],{"type":30,"value":339},{"type":24,"tag":138,"props":3357,"children":3358},{"style":224},[3359],{"type":30,"value":3360},"Success",{"type":24,"tag":138,"props":3362,"children":3363},{"style":213},[3364],{"type":30,"value":2622},{"type":24,"tag":138,"props":3366,"children":3367},{"style":298},[3368],{"type":30,"value":248},{"type":24,"tag":138,"props":3370,"children":3371},{"style":213},[3372],{"type":30,"value":1188},{"type":24,"tag":138,"props":3374,"children":3375},{"style":213},[3376],{"type":30,"value":3377}," not",{"type":24,"tag":138,"props":3379,"children":3380},{"style":213},[3381],{"type":30,"value":1193},{"type":24,"tag":138,"props":3383,"children":3384},{"style":236},[3385],{"type":30,"value":253},{"type":24,"tag":138,"props":3387,"children":3388},{"class":209,"line":421},[3389],{"type":24,"tag":138,"props":3390,"children":3391},{"style":236},[3392],{"type":30,"value":379},{"type":24,"tag":138,"props":3394,"children":3395},{"class":209,"line":452},[3396,3401,3405,3410,3414,3418],{"type":24,"tag":138,"props":3397,"children":3398},{"style":298},[3399],{"type":30,"value":3400},"            musics",{"type":24,"tag":138,"props":3402,"children":3403},{"style":236},[3404],{"type":30,"value":339},{"type":24,"tag":138,"props":3406,"children":3407},{"style":230},[3408],{"type":30,"value":3409},"Add",{"type":24,"tag":138,"props":3411,"children":3412},{"style":236},[3413],{"type":30,"value":239},{"type":24,"tag":138,"props":3415,"children":3416},{"style":298},[3417],{"type":30,"value":837},{"type":24,"tag":138,"props":3419,"children":3420},{"style":236},[3421],{"type":30,"value":842},{"type":24,"tag":138,"props":3423,"children":3424},{"class":209,"line":461},[3425],{"type":24,"tag":138,"props":3426,"children":3427},{"style":236},[3428],{"type":30,"value":1356},{"type":24,"tag":138,"props":3430,"children":3431},{"class":209,"line":483},[3432],{"type":24,"tag":138,"props":3433,"children":3434},{"style":236},[3435],{"type":30,"value":1380},{"type":24,"tag":138,"props":3437,"children":3438},{"class":209,"line":491},[3439],{"type":24,"tag":138,"props":3440,"children":3441},{"emptyLinePlaceholder":1113},[3442],{"type":30,"value":1116},{"type":24,"tag":138,"props":3444,"children":3445},{"class":209,"line":530},[3446,3450,3454],{"type":24,"tag":138,"props":3447,"children":3448},{"style":269},[3449],{"type":30,"value":272},{"type":24,"tag":138,"props":3451,"children":3452},{"style":298},[3453],{"type":30,"value":3187},{"type":24,"tag":138,"props":3455,"children":3456},{"style":236},[3457],{"type":30,"value":901},{"type":24,"tag":138,"props":3459,"children":3460},{"class":209,"line":568},[3461],{"type":24,"tag":138,"props":3462,"children":3463},{"style":236},[3464],{"type":30,"value":688},{"type":24,"tag":25,"props":3466,"children":3468},{"id":3467},"まとめ",[3469],{"type":30,"value":3467},{"type":24,"tag":2502,"props":3471,"children":3472},{},[3473,3498,3510],{"type":24,"tag":122,"props":3474,"children":3475},{},[3476,3478,3483,3484,3489,3491,3496],{"type":30,"value":3477},".NET 6以降の ",{"type":24,"tag":46,"props":3479,"children":3481},{"className":3480},[],[3482],{"type":30,"value":1030},{"type":30,"value":698},{"type":24,"tag":46,"props":3485,"children":3487},{"className":3486},[],[3488],{"type":30,"value":88},{"type":30,"value":3490}," を ",{"type":24,"tag":46,"props":3492,"children":3494},{"className":3493},[],[3495],{"type":30,"value":96},{"type":30,"value":3497}," に直接変換できるため、Base64で文字列化する必要はない",{"type":24,"tag":122,"props":3499,"children":3500},{},[3501,3503,3508],{"type":30,"value":3502},"IndexedDBは",{"type":24,"tag":46,"props":3504,"children":3506},{"className":3505},[],[3507],{"type":30,"value":104},{"type":30,"value":3509},"なしで生のバイナリを直接入れる形が、自己完結したバイナリフォーマット（PIM）との相性が良い",{"type":24,"tag":122,"props":3511,"children":3512},{},[3513,3519],{"type":24,"tag":46,"props":3514,"children":3516},{"className":3515},[],[3517],{"type":30,"value":3518},"navigator.storage.persist()",{"type":30,"value":3520}," を忘れないこと",{"type":24,"tag":935,"props":3522,"children":3524},{"label":3523,"to":938},"PIMバイナリ側のフォーマット設計についてはこちら⬇️",[],{"type":24,"tag":3526,"props":3527,"children":3528},"style",{},[3529],{"type":30,"value":3530},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":256,"depth":256,"links":3532},[3533,3534,3535,3538,3539,3541,3542,3546,3547],{"id":27,"depth":256,"text":27},{"id":109,"depth":256,"text":109},{"id":158,"depth":256,"text":161,"children":3536},[3537],{"id":733,"depth":265,"text":733},{"id":743,"depth":256,"text":746},{"id":942,"depth":256,"text":3540},"レイヤー3 C#/JS境界を越える — byteを直接渡す",{"id":1630,"depth":256,"text":1633},{"id":2196,"depth":256,"text":2199,"children":3543},[3544,3545],{"id":2227,"depth":265,"text":2230},{"id":2576,"depth":265,"text":2579},{"id":2891,"depth":256,"text":2891},{"id":3467,"depth":256,"text":3467},"markdown","content:articles:tech:blazor:indexeddb-blazor-interop.md","content","articles/tech/blazor/indexeddb-blazor-interop.md","articles/tech/blazor/indexeddb-blazor-interop","md",{"title":3555,"description":3556},"MessagePackで独自バイナリファイル形式（PIM）をバージョン管理対応で設計する","音楽作成アプリPICOMで独自のバイナリファイル形式「PIM」をMessagePackで実装しました。なぜJSONでなくMessagePackを選んだのか、`[Key]`番号の運用ルール、将来のフォーマット進化に備えるVersionフィールド戦略について解説します。",1776664814847]