アーカイブ

Archive for the ‘プログラミング’ Category

dotnet publish時にp:PublishSingleFileを指定した場合、設定ファイルも一緒にパッケージングする

2019年12月17日 1件のコメント

単一ファイルで出力すると、ファイルサイズがデカいとか、起動が少し遅くなるとかありますが、ちょっとしたツールを配布するときはだいぶお手軽になります。

dotnet publish p:publishSingleFile=true

独自の設定ファイル(appsettings.json)のような単なるコンテンツファイルは、プロパティーウインドウで明示的にコピーされるようにしないと、パッケージに含まれてくれません。コメント 2019-12-17 190215

この状態でビルドしても、出力フォルダーには設定ファイルは見当たりませんが、実行するとちゃんと設定ファイルを読んでくれます。
コメント 2019-12-17 190402

これは、単一ファイルで配布した場合、実行時に一時フォルダー(%LocalAppData%\Temp.net[exe名]\ハッシュのディレクトリ)に展開され実行されるからです。
このため、単にプログラムと同じディレクトリに設定ファイルを置いたとしても設定を読み込んでくれないので、publish時に環境毎の設定ファイルを含めてあげるか、Microsoft.Extensions.Configurationのパターンのように、環境変数やコマンドライン変数から設定値を上書きできるように設計したほうが良さそうです。

カテゴリー:C#

EntityFramework Core 3.1 は .NET Standard 2.0をターゲットにしている

2019年12月6日 コメントを残す

.NET Core 3.1 に合わせて EntityFramework Core の 3.1 もリリースされています。
下記の記事でも触れられているように、この子は .NET Standard 2.0 をターゲットにしているようなので、.NET Core 2.2 以下でも使えるようになっているんですよね。

Announcing Entity Framework Core 3.1 and Entity Framework 6.4


https://github.com/aspnet/EntityFrameworkCore/issues/18141

ただ、うちで採用しているPomelo.EntityFrameworkCore.MySqlは.NET Standard 2.1をターゲットにしているので、こちらに引きずられちゃうんですけれどね、、、
https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql

カテゴリー:ASP.NET, C#, MySql

Razorlight の .NET Core 3.x 対応

2019年12月5日 コメントを残す

テキストのテンプレートエンジンとしてRazorlight(https://github.com/toddams/RazorLight)のbeta1を利用しています。.NET Core 3.1にアップグレードしたところ、下記のような例外が発生してRazorEngine の構成に失敗してしまいました。

InvalidOperationException: Cannot find reference assembly ‘Microsoft.AspNetCore.Antiforgery.dll’ file for package Microsoft.AspNetCore.Antiforgery

もともとbeta1を利用していたので、そろそろ正式版がリリースしている?とおもってプロジェクトサイトをのぞいてみたら、beta2で3.0に対応しているようなのでまずこいつのアップグレードをします(betaはとらない方針なのかな?nugetで出てこないから正式版にしてほしいけれど、、、)。

Razorlight v2.0.0-beta2 対応

betaリリースということなので、nugetの管理画面からインストールする場合は、プレリリースを含めるチェックボックスをオンにしてからインストールします。
razorlight-1.png

TemplateCacheを使っているコードとCompileRenderAsyncの非ジェネリック版を使っていると文句を言われるので修正します。

TemplateCacheの対応

変更前

var cacheResult = _razorEngine.TemplateCache.RetrieveTemplate(templateKey);
if (cacheResult.Success)
{ 

変更後

var cacheResult = _razorEngine.Handler.Cache.RetrieveTemplate(templateKey);
if (cacheResult.Success)
{ 

CompileRenderAsyncのジェネリック対応

変更前

var text = await _razorEngine.CompileRenderAsync(templateKey, templateText, vm);

変更後

var text = await _razorEngine.CompileRenderStringAsync(templateKey, templateText, vm);

これでコンパイルエラーと警告は消えたんだけれど、まだ同じエラーが出る、、、

Cannot find reference assembly への対応

.NET Core 3.1の既知の問題を見ると一番上にそれっぽい記述が、Preview2で対応されたとなっているけれど、、、
https://github.com/dotnet/core/blob/master/release-notes/3.1/3.1-known-issues.md

とりあえず、プロジェクトファイルにこの2行を足してみると、RazorEngine の構成自体は無事通るようになりました。

<PreserveCompilationReferences>true</PreserveCompilationReferences>
<PreserveCompilationContext>true</PreserveCompilationContext>

Razorlightが内部で使っているRoslyn向け言語バージョンの指定

実際にテンプレートからテキストの生成を行ってみると、こんな例外画面が!!
razorlight-2

あれ?.NET CoreのプロジェクトってC#の言語バージョンは変更できなかったような、、、
razorlight-3

…プロジェクトファイルに書いてありました!!7.3→8.0に変更したら、無事動きました。

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    ...
    <LangVersion>7.3</LangVersion>
    ...
    <PreserveCompilationReferences>true</PreserveCompilationReferences>
    <PreserveCompilationContext>true</PreserveCompilationContext>
  </PropertyGroup>
  ...
</Project>
カテゴリー:ASP.NET

Visual Studio Version 16.4.0のコンテナ用ツール

2019年12月4日 コメントを残す

.NET Core 3.1 に合わせて Visual Studio 2019 の最新版である Version 16.4.0 が同時に公開されましたが、このバージョンに含まれるコンテナ用のツールが結構よさげです。Kitematicでもいいんですが、表示されている情報が古かったりして微妙なことが多いので結構いいかも。

ツールメニュー > その他のウインドウ > コンテナー から起動できるこの子ですが、
vs20191204

コンテナを起動したり、起動しているコンテナの環境変数やポート情報を確認したり、
docker-env2

ログを表示したり、
docker-env

コンテナの中身のファイルして開いたり(!!)が簡単にできます。
残念ながらホストにファイルをコピーするなどは、ここからは行えないみたいですね。
docker-file

必要になったらコマンドアイコンをクリックすれば、コマンドプロンプトが開きます。
docker-terminal

統合ターミナル(Whack Whack Terminal)がインストールされていればそちらを起動してくれるみたいです。
docker-terminal2

Riderのコンテナツールもいい感じですよね

カテゴリー:Docker, Visual Studio

.NET Core 3.1 のリリース、12/23には.NET Core 2.2 がサポート終了

2019年12月4日 コメントを残す

今日(2019/12/03).NET Core 3.1のアナウンスがありダウンロードが可能になりました。

Announcing .NET Core 3.1

Announcing .NET Core 3.1

下記のページに.NET Coreのサポートポリシーが記載されていますが、今回のリリースはLTS付きなので、少なくとも3年の長期サポートが付きます。
https://dotnet.microsoft.com/platform/support/policy
→ 3.1のリリースに間に合っていないようでこちらのほうが最新の情報が載っていますね。
https://github.com/dotnet/core/blob/master/microsoft-support.md

これ自体は喜ばしいことなんですが、現行リリースである2.2とひとつ前のLTSである2.1のサポート終了時期が迫っているということにもなります。下記の表のとおり、2.2は2019/12/23、2.1は2020/03/03までのサポートになります。
コメント 2019-12-04 094546

Docs Microsoftの移行に関するドキュメント

ASP.NET Core 2.2 から3.0 への移行
https://docs.microsoft.com/ja-jp/aspnet/core/migration/22-to-30
ASP.NET Core 3.0 から3.1 への移行
https://docs.microsoft.com/ja-jp/aspnet/core/migration/30-to-31

コミュニティーの移行に関するドキュメント

ASP.NET Core / Entity Framework Core 3.0 の気になった機能と 2.2 からの移行

ASP.NET Core 2.2→3.0への移行 メモ

ASP.NET Core + Entity Framework Core のプロジェクトを 2.2 から 3.0 にアップグレードした話

カテゴリー:ASP.NET, C#

EventListener の OnEventSourceCreated メソッドはコンストラクター実行前に呼び出される

2019年11月28日 コメントを残す

EventListenerを継承するクラスを作っていてはまったのでメモ
下記のようなコードは、コンストラクターが完了する前にOnEventSourceCreatedが呼び出されるのでNull参照で落ちます。

public class GcEventListener: EventListener
{
    private readonly ILogger _logger;

    public GcEventListener(DiagnosticsConfig config, ILoggerFactory 
loggerFactory)
    {
        _logger = loggerFactory.CreateLogger();
    }
    protected override void OnEventSourceCreated(EventSource eventSource)
    {
        _logger.Information("test");
    }
}

対策としては、githubのissueにある通り、OnEventSourceCreated で受け取ったイベントソースのリストをいったん変数に格納しておいて、コンストラクターに戻ってから有効化する。
https://github.com/Microsoft/ApplicationInsights-dotnet/issues/1106

カテゴリー:ASP.NET, C#

.net core 3系のパフォーマンス系ツール

2019年11月25日 コメントを残す

ASP.NET のメトリクスを取りたい場合、Windows 環境であればパフォーマンスカウンターが使えるんだけれど、Linux 環境では ASP.NET Core から利用できるパフォーマンスカウンターなんてものは無いので、dotnet-counters ツールを利用します。
https://docs.microsoft.com/ja-jp/dotnet/core/diagnostics/dotnet-counters

SDK がインストール環境であれば、インストールコマンドを入力してパスを通してあげれば利用できるようになります。
docker 環境で SDK が入っていないイメージをもとに Build している場合は、先に SDK をインストールする必要があります。例えば、Visual Studio が作成する Dockerfile で利用される buster-slim の場合は、下記の URL を参考に SDK をインストールする必要があります。
https://dotnet.microsoft.com/download/linux-package-manager/sdk-3.0.101

あらかじめ、dotnet-counters ツールを使うことがわかっているなら、Dockerfile を書き換えてしまってもいいかもしれません、、、

wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.asc.gpg
sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/
wget -q https://packages.microsoft.com/config/debian/9/prod.list
sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list
sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list

sudo apt-get update
sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install dotnet-sdk-3.0

dotnet-counters ツールをインストールするには下記のコマンドです。

# dotnet tool install --global dotnet-counters
Tools directory '/root/.dotnet/tools' is not currently on the PATH environment variable.
If you are using bash, you can add it to your profile by running the following command:

cat <> ~/.bash_profile
# Add .NET Core SDK tools
export PATH="$PATH:/root/.dotnet/tools"
EOF

You can add it to the current session by running the following command:

export PATH="$PATH:/root/.dotnet/tools"

You can invoke the tool using the following command: dotnet-counters
Tool 'dotnet-counters' (version '3.0.52901') was successfully installed.

インストールしたら、指示の通りパスを通してあげましょう。

実行するとこんな感じになります。
コメント 2019-11-25 191137

診断ツールに関しては、Docsの下記のURLに一通り乗っています。
https://docs.microsoft.com/ja-jp/dotnet/core/diagnostics/

dotnet-counters 以外にも、dotnet-dump、dotnet-trace といったツールもあるようです。

カテゴリー:C#, Docker

dotnet core 3.0 でマイグレーションスクリプトを追加するときは、dotnet-efサブコマンドを別途インストールする

2019年10月31日 コメントを残す

dotnet core 3.0 を導入済みの端末で dotnet ef サブコマンドを実行すると、下記のようなエラーが表示されマイグレーションファイルが追加できない問題が発生しました。

指定されたコマンドまたはファイルが見つからなかったため、実行できませんでした。
次のような原因が考えられます:
* 組み込みの dotnet コマンドのスペルが間違っている。
* .NET Core プログラムを実行しようとしたが、dotnet-ef が存在しない。
* グローバル ツールを実行しようとしたが、プレフィックスとして dotnet が付いたこの名前の実行可能ファイルが PATH に見つからなかった。

コメント 2019-10-31 100157

下記のURLにある通り、dotnet core 3.0 からは dotnet-ef サブコマンドを別途インストールが必要になったようです。

dotnet tool install --global dotnet-ef

EF Core 3.0 に含まれる破壊的変更
EF Core のコマンドライン ツールである dotnet ef が .NET Core SDK の一部ではなくなった
https://docs.microsoft.com/ja-jp/ef/core/what-is-new/ef-core-3.0/breaking-changes#dotnet-ef

マイグレーションをdocker内で実行している場合もDockerfile内でインストールしないとこけるので注意ですね。

カテゴリー:ASP.NET, C#, DB

.net core 3.0 でデータプロバイダーにSQLiteを利用している場合、DateTimeOffset 列に対する OrderBy で例外が発生する

2019年10月24日 コメントを残す

アプリのデータベースにはMySQLを利用しているんですが、単体テスト時はSQLiteを使ってテストしています。
こんな感じのコードを実行した場合、.net core 2.2の時点ではMySQL(Pomelo.EntityFrameworkCore.MySql)だろうが、SQLiteだろうが特に問題なく実行できていたのですが、

await MyDbContext.Users
        .OrderByDescending(u =&gt; u.UpdateDate)
        .FirstOrDefaultAsync();

.net core 3.0にアップデートした後に単体テストを実行したらこんな例外が発生してテストが失敗してしまいました。

  メッセージ: 
    System.NotSupportedException : SQLite cannot order by expressions of type 'DateTimeOffset'. Convert the values to a supported type or use LINQ to Objects to order the results.

このあたりの制約に引っかかっているようです。
SQLite EF Core データベースプロバイダーの制限事項
https://docs.microsoft.com/ja-jp/ef/core/providers/sqlite/limitations#query-limitations

検索してみるとこのあたりで良い感じの解決策がありました。
https://blog.dangl.me/archive/handling-datetimeoffset-in-sqlite-with-entity-framework-core/

OnModelCreatingのタイミングで、データベースプロバイダーがSQLiteの場合に型変換を実施して回避するようです。

カテゴリー:プログラミング, C#, DB

C# 8で有効になったusingに対する複数の機能拡張

2019年10月11日 コメントを残す

小規模なバッチプログラムを書く機会があって、折角だし dotnet core 3.0 で作成してみるかと実装していったところ、ReSharper にこんな指摘をされた。
awaitusingvar-00

おや?と思いつつ ReSharper さんに従ってみる。
もともとはこんなコードで、マルチパートなリクエストを送る処理ですね。

using (var fileStream = File.OpenRead(localTemplatePath))
using (var multipartContent = BuildSaveTemplateRequest(remoteTemplateName, fileStream, contentType, comment))
    await CreateHttpClient().PostAsync($"/api/template/{remoteTemplateName}", multipartContent);

提案を受け入れると await using になりましたね。
非同期の using って何だろう?という感じですが、Docsのこの記事を見ると await がかかっているのは using というより var fileStream に対してなんですね。非同期ストリームは待ち望んでいた機能なのでワクワクですね。
チュートリアル: C#8.0 および .NET Core 3.0 を使用して非同期ストリームを生成および使用する
https://docs.microsoft.com/ja-jp/dotnet/csharp/tutorials/generate-consume-asynchronous-stream

await using (var fileStream = File.OpenRead(localTemplatePath))
using (var multipartContent = BuildSaveTemplateRequest(remoteTemplateName, fileStream, contentType, comment))
    await CreateHttpClient().PostAsync($"/api/template/{remoteTemplateName}", multipartContent);

あれ?まだ提案がある?
awaitusingvar-02

docs.microsoft では Using 宣言 となっている改善機能ですね。
外側の変数スコープに応じて Dispose を呼び出してくれるようになるので、ソースの見通しが良くなります。
https://docs.microsoft.com/ja-jp/dotnet/csharp/whats-new/csharp-8#using-declarations

await using var fileStream = File.OpenRead(localTemplatePath);
using var multipartContent = BuildSaveTemplateRequest(remoteTemplateName, fileStream, contentType, comment);
await CreateHttpClient().PostAsync($"/api/template/{remoteTemplateName}", multipartContent);

ただ、この提案があるのはusingの後に何もない場合のみで、usingの後にそのリソース以外を使ったものがある場合は提案されないようです。
awaitusingvar-03

C#も構文が増えてきて、ちょっと目を離すとおや?これコンパイル通るのか?みたいなコードになりますが、ReSharperさんに支えられて何とかなっています。

カテゴリー:C#, ReSharper