tekitoumemo’s diary

C#、.NET系の技術ブログを書いています。みんなの洋楽ランキングを運営しています。

C#史上最強なORマッパーを使ってみた

C#のORマッパーはEntity Framework(以下EF)をはじめ、Dapper、PetaPoco等が有名ですが、とにかくどれも微妙な完成度でRailsのActiveRecodeみたいなものがありません(Entity Frameworkがそれですが、とにかく遅い)。Dapperほどの速度が出てビルダーマッピングをしてくれるライブラリがないのかなと思って探したらありました。

sqlkata.com

見る限りだとビルダーを備えててDapper依存しているから確実に早いだろうと予測。Joinも含まれてるのでマッピングしてくれれば、おそらくC#史上最強なORマッパー。ってかなんて読むのこれ?えすきゅーえるかた?

使ってみます。

まずNugetから

SqlKataとSqlKata.Executionを落とします。現在(2/15時点)は1.1.6が最新です。

dotnet add package SqlKata --version 1.1.6
dotnet add package SqlKata.Execution --version 1.1.6

今回はSQLServerを使うのでSqlClientも取ってきます。

dotnet add package System.Data.SqlClient

SqlKataを使う準備

using SqlKata;
using SqlKata.Compilers;
using SqlKata.Execution;
using System.Data.SqlClient;

var connection = new SqlConnection("");
var compiler = new SqlServerCompiler();
var db = new QueryFactory(connection, compiler);

compilerはビルダーからSQLを生成するオブジェクトでdbを使ってビルダーを使います。

ビルダーを使う

まずはSELECT
db.Query("Posts").Select("Id", "Title", "CreatedAt as Date");

これが以下になります。

SELECT [Id], [Title], [CreatedAt] AS [Date] FROM [Posts]

次はJOIN

db.Query("Posts").Join("Authors", "Authors.Id", "Posts.AuthorId");

これが以下になります。

SELECT * FROM [Posts] INNER JOIN [Authors] ON [Authors].[Id] = [Posts].[AuthorId]

ここら辺はドキュメントが豊富なので以下を参考にしてください。
sqlkata.com

データを取得する

なんどデータ取得も出来ます。Dapperにフル依存してるので。

取得にはGetを使います。

db.Query("Posts").Select("Id", "Title", "CreatedAt as Date");.Get()

これだと戻りがdynamicなのでジェネリックで指定します。

db.Query("Posts").Select("Id", "Title", "CreatedAt as Date");.Get<Posts>()

これでPostクラスの型でマッピングされます。

Joinしたデータを取得する

ビルダー備えてマッピングまでやるならJoinでいけるのか!?という疑問があったので試してみました。
クラスを用意します。

public class Hoge {
    public int Id { get; set; }
    public int PiyoId { get; set; }
    public Piyo Piyo { get; set; }
}

public class Piyo {
    public int Id { get; set; }
}

ビルダー

var query = db.Query(nameof(Hoge))
     .Join(nameof(Piyo), "Hoge.PiyoId", "Piyo.Id")
     .OrderBy("Hoge.Id").Get<Hoge>();

queryをみましたがPiyoは入ってませんでした。やっぱりC#ではまだ無理そうです。EFかDapperで頑張りましょう。

SQLを生成する

ビルダーとしてはかなり優秀なのでSQLを生成してみます。ちなみに以下ではSQLを生成出来ません。

db.Query("Posts").Select("Id", "Title", "CreatedAt as Date")

ビルダーからSQLコンパイルします。

var compiler = new SqlServerCompiler();
var query = db.Query("Posts").Select("Id", "Title", "CreatedAt as Date")
var sql = compiler.Compile(query).Sql;

これでビルダーで作ったSQLが取得出来ました。

使ってみた結果として、ビルダーとしては優秀ですがマッピングはDapperと一緒なので結局は微妙なとこです。C#インピーダンスマッチは幻想なので無理に自作ライブラリなど作らずSQLゴリゴリ書いた方が効率が良いです。マッピングまでしてくれたら自分が作ったDapperの拡張ライブラリとさよならかと思ってましたがしばらくは付き合っていくはめになりそうです。
github.com
コネクションやDapperが依存しているとはいえ、ビルダーは依存させなくても使えるようです。

var db = new QueryFactory(); // なにも指定しなくておけ
var query = db.Query(nameof(Hoge))
    .Join(nameof(Piyo), "Hoge.PiyoId", "Piyo.Id")
    .OrderBy("Hoge.Id");
var sql = compiler.Compile(query).Sql;
// sql -> SELECT [Id], [Title], [CreatedAt] AS [Date] FROM [Posts]

どうしてもSQLを書きたくない人はこんな感じで使ってみても良いかも。構文ミスとかなくなるのでそこらへんは便利かも。
今後はマルチマッピングもIssueに上がってるのでキープしといても良いかも
github.com

ASP.NET Identityの外部ログインで任意の値をClaimに追加する

https://josealvarez.gallerycdn.vsassets.io/extensions/josealvarez/measpnetidentity/1.0/1482143264518/210260/1/screenshot.png

ASP.NET Identityを使っていて、ログイン後に任意の値を入れたいと思うことが多々あります。例えば、ユーザーを特定するIDやその他ユーザーに付随する情報など。ASP.NET Identityはセキュリティ上認証の際のみClaimに追加できないのでそのイベントのフックと追加方法を説明します。

外部ログインの追加は以下に書きましたので、知りたい方は以下へ。
tekitoumemo.hatenablog.com
tekitoumemo.hatenablog.com

tekitoumemo.hatenablog.com

FaceBook & Google

認証後はOnCreatingTicketへフックされ内部で処理が可能です。

.AddFacebook(facebookOptions =>
{
    facebookOptions.AppId = "";
    facebookOptions.AppSecret = "";
    facebookOptions.Fields.Add("picture");
    facebookOptions.Events = new OAuthEvents
    {
        OnCreatingTicket = context =>
        {
           context.Identity.AddClaim(new Claim("{ユーザーIDのKey}", {ユーザーIDのValue}));
           return Task.CompletedTask;
        }
    };
})

ちなみにFaceBookで画像を取得したい場合は以下のように指定します。

$"https://graph.facebook.com/{facebookのID}/picture"

Twitter

Twitterは特殊でTwitterEventsというものを扱います。ですが基本的にはOAuthEventsと同じです。

.AddTwitter(twitterOptions =>
{
    twitterOptions.ConsumerKey = "";
    twitterOptions.ConsumerSecret = "";
    twitterOptions.Events = new TwitterEvents()
    {
        OnCreatingTicket = async context =>
        {
            Identity.AddClaim(new Claim("{ユーザーIDのKey}", {ユーザーIDのValue}));
            await Task.CompletedTask;
        }
    };
})

SNSのIDを使いまわしても良いのですが、結構めんどい部分が出てくるので任意の値を入れられるのは良いと思いました。あと意外にこの手の記事がなかったよ.NET 普及しろ

Spotifyの.Netライブラリが凄く良かったよ

http://www.scdn.co/i/_global/open-graph-default.png

SpotifyApiをみんなの洋楽ランキングで使いたかったのでラッパーライブラリを途中まで作ってました。
github.com
が、相当完成度の高いライブラリがありましたので自前で実装するのをやめてSpotifyAPI-NETと言うものを使いました。
github.com

Client IDとClient Secretを取得

以下を参考にしてください。
dev.classmethod.jp

Spotifyインスタンスを生成

おそらくHttpClientを使ってるからstaticなのだろう

private static SpotifyWebAPI _spotify;

認証

超楽

var auth = new CredentialsAuth(clientId, clientSecret);
var token = await auth.GetToken();
_spotify = new SpotifyWebAPI() { TokenType = token.TokenType, AccessToken = token.AccessToken };

検索

_spotify.SearchItems("ariana grande", SearchType.Artist);
_spotify.SearchItemsAsync("ariana grande", SearchType.Artist);

アーティスト検索

_spotify.GetArtist(id);
_spotify.GetArtistAsync(id);

スタートガイド

ざっと始めるにはここ見れば一瞬でわかります。ドキュメントも豊富で超便利!
SpotifyAPI-NET/gettingstarted.md at master · JohnnyCrazy/SpotifyAPI-NET · GitHub

APIのwrapperライブラリのメリット

この手のライブラリのメリットはC#だとモデルクラス作る手間がなかったり、API側のバージョンをライブラリに任せられるのが良いですね。ググってライブラリが見つかってStart50以上あったらだいたい使っても大丈夫っす。これは500以上あるのでかなりよいかも。CoreTweetでも200前後だし。あとこれも日本語情報ないよなぜに!?

vscodeのCode Helperが100%になる問題を解決した

https://blog.launchdarkly.com/wp-content/uploads/2018/10/visualstudio_code-card.png

僕はvscodeで開発してるのですが、最近デバッグすると激重になってデバッガをほとんど使っていませんでした。Reactベースの開発がほとんどでChrome DevToolでサーバーサイドは対してデバッグする必要ないので気にしてなかったんです。ただ、最近構造を大幅に変更することもあってとてもじゃないけど開発出来るレベルじゃなかったので解決方法を気合いで探しました。解決できたのでやったことをいくつか書きます。

files.wathcherExclude

ファイルの監視対象から外すやり方。「vscode 重い mac」とかで調べると必ず出てくる方法。node_moduleとか対象に入ってると激重になるのですが、監視対象を外しても意味なかったです。
qiita.com

プラグインをひたすら外す

TSLintやらAzure系のプラグインやらひたすら外しました。これも全く関係なかった。

リクエスト系のミドルウェアの見直し

これは.Net Core限定っす。app.UseやHeadersでキャッシュさせない設定が入っていたので全部外す。Httpsも外す。全く意味なし。

package.jsonの見直し

これはフロントエンド使っている人限定。まず使ってないやつを削除。効果なし。次に「hot」って書いてあるプラグインを疑う。だいたいリロードしなくてもJSを更新したりTypeScriptを更新したりするもの。超絶怪しいのでまずはバージョンをあげて様子見。効果なし。僕の場合はCtrl+Sで全ファイル保存のショートカットを入れていたのでTypescriptを保存しないように変更。サーバーサイドのファイル更新でも激重。意味なし。

もう諦める

「....」
https://2.bp.blogspot.com/--X2z5ldMf2A/WEOPX4Y31HI/AAAAAAABALg/pc0SbFkluPo4ImDnJxxQgGT2mq-96C9IACLcB/s400/neet_man2.png

Mac OS「Mojave」でNVIDIAのドライバが動かないという記事を見つける

NVIDIAのドライバのせいでElectron系(ATOMとか)のソフトが軒並み重くなったらしい。Macbook airなので関係ないがhigh sierraに下げようか検討する。流石にだるくてやめる

やっぱwebpackが怪しいよ

やはり保存する度に重くなる。絶対これだ。vscodeデバッグコンソールを眺めながらエディタを動かしまくる。

「....」

「これだ!!!」

f:id:tekitoumemo:20190207224858p:plain

__webpack_hmrってのが404になってるじゃないですか!!調べてみるとHMR(Hot Module Reloading)の更新通知に用いられるもの。絶対これと思ったが適当なReactプロダクト作って試しても重くない。。

「あ、これだ」

tekitoumemo.hatenablog.com
以前作ったエラーハンドリングが引っかかって毎回Viewを表示してる。絶対これ。Startup.csを変える

app.UseStatusCodePagesWithReExecute("/xxxxxxxx");

すげー適当だけどこれでルーティングに引っかからないから大丈夫なはず!

結果

元通りになりました。

ユーザー車検に向けて整備

3年前に購入した中古車の車検の季節がやってきました。

ユーザー車検は二回目ですが、前回はノー整備で余裕合格だったんで今回はある程度自分で整備します。

まず、オートバックスとかで見積もりを取る

車に詳しい人はここを端折っても良いのですがわからない人はある程度見てもらった方が良いでしょう。こんな感じでとりあえずいろんなものが見積もりに付けられます。

ここで気をつけて欲しいことをいくつか。
・オイル交換系(エレメント、フラッシング)
これは基本マメにやってる人が多いのでいらないっす。まず、車検でここはチェックされない。タイミングが合えばやればいい程度。フラッシングは一生やらなくていいと個人的には思ってる。
・エアコンフィルター
意味が分からない。オプションの車もあるので車検関係ない。自分で余裕で交換できる
ブレーキフルード
量あれば余裕。
・アンダーコーティング
意味不明。
・ブレーキパッド
多少あれば余裕で通るけど、足回りは交換しても良いかも。店舗だと純正品に交換させられて高いからモノタロウとかでちゃんとした社外品買ってつけても良いかも。
・ワイパー
たしか見てなかった気がする。ぶっちゃけ関係ないので気が向いたら交換程度でおけ
・タイロットエンドブーツとロアアームブーツ
ここで車検落ちる人が多いらしい。基本破れてなければオッケーで、ちょっとヤバくても受かると思う。モノタロウで300円程度だから交換しても良いかも。俺はヤバかった。

整備

僕がやった範囲で説明します。

違和感がないか

異音、エンジン掛けるとき、ブレーキ、アクセルらへんを確認。普通に走ってればだいたい大丈夫。

ウォッシャー液

イッチバン安いので良い。200円で買える。水より安い

オイル漏れ

ここは確認しづらいですが、駐車場などでエアコンかけずに5分ぐらいエンジンかけたまんまニュートラルにします。それで車を移動して、車のあった場所が濡れてないか確認。オイルっぽくなければおけ。

ブレーキパッド

テッチンだとタイヤ外さないと見えない。社外のホイールおススメ。これは目視で確認できる。MKカシヤマってのが信用出来るのかな?

タイロットエンド周り

先程貼った画像の箇所。ブーツが破れてグリス出てないか確認。この大野ゴム工業が割と信頼出来るのかな?ちなみにタイロットエンド自体交換しろと言ってくるところは無視。ロアアームはあまり劣化しないから基本大丈夫なはず。

タイヤ

社外ホイールの場合、このマーク確認。だいたい付いてるが。

注意

無理せず、業者にお願いしよう!特に中古車買った人は、前のオーナーがどんな整備してるか不明なので見てもらうこと大事!僕の場合、タイロットエンドにパッキンされてて意味わからないことになってました。持ち込みでやってくれるとこ結構あるので、好きな方法で換えましょう。

ユーザー車検のメリット

値段が安い。法的費用は車にもよりますが二桁万円は行きません。店舗だと法的費用の2.5倍かかるので圧倒的におトク。車の維持費はここが結構ネックなので自分である程度見れると良い車が乗れます。プリウスとかノートとか無駄に高い車でなくカッコいい車に乗れるようになるので今回も自分で行こうと決めました。あとボロ車に金掛けたくない人多いと思うので、有給取って行ってみるのも良いのではないでしょうか。割と楽しいです。

ちなみに

今年まだ受けてませんが、受かる気しかしないです。またブログ書きます。

2018年振り返って

2018年はいろんなことがあったので振り返ります。

自己満日記ですが一応自己紹介は以下の記事で。

仕事のこと

フリーランスになった

給料とか給料とか給料とかでフリーに転身した。流石に受注とか自分のサービスで生計立てられないから業務委託。今年はずっと同じとこにいたので「あれ?転職したのかな俺?」ってよくわからない状態。下手するとあと一年以上は延長されるっぽいので、早めに退散しようと思ってる。

webサービス作った


趣味の延長。月5000〜10000pv程度の弱小サービス。割と楽しくやってるからおっけ。Twitterのフォロワーが増えなさすぎることが勉強になった(1000は行くと思った)

エンジニアにありがちなバックエンドのみの変更を繰り返したことは失敗。ユーザーに提供するのが一番大事。前職で無駄機能を付けるのは無意味ってことを分かってたんだが、億劫になり過ぎた。っか勘違いしてた。無駄機能と呼べるのは成熟期の話でしょっぱなはとりあえず作り込まなきゃダメ。話はそれから。

アーキテクチャは以下のブログ書いた

ブログ結構書いた

ほとんど.NET Core、たまにreact。普通に.NET Core最高過ぎて他のフレームワーク触る気起きない。技術的にはそんなに向上してない。Windows嫌いになった。

本当にやりたいことが見えてきた

仕事したくない
ほんとこれ。エンジニアとして一流になりたいとか全然ない。あとプログラムが好きなわけじゃなくて物作りが好きなので、たまたま一番お金かからないプログラムをやってただけなんだなと実感出来た。なので今年はアプリを作ろうと思ってる。言語はなんでもいいや、楽なやつがいい。

お金

結構使った。パソコンはWindowsLinux)とMacの二台買った。デスクトップはいらないなと思った。Azureに6万、GitHubに5000円ぐらい、freeeに一万。パソコンはしばらくいらないのでなんかキャンペーンとかにお金を使おうと思ってる。結構真面目にみんなの洋楽ランキングは成長させたい!洋楽好きだし。

人脈

むしろ減った。たまに勉強会とか行ったけど家でやったほうが捗るわ。何人かと絡んだけど意外に異業種の人と付き合った方がいい。前職からやたら声かかる。普通にすげー仕事させられるから行く気ゼロ。みんなの洋楽ランキング経由でTwitterで何人かと絡んだ。凄腕のエンジニアと未経験のエンジニアの違いがイマイチわからんくなった。凄腕のエンジニアより未経験おじさんのサイトの方がサイトまともってどゆこと!?とりあえず30半ば以上の人の行動力はイかれてる。

勉強

いろんなことが勉強になった。帳簿付けとか割と知らないことあってびっくり。技術面ではangularやっぱ良いなと実感。軌道に乗るといろいろ楽。reactもちょっとやった。俺は好きだけど、実務でやるとどうなんだろう。Azureも結構触った。何が良いの?って聞かれたらよくわかんないけど、値段も含めだいたいAzureで片付くのでそこぐらい。今年は資格取ろうかな。

プライベート

結婚した

28で結婚した。思ったより早かった。周りの見る目変わり過ぎ。今年に子どもが生まれるんでもっと楽しくなりそう。

洋楽よく聞いた

すげー聞いた。前も聞いてたけどspotifyにしてから恐ろしいぐらい聞いた。今年はいい曲が少なかったのでサラ・バレリスの「Love Song」を聞きまくった。これはマジで名曲。今年の曲だとこれかな。

結構休んだ

数週間とか平気で休むようになった。普通に休ませてくれる今の現場はかなり良い、さすが大企業。休み中はひたすらプログラムしてる感じかな。平日ほとんど出来ないし。

テラハめっちゃ見た

嫁と。部屋で引きこもってプログラムしてると怒られるからノート購入。机座らなくなった。Mac miniとディスプレイいらね。机も椅子もいらね。テラハかなりおもしろい全部見た。

健康

寝なくなった

基本定時帰りだけど、調べ物とかしてて夜中になる。睡眠不足みたいな。でも正社員みたいな面倒な人付き合いとかないから気持ち的にもプログラミングできて良かった。前職だとプログラム全くしたくなかったし、実際エンジニアの仕事してなかったし。

デブった

マジ太った。社会人になって6年だけど体重15キロ増えた。これはやばい。

タバコ吸い過ぎた

一日20本。アイコスにして複数吸い出来ないあの感じが減ったから無限に吸えちゃう。休日なんか一箱以上吸っちゃう。アイコスにしても意味ね。

食生活はまとも

基本作ってくれるので野菜とかめっちゃ食べてる。順調に太ってきた。やばい。

総括

わりと濃い一年。今年はどうしようか。サービス作るか。エンタメ系のサービスが良いな。〇〇を解決するサービスは作る気ゼロ。というかイかれてるクオリティ出さないと到底お金は取れない。3Dプリンタとかそこら辺が多分楽しいと思う。ぶっちゃけゲーム以外のソフトウェアは結構限界にきてると思う。ラズパイとか面白いと思う。

ASP.NET CoreのGoogle認証

f:id:tekitoumemo:20190106005729p:plain

前回、外部ログインのセットアップとFacebook認証までは説明したので今回はGoogle認証の追加だけです。不足してる情報は以下に書いたのでよかったらみてください。
tekitoumemo.hatenablog.com

tekitoumemo.hatenablog.com

前準備

https://console.developers.google.com/projectselector/apis/libraryGoogle Cloud Platform
でアプリを作成します。これもだいたい以下のURLに書いてます。
docs.microsoft.com
ここも基本的には「/signin-google」でcallback Urlを設定してください。
f:id:tekitoumemo:20190106010614p:plain

クライアント IDとクライアント シークレットを取得しておいてください。

Googlehttpsのみ対応しています。ssl入れてない人はあきらめましょう(多分)

Startupに登録

ConfigureServicesに以下を追加

services.AddAuthentication().AddGoogle(googleOptions =>
{
    googleOptions.ClientId = Configuration["Authentication:Google:ClientId"];
    googleOptions.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
});

Viewを作成

// これか
<a asp-action="SignIn" asp-route-provider ="Google">Google</a>
// これでもおけ
<a href="/auth/signin?provider=Google">Google</a>

これで前回のTwitterの記事と同じ要領で実装終了です。

めっちゃ楽!

Twitterの記事で書いたcallbackUrlとFacebookの記事で書いたhttpさえ解決出来ればすぐ実装出来ますね。

SNS認証は一通り出来たので次は他のことを実装しよう!
f:id:tekitoumemo:20190106011403p:plain
メアド認証がないとログイン画面が決まらんなぁ〜

次はrole関係を適当に書きます。