うさ☆うさ日記 このページをアンテナに追加 RSSフィード

2006 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 05 | 06 |
2013 | 05 | 08 | 09 | 10 | 11 | 12 |
2014 | 08 |
2015 | 04 | 06 | 08 | 09 | 11 | 12 |
2016 | 01 | 02 | 04 | 05 | 09 | 11 | 12 |
2017 | 04 | 05 | 06 |

2017-06-09

[]ASP.NET Coreで設定ファイルによるDIの設定を行い環境によって使用されるコンポーネントを変更する(楽屋裏)

記事はこちら

え〜

これらは用途に応じて組み合わせて使い分けるべきもので、どれかがあれば他はいらないとかそういう種のものですたい(´・ω・`)


「○○という手法はもう古い」「時代は□□(という手法)」みたいな煽り系エンジニアも多かったりしますが、単に特定のユースケースしか考えていないだけだったりすることもあったりで。

人様のおうんこな言説に惑わされることなく、自分の要件にあった手法を自分で選択できる技術者でありたいものです(`・ω・´)

2017-05-08

[]NuGetで参照するだけで自動生成機能が組み込まれるライブラリのNuGetパッケージを作成する

記事はこちら

Xamarin関連で調べた内容のまとめです。

ちゅーか、実は既に結構使われている技だったりするもの(・ω・;)?

なお、ポイントは「NuGetで参照するだけ」で「csprojを手編集で弄ったりすることが不要」っという点です。

2017-04-22

[]Xamarin.Formsを使うライブラリを.NET Standardで作る時のメモ

毎回忘れて調べるので備忘録(・ω・;)

「クラスライブラリ(.NET Standard)」でプロジェクトを作成した後、csprojを開いて下記のように<PackageTargetFallback>を追加。

  <PropertyGroup>
    <TargetFramework>netstandard1.1</TargetFramework>
    <PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback>
  </PropertyGroup>

これでXamarin.FormsをNuGetから参照可能に。

2016-12-09

[]TestHostを用いたASP.NET Coreアプリケーションのテスト

Microsoft.AspNetCore.TestHostを使用して、ASP.NET Core Webアプリケーションをオンメモリにホストした状態でのテストを行います。

TestHostを用いることで、HTTPリクエストをエミュレートしたエンドツーエンドの試験が可能になります。

要は、Javaで埋め込みコンテナを使ってテストする〜、みたいな奴のASP.NET Core版です。

環境

  • Visual Strudio 2015
  • .NET Core Tooling Preview 2 for Visual Studio 2015

前提

テスト対象となるASP.NET Core Webアプリケーションのプロジェクトが作成され、.NET Core 1.1へアップデート済みの状態とします。

また、今回はわかりやすいようにAPIコントローラーの呼び出しをテスト対象とするため、APIコントローラーを追加済みの状態とします。

サンプル

以下に完成形のサンプルを用意しています。

手順

テストプロジェクトの構築手順について記述します。

ASP.NET Coreアプリケーションのソリューションにテストプロジェクトとして「Class Library (.NET Core)」のプロジェクトを追加します。

作成されたプロジェクトはターゲットフレームワークが.NET Standardになっているため、そのままではASP.NET Coreアプリケーションのプロジェクトを参照できないのでproject.jsonの内容を変更します。

ターゲットフレームワークの変更と、必要なライブラリの参照を追加したproject.jsonは以下の様になります。

{
  "version": "1.0.0-*",

  "testRunner": "xunit",

  "dependencies": {
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.1.0"
    },
    "dotnet-test-xunit": "2.2.0-preview2-build1029",
    "xunit": "2.2.0-beta4-build3444",
    "Microsoft.AspNetCore.TestHost": "1.1.0",
    "Microsoft.DotNet.InternalAbstractions": "1.0.0",
    "TestHostExample": "1.0.0-*"
  },

  "frameworks": {
    "netcoreapp1.1": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  }
}

行っている作業は以下になります。

  • .NETStandard 1.6の設定から.NETCoreApp 1.1用にdependenciesとframeworksを変更
  • testRunnerセクション追加
  • dotnet-test-xunit、xunitへの参照追加
  • Microsoft.AspNetCore.TestHostへの追加
  • Microsoft.DotNet.InternalAbstractionsへの追加
  • Webアプリケーションプロジェクト(TestHostExample)への参照の追加

なお、Microsoft.DotNet.InternalAbstractionsについては、1.0環境では問題ありませんが、Microsoft.AspNetCore.Mvcを1.1.0にあげると問題が発生する(Visual Studioのテストエクスプローラーにテストが表示されない、dotnet testコマンドによるテストでは例外が発生する)ため追加しています。

テストコード

テストコードは以下の内容となります。

using System.Net.Http;

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;

using Xunit;

public class ValuesControllerTest
{
    [Fact]
    public async void GetReturnValueArray()
    {
        var config = new ConfigurationBuilder().Build();

        var host = new WebHostBuilder()
            .UseConfiguration(config)
            .UseStartup<Startup>();

        var server = new TestServer(host);

        using (var client = server.CreateClient())
        {
            var request = new HttpRequestMessage(HttpMethod.Get, "/api/values/");
            var response = await client.SendAsync(request);

            var content = await response.Content.ReadAsStringAsync();

            Assert.Equal(content, "[\"value1\",\"value2\"]");
        }
    }
}

テスト対象プロジェクトのStartupをホストしてTestServerのインスタンスを作成し、そこからクライアントの作成を行って、HTTPリクエスト/レスポンスのエミュレーションによるテスト内容になります。

テスト用のカスタマイズを行う場合、TestServerのインスタンス作成前にconfigやWebHostBuilderをいじったりします。

あとは、Visual Srudioのテストメニューやdotnet testコマンドによりテストを実行するだけです。


ホスティングまで疑似ってテストすると重いと思うかもしれませんが、テストの実行時間は1個目こそ500msくらいかかりますが、それ以降は10msくらいで終わるので気にしなくていいと思います。


ところで、Startup内でServiceProviderに登録しているコンポーネントについて、テスト用のモックへの置き換えはどこでやるのがええんやろね(・ω・)?

Startupのコンポーネント登録箇所をvirtualにしてそこで、とか?

2016-12-08

[]ASP.NET Core用カスタムResolver拡張作った

この内容だとコントローラー以降のDIにしか対応していないので、[FromServices]や@injectでのDIにも対応できるように完全版を作った(・ω・)

作るにあたって調査した内容は以下にまとめた。

ソース

使い方

ASP.NET Coreプロジェクトを作って、1.1化して、NuGetでUsa.Smart.Resolver.AspNetCoreをインスコ

Startupのソースでusing Smart.Resolverして、ConfigureServices()を以下の様に変更すればOK。

public class Startup
{
    private readonly StandardResolver resolver = new StandardResolver();

...
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc();

        return SmartResolverHelper.BuildServiceProvider(resolver, services);
    }
...
}

概念

  • [FromServices]や@injectで使用されるコンポーネントASP.NET Coreのコンポーネント含め、全てのコンポーネントはIServiceProviderで管理される
  • ConfigureServices()で独自のIServiceProviderを返すと、標準のIServiceProviderに変わってそれが使用される
  • よって、カスタムResolverと連携するIServiceProviderを作ることで、任意のコンポーネントの管理を独自Resolverに任せることができる

特徴

そもそもなんでカスタムResolverを使いたいかと言えば、標準のIServiceProviderでは対応していないコンディショナルバインディングとかをしたいから(´・ω・`)

そういうのが不要ならば、標準のIServiceProviderを使っていればOK(・∀・)b

2016-11-24

[][]CentOS 7.2上にASP.NET Core Webアプリデプロイしてサービス化する

昨日の続きとして、.NET Core 1.1をインストールしたCentOS上に、Visual Studioで作ったASP.NET Core Webアプリデプロイして、ついでにサービス化する方法について(・ω・)

手順

nginxとの連携とかはせず、ASP.NET Core Webアプリを動かす最低限の作業について記述。

また、アプリビルドCentOS上で行うのではなく、Visual Studio上でビルドしたものをCentOSデプロイするパターンについて記述。

プロジェクト作成

Visual Studioで「ASP.NET Core Web Application (.NET Core)」を作成。

1.1へ更新

Visual Studioで作成されるひな形は1.0用の構成。

CentOSには1.1が入っているので1.1用に更新。

まずはNuGetですべてのパッケージを更新。


次に、project.jsonの次の箇所を更新。

  • 変更前
  "frameworks": {
    "netcoreapp1.0": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  },
  • 変更後
  "frameworks": {
    "netcoreapp1.1": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  },

また、次の箇所も変更。

  • 変更前
    "Microsoft.NETCore.App": "1.1.0",
  • 変更後
    "Microsoft.NETCore.App": {
      "version": "1.1.0",
      "type": "platform"
    },

project.json全体は以下のような内容。

{
  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.1.0",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Diagnostics": "1.1.0",
    "Microsoft.AspNetCore.Mvc": "1.1.0",
    "Microsoft.AspNetCore.Razor.Tools": {
      "version": "1.0.0-preview2-final",
      "type": "build"
    },
    "Microsoft.AspNetCore.Routing": "1.1.0",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
    "Microsoft.AspNetCore.StaticFiles": "1.1.0",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
    "Microsoft.Extensions.Configuration.Json": "1.1.0",
    "Microsoft.Extensions.Logging": "1.1.0",
    "Microsoft.Extensions.Logging.Console": "1.1.0",
    "Microsoft.Extensions.Logging.Debug": "1.1.0",
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0",
    "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.1.0",
  },

  "tools": {
    "BundlerMinifier.Core": "2.2.306",
    "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
  },

  "frameworks": {
    "netcoreapp1.1": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  },

  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  },

  "runtimeOptions": {
    "configProperties": {
      "System.GC.Server": true
    }
  },

  "publishOptions": {
    "include": [
      "wwwroot",
      "**/*.cshtml",
      "appsettings.json",
      "web.config"
    ]
  },

  "scripts": {
    "prepublish": [ "bower install", "dotnet bundle" ],
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  }
}
URL設定

デフォルトではlocalhostからのアクセスのみ許可されるので、外部からも接続できるようにUseUrls()の記述を追加。

public static void Main(string[] args)
{
    var host = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseUrls("http://*:80/")
        .UseStartup<Startup>()
        .Build();

    host.Run();
}

なお、この時点でVisual Studio上でもデバッグ動作できることを確認しておく。

できなければ何かが不足している状態。

デプロイ

今回はLinux上でビルドするのではなく、開発環境上でビルドしたものを配布する。


Visual Studioの[ビルド]メニューからアプリケーションの発行を実施。

発行方法は「ファイルシステム」で、ターゲットの場所はデフォルトだと「.\bin\Release\PublishOutput」。

上記フォルダの内容がCentOS上へコピーするファイル。


なお、発行と同じことをコマンドラインからMSBuildで行う場合、以下のコマンドで指定したディレクトリにファイルを作成可能。

MSBuild src\Xxx\Xxx.xproj /p:Configuration=Release /t:PackagePublish /p:PublishOutputPathNoTrailingSlash=bin\Release\PublishOutput
Firewall設定

CentOSに対して外部から接続可能にするためFirewallを設定。

[root@centos ~]# firewall-cmd --zone=public --add-port=http --permanent
success
[root@centos ~]# firewall-cmd --reload
success
[root@centos ~]#
動作確認

CentOS上のコピー先は「/opt/webapp」として、そこに移動してdotnetコマンドを実行。

[root@centos ~]# cd /opt/webapp
[root@centos webapp]# dotnet WebApplication.dll
Hosting environment: Production
Content root path: /opt/webapp
Now listening on: http://*:80
Application started. Press Ctrl+C to shut down.

この状態で、外部からWebブラウザで動作を確認する。

問題がなければ画面が表示され、コンソールにもログが表示される。

サービス化

ついでに上記アプリケーションのサービス化。


まず、起動用のスクリプトとして以下のような/opt/webapp.shを作成。

#!/bin/bash

cd /opt/webapp
dotnet WebApplication.dll

実行権限の設定。

[root@centos ~]# chmod 755 /opt/webapp.sh

次に、サービスの起動スクリプトとして以下のような/etc/systemd/system/webapp.serviceを作成。

[Unit]
Description = webapp daemon

[Service]
ExecStart = /opt/webapp.sh
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target

以下のコマンドで正しく作成されていることを確認。

[root@centos ~]# systemctl list-unit-files --type=service | grep webapp
webapp.service                              enabled

サービスの開始。

[root@centos ~]# systemctl start webapp

これで、OS再起動してもWebアプリケーションが起動。

なお、これはあくまで最低限の設定なので、実際にプロダクションに導入する際には、もう少しスクリプトの内容を検討すること。


…っということで、これで実行環境がLinuxだからという理由でJavaでWebアプリを作っていたような人達も、.NET Coreで同程度のことはできるようになったわけで、これまで.NETのウィークポイントであった実行環境面が克服されたのでした٩(๑´3`๑)۶

みんな、これからはWebアプリASP.NET Coreで作るのじゃ(`・ω・´)

2016-11-23

[][]CentOS 7.2上に.NET Core 1.1をインストールする

昨日に続き、Dockerではなく、CentOSに直接インストールする方法について(・ω・)

動作環境などは昨日に引き続きで。

手順

.NET Core installation guideに従ってやるだけ。

CentOS以外は、ディストリビューション毎の記述を参照のこと。

必要ライブラリインストール
[root@centos ~]# yum install -y libunwind libicu
読み込んだプラグイン:fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.riken.jp
 * extras: ftp.riken.jp
 * updates: ftp.riken.jp
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ libicu.x86_64 0:50.1.2-15.el7 を インストール
---> パッケージ libunwind.x86_64 2:1.1-5.el7_2.2 を インストール
--> 依存性解決を終了しました。

依存性を解決しました

======================================================================================================================================================================================================
 Package                                        アーキテクチャー                            バージョン                                             リポジトリー                                  容量
======================================================================================================================================================================================================
インストール中:
 libicu                                         x86_64                                      50.1.2-15.el7                                          base                                         6.9 M
 libunwind                                      x86_64                                      2:1.1-5.el7_2.2                                        updates                                       56 k

トランザクションの要約
======================================================================================================================================================================================================
インストール  2 パッケージ

総ダウンロード容量: 6.9 M
インストール容量: 24 M
Downloading packages:
(1/2): libunwind-1.1-5.el7_2.2.x86_64.rpm                                                                                                                                      |  56 kB  00:00:00
(2/2): libicu-50.1.2-15.el7.x86_64.rpm                                                                                                                                         | 6.9 MB  00:00:03
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
合計                                                                                                                                                                  1.9 MB/s | 6.9 MB  00:00:03
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  インストール中          : 2:libunwind-1.1-5.el7_2.2.x86_64                                                                                                                                      1/2
  インストール中          : libicu-50.1.2-15.el7.x86_64                                                                                                                                           2/2
  検証中                  : libicu-50.1.2-15.el7.x86_64                                                                                                                                           1/2
  検証中                  : 2:libunwind-1.1-5.el7_2.2.x86_64                                                                                                                                      2/2

インストール:
  libicu.x86_64 0:50.1.2-15.el7                                                                    libunwind.x86_64 2:1.1-5.el7_2.2

完了しました!
ダウンロード及び展開
[root@centos ~]# curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=835019
[root@centos ~]# mkdir -p /opt/dotnet && sudo tar zxf dotnet.tar.gz -C /opt/dotnet
[root@centos ~]# ln -s /opt/dotnet/dotnet /usr/local/bin
動作確認
[root@centos ~]# dotnet

Microsoft .NET Core Shared Framework Host

  Version  : 1.1.0
  Build    : 928f77c4bc3f49d892459992fb6e1d5542cb5e86

Usage: dotnet [common-options] [[options] path-to-application]

Common Options:
  --help                           Display .NET Core Shared Framework Host help.
  --version                        Display .NET Core Shared Framework Host version.

Options:
  --fx-version <version>           Version of the installed Shared Framework to use to run the application.
  --additionalprobingpath <path>   Path containing probing policy and assemblies to probe for.

Path to Application:
  The path to a .NET Core managed application, dll or exe file to execute.

If you are debugging the Shared Framework Host, set 'COREHOST_TRACE' to '1' in your environment.

To get started on developing applications for .NET Core, install the SDK from:
  http://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409
[root@centos ~]# dotnet --info
.NET Command Line Tools (1.0.0-preview2-1-003177)

Product Information:
 Version:            1.0.0-preview2-1-003177
 Commit SHA-1 hash:  a2df9c2576

Runtime Environment:
 OS Name:     centos
 OS Version:  7
 OS Platform: Linux
 RID:         centos.7-x64

っで、次回はVisual Studio 2015で作ったASP.NET Core Webアプリケーションをこの環境で動かす話について٩(๑>◡<๑)۶

2016-11-22

[][]CentOS 7.2上にSQL Server on Linuxインストールする

Dockerではなく、CentOSに直接インストールする方法について(・ω・)

動作環境

OSインストール後、yum updateしたところまでの状態からはじめる。

手順

Install SQL Server on Red Hat Enterprise Linuxに従ってやるだけ。

RHELインストール手順だが、CentOSも同じでOK。

repository configuration取得
[root@centos ~]# curl https://packages.microsoft.com/config/rhel/7/mssql-server.repo > /etc/yum.repos.d/mssql-server.repo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   220  100   220    0     0    101      0  0:00:02  0:00:02 --:--:--   101
インストール
[root@centos ~]# yum install -y mssql-server
読み込んだプラグイン:fastestmirror
packages-microsoft-com-mssql-server                                                                                                                                                    | 2.9 kB  00:00:00
packages-microsoft-com-mssql-server/primary_db                                                                                                                                         | 2.4 kB  00:00:00
Loading mirror speeds from cached hostfile
 * base: ftp.tsukuba.wide.ad.jp
 * extras: ftp.tsukuba.wide.ad.jp
 * updates: ftp.tsukuba.wide.ad.jp
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ mssql-server.x86_64 0:14.0.1.246-6 を インストール
--> 依存性の処理をしています: bzip2 のパッケージ: mssql-server-14.0.1.246-6.x86_64
--> 依存性の処理をしています: gdb のパッケージ: mssql-server-14.0.1.246-6.x86_64
--> トランザクションの確認を実行しています。
---> パッケージ bzip2.x86_64 0:1.0.6-13.el7 を インストール
---> パッケージ gdb.x86_64 0:7.6.1-80.el7 を インストール
--> 依存性解決を終了しました。

依存性を解決しました

==============================================================================================================================================================================================================
 Package                                      アーキテクチャー                       バージョン                                     リポジトリー                                                         容量
==============================================================================================================================================================================================================
インストール中:
 mssql-server                                 x86_64                                 14.0.1.246-6                                   packages-microsoft-com-mssql-server                                 138 M
依存性関連でのインストールをします:
 bzip2                                        x86_64                                 1.0.6-13.el7                                   base                                                                 52 k
 gdb                                          x86_64                                 7.6.1-80.el7                                   base                                                                2.4 M

トランザクションの要約
==============================================================================================================================================================================================================
インストール  1 パッケージ (+2 個の依存関係のパッケージ)

総ダウンロード容量: 140 M
インストール容量: 145 M
Downloading packages:
(1/3): bzip2-1.0.6-13.el7.x86_64.rpm                                                                                                                                                   |  52 kB  00:00:00
(2/3): gdb-7.6.1-80.el7.x86_64.rpm                                                                                                                                                     | 2.4 MB  00:00:03
warning: /var/cache/yum/x86_64/7/packages-microsoft-com-mssql-server/packages/mssql-server-14.0.1.246-6.x86_64.rpm: Header V4 RSA/SHA256 Signature, key ID be1229cf: NOKEY=-] 2.7 MB/s | 140 MB  00:00:00 ETA
mssql-server-14.0.1.246-6.x86_64.rpm の公開鍵がインストールされていません
(3/3): mssql-server-14.0.1.246-6.x86_64.rpm                                                                                                                                            | 138 MB  00:01:07
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
合計                                                                                                                                                                          2.1 MB/s | 140 MB  00:01:07
https://packages.microsoft.com/keys/microsoft.asc から鍵を取得中です。
Importing GPG key 0xBE1229CF:
 Userid     : "Microsoft (Release signing) <gpgsecurity@microsoft.com>"
 Fingerprint: bc52 8686 b50d 79e3 39d3 721c eb3e 94ad be12 29cf
 From       : https://packages.microsoft.com/keys/microsoft.asc
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  インストール中          : bzip2-1.0.6-13.el7.x86_64                                                                                                                                                     1/3
  インストール中          : gdb-7.6.1-80.el7.x86_64                                                                                                                                                       2/3
  インストール中          : mssql-server-14.0.1.246-6.x86_64                                                                                                                                              3/3

+-------------------------------------------------------------------+
| Please run /opt/mssql/bin/sqlservr-setup to complete the setup of |
|                  Microsoft(R) SQL Server(R).                      |
+-------------------------------------------------------------------+

  検証中                  : mssql-server-14.0.1.246-6.x86_64                                                                                                                                              1/3
  検証中                  : gdb-7.6.1-80.el7.x86_64                                                                                                                                                       2/3
  検証中                  : bzip2-1.0.6-13.el7.x86_64                                                                                                                                                     3/3

インストール:
  mssql-server.x86_64 0:14.0.1.246-6

依存性関連をインストールしました:
  bzip2.x86_64 0:1.0.6-13.el7                                                                            gdb.x86_64 0:7.6.1-80.el7

完了しました!
セットアップ

パスワードはポリシーが有効になっているので、ある程度複雑なものが必要。

後でSSMS上から変更可能。

[root@centos ~]# /opt/mssql/bin/sqlservr-setup
Microsoft(R) SQL Server(R) Setup

You can abort setup at anytime by pressing Ctrl-C. Start this program
with the --help option for information about running it in unattended
mode.

The license terms for this product can be downloaded from
http://go.microsoft.com/fwlink/?LinkId=746388 and found
in /usr/share/doc/mssql-server/LICENSE.TXT.

Do you accept the license terms? If so, please type "YES": YES

Please enter a password for the system administrator (SA) account:
Please confirm the password for the system administrator (SA) account:

Setting system administrator (SA) account password...

Do you wish to start the SQL Server service now? [y/n]: y
Do you wish to enable SQL Server to start on boot? [y/n]: y
Created symlink from /etc/systemd/system/multi-user.target.wants/mssql-server.service to /usr/lib/systemd/system/mssql-server.service.
Created symlink from /etc/systemd/system/multi-user.target.wants/mssql-server-telemetry.service to /usr/lib/systemd/system/mssql-server-telemetry.service.

Setup completed successfully.
状態確認
[root@centos ~]# systemctl status mssql-server
● mssql-server.service - Microsoft(R) SQL Server(R) Database Engine
   Loaded: loaded (/usr/lib/systemd/system/mssql-server.service; enabled; vendor preset: disabled)
   Active: active (running) since 火 2016-11-22 21:01:21 JST; 12s ago
 Main PID: 2810 (sqlservr)
   CGroup: /system.slice/mssql-server.service
           tq2810 /opt/mssql/bin/sqlservr
           mq2823 /opt/mssql/bin/sqlservr

1122 21:01:26 centos sqlservr[2810]: 2016-11-22 12:01:26.37 spid17s     Server is listening on [ 0.0.0.0 <ipv4> 1433].
1122 21:01:26 centos sqlservr[2810]: 2016-11-22 12:01:26.38 Server      Server is listening on [ 127.0.0.1 <ipv4> 1434].
1122 21:01:26 centos sqlservr[2810]: 2016-11-22 12:01:26.38 Server      Dedicated admin connection support was established for listening locally on port 1434.
1122 21:01:26 centos sqlservr[2810]: 2016-11-22 12:01:26.38 spid17s     SQL Server is now ready for client connections. This is an informational message; no user action is required.
1122 21:01:26 centos sqlservr[2810]: 2016-11-22 12:01:26.57 spid7s      Starting up database 'tempdb'.
1122 21:01:26 centos sqlservr[2810]: 2016-11-22 12:01:26.98 spid7s      The tempdb database has 1 data file(s).
1122 21:01:26 centos sqlservr[2810]: 2016-11-22 12:01:26.99 spid20s     The Service Broker endpoint is in disabled or stopped state.
1122 21:01:27 centos sqlservr[2810]: 2016-11-22 12:01:26.99 spid20s     The Database Mirroring endpoint is in disabled or stopped state.
1122 21:01:27 centos sqlservr[2810]: 2016-11-22 12:01:27.02 spid20s     Service Broker manager has started.
1122 21:01:27 centos sqlservr[2810]: 2016-11-22 12:01:27.09 spid5s      Recovery is complete. This is an informational message only. No user action is required.
Firewall設定
[root@centos ~]# firewall-cmd --zone=public --add-port=1433/tcp --permanent
firewall-cmd --reloadsuccess
[root@centos ~]# firewall-cmd --reload
success
接続

SQL Server Management Studio (SSMS) のダウンロードからダウンロードしたSSMSで接続可能。

16.5では未サポートの動作あり。

データベース作成

デフォルトでは[照合順序]が「SQL_Latin1_General_CP1_CI_AS」になるので変更して作成する。*1

また、ユーザの[規定の言語]も「Arabic」になっているので変更しておく。


次回はCentOS上に.NET Core 1.1をインスコする話について(๑˃̵ᴗ˂̵)و

*1:Japanese_XJIS_140_*とかで

2016-11-14

[]ASP.NET CoreアプリDependency Injection処理を別のDIコンテナに委譲する(オマケ) Request Scopeへの対応

最初に追記。

こっちのやりかたなら以下の内容は不要です。



昨日の日記の続きとして、ついでにRequest Scopeでのオブジェクト管理機能を追加してみます(・ω・)


通常、各種DIコンテナのスコープ管理については、その実装固有の部分があるため、詳細な対応方法は異なります。

ここでは、ASP.NET Coreとの統合をするにあたり、どのような初期化処理や終了処理が必要かについてサンプルでその概要を示し、他のDIコンテナでも応用できるようにします。

サンプル

昨日のサンプルにRequest Scopeの対応を追加してあります。

今回は上記からソースを抜粋して概要を記述することで対応方法について示します。

概要

Smart.Resolverについて

Request Scopeの実装ではコンテナ固有の知識が必要になるため、まずSmart.Resolverのスコープ管理の概要について記述しておきます。

Smart.Resolverは、標準ではPrototypeSingleton Scopeにのみ対応したDependency Resolverです。

ただし、機能の拡張が可能となっており、以下の実装を用意することで独自のスコープ管理機能を追加することが可能になっています。

インターフェース 概要
IScope IScopeStorageのファクトリー、Bind()時に指定する
IScopeStorage Remember()/TryGet()/Clear()を実装する、スコープ内のオブジェクトプール機能

独自のスコープ管理を行いたい場合には、IScopeStorageの実装とそのファクトリーであるIScopeの実装を用意します。

Resolverに対してインスタンス要求が行われた場合、スコープ管理されているバインディングについては、まずIScopeStorage.TryGet()でスコープのオブジェクトプールからインスタンスの検索を行います。

また、オブジェクトプールにインスタンスがない場合はインスタンスを生成し、IScopeStorage.Remember()によりオブジェクトプールにインスタンスを追加するというのがSmart.Resolverのスコープ管理の概要です。


なお、Singleton Scopeでのスコープ管理も、Dictionaryを使用したIScopeStorageにより実装されています。


今回は、HttpContext.Itemsでオブジェクトを管理するRequestScopeStorageを用意することで、Request Scopeでのオブジェクト管理機能を追加しています。

ライフサイクル管理

Request Scopeでのライフサイクル管理の要件を要約すると、HTTPリクエストが終わったタイミングでオブジェクトプール内のインスタンス破棄を行う、ということになります。

これをASP.NET Coreのコードイメージで言えば、以下のような処理を書けば良いと言うことになります。

app.Use(async (context, next) =>
{
    using (new RequestScopeObjectPool())
    {
        await next();
    }
});

サンプルでは以下のような拡張メソッドを用意して、next()の後でRequest Scopeで管理されるオブジェクトの破棄を行うようにしています。

public static void UseSmartResolverRequestScope(this IApplicationBuilder app, StandardResolver resolver)
{
    var storage = new RequestScopeStorage(app.ApplicationServices.GetRequiredService<IHttpContextAccessor>());

    // RequestScopeStorageでのオブジェクト管理機能をStandardResolverに追加
    resolver.Configure(container => container.Register(storage));

    app.Use(async (context, next) =>
    {
        try
        {
            await next();
        }
        finally
        {
            // Request Scopeで管理されるオブジェクトの破棄
            storage.Clear();
        }
    });
}

利用方法としては、以下のようにStartupにおいてこの拡張メソッドを以下のように使用することで、MVCの処理が終わった後にオブジェクトの破棄処理ができるようになります。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
    // UseMvcの前に記述
    app.UseSmartResolverRequestScope(resolver);

    // Enable request scope
    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

なお、注意事項として、UseSmartResolverRequestScope()はUseMvc()の前に記述する必要があります。

HttpContextでのオブジェクト管理

Request Scopeオブジェクト自体はHttpContext.Itemsに入れてライフサイクル管理を行いますが、ASP.NET CoreではHttpContextへのアクセスにIHttpContextAccessorを使用します。

IHttpContextAccessorは標準ではサービスに追加されていないので、Startupで以下のようにIHttpContextAccessorの追加をしておく必要があります。

public void ConfigureServices(IServiceCollection services)
{
...
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
...
}

これにより、拡張メソッドUseSmartResolverRequestScope()内において、IApplicationBuilder.ApplicationServices.GetRequiredService<IHttpContextAccessor>()でIHttpContextAccessorの取得が可能となります。

RequestScopeStorage内ではIHttpContextAccessor.HttpContextにより現在のHttpContextを取得し、そこでオブジェクトプールを管理しています。

この詳細についてはRequestScopeStorageのソースを参照してください。

バインディング

Request Scopeで管理されるオブジェクトバインディングは以下のように記述します。

resolver
    .Bind<RequestScopedObject>()
    .ToSelf()
    .InRequestScope();

上記のバインディングを記述することにより、RequestScopedObjectのインスタンスはHttpContext内で管理されるようになり、HTTPの処理毎にインスタンスの生成と破棄が行われるようになります。

なお、InRequestScope()は統合用に用意した拡張メソッドで、その実態は以下のようになっています。

public static IBindingNamedWithSyntax InRequestScope(this IBindingInSyntax syntax)
{
    return syntax.InScope(new RequestScope());
}

以上が、Request Scopeへの対応の概要となります。


まあ、自分はRequest Scopeが必要になるような設計をすることは無いと思うんですけどね(´д`;)

2016-11-13

[]ASP.NET CoreアプリDependency Injection処理を別のDIコンテナに委譲する

ASP.NET CoreではDependency Injectionが標準機能として組み込まれていますが、それでは機能不足な事も多いと思います(´・ω・`)

そこで、他のDIコンテナASP.NET Coreを連携させる方法について記述します。


通常、各種DIコンテナについては、その拡張としてASP.NET Coreとのインテグレーション機能が提供されると思いますが、今回は自作のDependency Resolverを使用して、連携方法の仕組み自体について記述します。

この方法と同じやり方をすることで、インテグレーション機能が提供されていないコンテナについても、ASP.NET Coreとの連携が可能となります。

環境

手順

IControllerActivator実装

IControllerActivatorの派生クラスとして、以下のような実装を用意します。

なお、IResolverはSmart.ResolverのDependency Resolverインターフェースになります。

using System;

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;

using Smart.Resolver;

public class SmartResolverControllerActivator : IControllerActivator
{
    private readonly IResolver resolver;

    public SmartResolverControllerActivator(IResolver resolver)
    {
        this.resolver = resolver;
    }

    public object Create(ControllerContext context)
    {
        return resolver.Get(context.ActionDescriptor.ControllerTypeInfo.AsType());
    }

    public void Release(ControllerContext context, object controller)
    {
        (controller as IDisposable)?.Dispose();
    }
}
Startup修正

StartupクラスでStandardResolverをメンバに定義し、ConfigureServices()でSmartResolverControllerActivatorの設定を行います。

using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Extensions.DependencyInjection;

using Smart.Resolver;

public class Startup
{
    private readonly StandardResolver resolver = new StandardResolver();
...
    public void ConfigureServices(IServiceCollection services)
    {
        // 標準のASP.NET設定はここ

        services.AddSingleton<IControllerActivator>(new SmartResolverControllerActivator(resolver));
    }
...
}

IControllerActivatorが設定されると、コントローラーのインスタンスはその実装経由で行われるようになります。

この例では、実際のインスタンスの生成をSmart.ResolverのDependency Resolver実装であるStandardResolverに委譲することで、ASP.NET CoreとSmart.Resolverの連携を実現しています。

サンプル

実際に動くサンプルを以下に用意しました。

このサンプルは、用途毎に複数のDB接続があるようなアプリケーションを想定したものです。

接続を生成する複数のIConnectionFactoryのインスタンスについて、ASP.NET Coreの標準ではサポートされない条件付きバインディングを行っています。

なお、SQLiteとDapperを使用し、実際にデータアクセスまで行っています。

インスタンス生成委譲対象

サンプルで、StandardResolverにインスタンスの生成/管理を委譲する主なクラスについて以下に記述します。

クラス スコープ 概要
CharacterController Prototype CharacterServiceを使用するAPIコントローラー
ItemController Prototype ItemServiceを使用するAPIコントローラー
CharacterService Singleton 名称"Character"のCallbackConnectionFactoryを使用する
ItemService Singleton 名称"Master"のCallbackConnectionFactoryを使用する
IConnectionFactory Singleton * 2 "Character"、"Master"の2つのインスタンスが存在する
Resolver初期化コード

Resolverの初期化コードを以下に抜粋します。

var connectionStringMaster = Configuration.GetConnectionString("Master");
resolver
    .Bind<IConnectionFactory>()
    .ToConstant(new CallbackConnectionFactory(() => new SqliteConnection(connectionStringMaster)))
    .Named("Master");
var connectionStringCharacter = Configuration.GetConnectionString("Character");
resolver
    .Bind<IConnectionFactory>()
    .ToConstant(new CallbackConnectionFactory(() => new SqliteConnection(connectionStringCharacter)))
    .Named("Character");

resolver
    .Bind<MasterService>()
    .ToSelf()
    .InSingletonScope()
    .WithConstructorArgument("connectionFactory", kernel => kernel.Get<IConnectionFactory>("Master"));
resolver
    .Bind<CharacterService>()
    .ToSelf()
    .InSingletonScope()
    .WithConstructorArgument("connectionFactory", kernel => kernel.Get<IConnectionFactory>("Character"));

CallbackConnectionFactoryについては、接続情報の異なる2つのインスタンスを、Named()メソッドにより異なる名称で登録しています。

2つのServiceクラスについては、Singletonスコープとして登録し、インスタンス生成時のコンストラクタ引数connectionFactoryについて、名称指定でResolverから取得して設定するようにしています。

なお、Named()及びWithConstructorArgument()によって条件付きバインディングを行っていますが、名称による条件付きバインディングはNamedAttributeを使う事でも可能です。


また、Smart.Resolverでは明示的に情報を登録しないクラスについてはPrototypeスコープとして扱われるため、コントローラーについてはResolverへの情報登録は不要となっています。


ちなみに、IControllerActivatorの他に、IViewComponentActivatorとかもありますでよ(・ω・)