EasySqlParser 1.1.2 をリリース
バグがあったので修正しました
null値をバインドできないという比較的致命的なバグでした。
今回の修正でnull値を渡すとDBNull.Valueとして渡されます。
nugetアップロード済みです。
しかしバグ報告とかもないのは使われてないということか 😢
ChangeToken.OnChangeの罠
CI/CDとかクラウドとかまったく縁遠い中小企業にとっては.NET Framework初期のアプリの様に未だに設定ファイルをはじめ外部ファイルに大量依存、リリースも安心してできない、ブルーグリーンデプロイメントも当然できないといううれしくない状況なわけですが、そんな環境だと例えば外出しのSQLファイルだけ変えて仕様変更に対応するといったことをしたくなります。
で、.NET Coreにはファイルの変更を検知してゴニョニョするためのChangeToken.OnChange
という静的メソッドがあります。
※ASP.NET Coreとあるがコンソールアプリでも問題ないので気にしない
簡単に実装できそうだったが、なぜか検知してくれなかった。
結論としてはIFileProvider
のWatch
メソッドが絶対パスだとダメだったというオチだった。
なので正確にはPhysicalFileProvider.Watch(String) メソッドの仕様といったところなのかもしれない。
Watchメソッドはglobパターンで複数のファイルをWatchできるが、変更されたファイル1つに対してのみ何かアクションを起こしたいとき1は、globパターンで使っていると都合が悪いのでそのような場合はサンプルのようにすればいいかと思います。
1978-2020
コービー・ブライアント事故死
彼を知る世界中の誰しもがこんなことになるとは想像もしていなかっただろう
かく言う私もそのうちの一人
あまりにも突然過ぎて実感がない
しかしNBA公式が彼の画像とともに出したこの「1978-2020」という数字が現実のもので受け入れるしかないと思いつつも、いまだに信じられないという気持ちもある
コービーとともにコートで戦った選手や、コービーに憧れてNBAに入った選手ならなおさらショックは大きいのだろう
常に努力し続けること1
それを教えてくれた彼は間違いなく私のメンターだった
デビュー時から引退までコービーをリアルタイムで見続けることができたのは今考えると幸せだったなと思う
ありがとう!コービー!
これからもITエンジニアの端くれとして戦っていこうと思う(自戒の意味も込めて)
-
マンバメンタリティともいう↩
EasySqlParser 1.1.1 をリリース
バグがあったので修正しました
気付いた背景
知人からDb2のパラメータプリフィックス1は @
じゃなくて :
じゃね?
とツッコミが入ってそんなバカなと思い、確かめたものの結論としては @
のままでよかったのですが
そう言えば ODBC
は位置パラメータしか使えないが確かめたっけ??
と、怪しくなったので確認すると
見事に落ちてしまったというわけです
まぁいまどき ODBC
や OLEDB
を好き好んで使う人はいないと思いますが
各DB(IDbDataParameter実装型別)のパラメータプリフィックス
ついでなのでローカルでメモしていたものを共有するために書いておきます
DB | IDbDataParameter実装 | パラメータプリフィックス |
---|---|---|
SQL Server | SqlParameter | @ |
Db2 | DB2Parameter | @ |
As400 | iDB2Parameter | @ |
SQLite | SQLiteParameter | @ |
MySql | MySqlParameter | @ |
Oracle | OracleParameter | : |
PostgreSQL | NpgsqlParameter | : |
パラメータプリフィックスの参考資料
- OdbcParameter
- OleDbParameter
- SqlParameter
- OracleParameter
- NpgsqlParameter
- MySqlParameter
- DB2Parameter
- Db2だけ群を抜いてドキュメントが探しにくい
吐き気がするレベルで酷い
- SqliteParamter
-
と、私は読んでいるが正式名称は分からない↩
Nuget Packageの作り方
EasySqlParserでNuget Packageを作るときにハマったのでメモ
昔はCUI(Nugetコマンド)とかGUI(NuGet Package Explorer)とかでやってたましたが.NET Standardではdotnetコマンドでやります
cd プロジェクトファイルがあるディレクトリ dotnet pack -c Release rem デバッグシンボルも含める場合 rem dotnet pack -c Release --include-symbols
いやー、楽になったもんです
昔やったときはnuspecとかいうNugetパッケージを作るための元ネタ(ライブラリのバージョンとか依存関係とか)となるxmlを作る必要があったんですがそれは不要になりました
.NET Standardではそれらの情報をどこに書くかというとプロジェクトファイルに書きます
別ファイルに書くより断然楽です
Nugetパッケージができたらサーバにプッシュします
dotnet nuget push xxx.nupkg
ハマったところ
上記の情報はググればわりとヒットします
ハマったのは2019でやろうとしたときのことです
2017時代の情報はここに載っていますが、2019と比べると何かが違う
ライセンスが2017ではライセンスファイルへのURL指定だったものが2019では「MIT」とか「Apache-2.0」とか単なる文字列を指定するように変わっていました
どういう文字列ならいいのかという話ですが、これはSPDX識別子というもののようでここから選んで指定します
まとめ
.NET Standardでは…
ライブラリのバージョンの情報などはプロジェクトファイル(csprojとか)に書く
PackageLicenseExpressionはSPDX識別子から選ぶ
Nugetパッケージはdotnetコマンドで作る
おまけ
これを見る限りは以前に比べてプライベートリポジトリが増えているようなので、社内のライブラリでも利用するようにすれば管理が楽になると思います
参考
ASP.NET Coreのカスタムタグでハマった話
Javaではけっこうカスタムタグを作ったことがありますが、ASP.NET Coreではそのカスタムタグがかなり簡単に作れて感動しました
しかし少し凝ったことをしようと思ったら意外とハマったのでメモっておきます
何をしたいのか
<permissionControlManager> <input asp-for="Name"/> <input asp-for="Age" /> </permissionControlManager>
class PermissionControlManagerTagHelper : TagHelper { // 省略 }
permissionControlManagerみたいなタグをまず作っておいて、
その中に適当にinputタグとが突っ込んだらpermissionControlManagerに囲まれた項目を条件(ユーザIDとかロールとか)によって読み取り専用、非活性、非表示とかにする
そこまでやるか??(´・ω・`) という気もしなくもないがそれはいったん置いておいて
外側のタグ(permissionControlManager)自体ものすごくシンプルなので問題ない
問題なのはその中に置くinputとかはそのinput自体が読み取り専用にしたり、非活性にしたりする必要があるので、通常のinput(ASP.NET Coreのinput=InputTagHelper)では使えない
そこで、そのInputTagHelperを継承して作ってやる必要が出てくるわけですが
どういうわけかhtmlのinput(≠InputTagHelper)までカスタムタグだと判断されてしまって半日ほど時間を無駄にしました
結果から行くとクラスに付ける HtmlTargetElement 属性の指定の仕方をミスってたというオチでした
// 1 // アカンやつ [HtmlTargetElement("input")] // 2 // これもアカンやつ [HtmlTargetElement("input", Attributes = "asp-for", TagStructure = TagStructure.WithoutEndTag)] // https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/Mvc.TagHelpers/src/InputTagHelper.cs // と同じもの // 3 // イケてるやつ [HtmlTargetElement("input", Attributes = "hoge, asp-for", TagStructure = TagStructure.WithoutEndTag)]
Attributesの中身で判断しているようで、
1 Attributesが無いので全inputが根こそぎカスタムタグ扱いになる
2 Attributesがあるが、デフォルトのInputTagHelperと同じなのでhtmlのinputはカスタムタグ扱いされないが、拡張したInputTagHelperも元のInputTagHelperも同じカスタムタグ扱いになる
3 Attributesにデフォルトの「asp-for」のほかに「hoge」があるので、inputタグにasp-forとhoge属性があれば拡張InputTagHelperで、asp-forだけならデフォルトのInputTagHelper扱いになる
ドキュメントのAttributesの説明を見てもセレクタと書いてあるだけで今一つピンとこないのは英語慣れしてないからなのかな?
同じようなところでハマっている人がいたら HtmlTargetElement に気を付けてください
ドキュメントの補足 その1
動機は書き終わったのでドキュメントでは説明しきれないところなどを書いていこうかと思います
その1としてますが1だけで終わるかもしれませんw
名前
ソースコード中にも明記してますし、ドキュメントにも書いていますが
EasySqlParser内部のコードはDOMAの移植となっています
ならDOMA.NetとかnDOMAとかにしとくのがセオリーかもしれませんが、最初からDOMAを移植しようと思ったわけではありません
最初はパース処理を正規表現を駆使して、独自に書いていましたが、テストをしているとどうも遅いような気になって試しにDOMAを移植してみようかなと思って移植してみたら倍くらい速度が違いましたww
DOMAは1文字ずつ読み取っているから遅いんじゃないの?と高を括っていたのですがそんなことはなかった
10年くらい歴史があり、ググってたくさん情報が出てくるだけのことはあります
ちなみにEasySqlParserは最初から名前を決めていました
nugetを検索しても同じものが見つからないことを確認しながら…
また、DaoにもDomainにもマッピングのどれとも無関係なためDOMA.NetとかnDOMAと名付けるとか理解不能、理解不能(しげちー風)
マッピングとかせずに「単純にSQLをパースする」だけなのでそのまま名付けてEasySqlParserです1
なぜマッピングしないのにDB種別とか気にする必要があるのか
これはページングの際に必要だからです
ページングでは単一のSQLファイルからカウント文とデータ取得文を内部で生成しています
これ自体はDOMAのパクリ移植です
ページングのSQLは OFFSET
+ LIMIT
だったり、ROW_NUMBER
だったりとDBによってかなり違います
これを実現するためにDBが何なのかの情報が必要になってくるわけです
しかし、つい最近ようやくMySQLで ROW_NUMBER
がサポートされて、メジャーRDB(Microsoft SQL Server,Oracle,Db2,PostgreSQL,MySql,SQLite)すべてで ROW_NUMBER
がサポートされました2
そこでEasySqlParserではオリジナルの機能として、DBの種別を無視してこの ROW_NUMBER
を使用してデータ取得文を生成するようなオプションを用意しました
ドキュメントにもあるようにこのオプションを使用することでView層での行番号表示が容易に実現できます
これはサンプルアプリでも確認ができます