前回ローカルでDB接続できたので、Ubuntuにデプロイしてみます。
肝は環境の切り替えとDBマイグレーションです。
接続文字列はappsettings.{ENV}.jsonで管理
ASP.NET Coreでは接続文字列はappsettings.jsonに書くのが良いみたいです。
さらに環境設定はappsettings.{env.EnvironmentName}.jsonで手軽に切り替えられるようです。
まずはローカル開発環境で動くようにする
実行時の環境は環境変数ASPNETCORE_ENVIRONMENTを参照するみたいです。
VSではプロジェクトのプロパティのDebugセクションに定義してあります。
ということで、appsettings.Development.jsonを
1
2
3
4
5
6
7
8
9
10
11
12
13
|
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"ConnectionStrings": {
"BloggingDatabase": "Host=localhost;Database=aspnetdb_dev;Username=vagrant"
}
}
|
な感じに書き換えます。
DbContextをdependency injection
BloggingContext.csはからは直接appsettings.json内の値を参照できないので、DIするように設定します。
BloggingContext.csにコンストラクタを追加。
1
2
3
4
5
6
7
8
9
10
11
|
....
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options) : base(options) { } //追記
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {} //空に
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
....
|
Startup.csのConfigureServicesにAddDbContextを追記します。
1
2
3
4
5
6
7
8
9
10
11
|
using Microsoft.EntityFrameworkCore; //追記
using WebApplication3.Models; //追記
....
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BloggingContext>(options => options.UseNpgsql(Configuration.GetConnectionString("BloggingDatabase"))); //追記
// Add framework services.
services.AddMvc();
}
....
|
ControllerにInjectされるようコンストラクタを新設して、DIされたオブジェクトを使用するよう変更。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
....
public class HomeController : Controller
{
private Models.BloggingContext db;
public HomeController(Models.BloggingContext context)
{
this.db = context;
}
public IActionResult Index()
{
var blogs = db.Blogs.OrderBy(b => b.Url).ToList();
return View(blogs);
}
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
var blog = new Models.Blog { Url = "http://sample.com/"+DateTime.UtcNow.ToString("yyyyMMdd_hhmmssms") };
db.Blogs.Add(blog);
db.SaveChanges();
return View();
}
...
|
ひとまずデバッグ実行でちゃんと動くか確認。
Production用のappsettings作成
無事ローカルで動いたら、appsettings.Development.jsonをコピーしてappsettings.Production.jsonを作成。db名をaspnetdbに変更。
1
|
"BloggingDatabase": "Host=localhost;Database=aspnetdb;Username=vagrant"
|
Productionにdeploy
例によって
1
2
3
|
>dotnet restore
>dotnet build
>dotnet publish --configuration Release -r ubuntu.16.04-x64
|
scpなりftpなりでコピー。
Ubuntu環境をProduction扱いにする
環境変数をセットします。
1
|
vagrant@vagrant:~/src/publish$ export ASPNETCORE_ENVIRONMENT=Production
|
必要なら.bash_profileに書いとく。
実行とエラー対応
1
|
vagrant@vagrant:~/src/publish$ dotnet WebApplication3.dll
|
で実行。
postgersユーザーのパスワード
こんなエラーが出ました
1
|
No password has been provided but the backend requires one (in MD5)
|
空パスワードはダメらしいので設定します。
1
2
3
|
vagrant@vagrant:~/src/publish$ sudo -i -u postgres
postgres@vagrant:~$ psql
postgres=# alter user vagrant WITH PASSWORD 'test';
|
合わせてconnection stringを書き換え。
1
|
"BloggingDatabase": "Host=localhost;Database=aspnetdb;Username=vagrant;Password=test"
|
ubuntuでdb migration
続いてこのエラー
1
|
Npgsql.PostgresException: 42P01: relation "Blogs" does not exist
|
Udate-Databaseしてないからねー。
こちらを参考に
WebApplication3.csprojを編集
1
2
3
4
|
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.1" />
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" /><!--追記-->
</ItemGroup>
|
してpublish して dotnet efしても
1
|
No executable found matching command "dotnet-ef"
|
と怒られます。
いろいろ調べたんですが、まともな解決法は見つからず。
stackoverflow先生によると、
SQLを生成して実行か、dbContext.Database.Migrate()を実行だそうです。
今回はSQL実行します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
c:\usr\vstest\WebApplication3\WebApplication3>dotnet ef migrations script
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.65
CREATE TABLE "__EFMigrationsHistory" (
"MigrationId" varchar(150) NOT NULL,
"ProductVersion" varchar(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);
CREATE TABLE "Blogs" (
"BlogId" serial NOT NULL,
"Rating" int4 NOT NULL,
"Url" text,
CONSTRAINT "PK_Blogs" PRIMARY KEY ("BlogId")
);
CREATE TABLE "Posts" (
"PostId" serial NOT NULL,
"BlogId" int4 NOT NULL,
"Content" text,
"Title" text,
CONSTRAINT "PK_Posts" PRIMARY KEY ("PostId"),
CONSTRAINT "FK_Posts_Blogs_BlogId" FOREIGN KEY ("BlogId") REFERENCES "Blogs" ("BlogId") ON DELETE CASCADE
);
CREATE INDEX "IX_Posts_BlogId" ON "Posts" ("BlogId");
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20170615065858_InitialCreate', '1.1.2');
|
吐かれたSQLをpgAdminで実行。
動きます
無事エラーが解決ができたら、http://localhost:5050/にアクセスすると、ちゃんと動いている様子。
コンソールに吐かれるログは
1
2
3
4
5
6
7
8
9
|
dbug: Npgsql.NpgsqlConnection[3]
Opening connection to database 'aspnetdb' on server 'tcp://localhost:5432'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (16ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT "b"."BlogId", "b"."Rating", "b"."Url"
FROM "Blogs" AS "b"
ORDER BY "b"."Url"
dbug: Npgsql.NpgsqlConnection[4]
Closing connection to database 'aspnetdb' on server 'tcp://localhost:5432'.
|
こんな感じで、EFも動いているようです。
次回はDBマイグレーション関係を試してみます。