VisualStudioCodeでc#+MS-SQLのWebApplicationを開発する環境を作ったときのメモ-1(自分用)

Webアプリケーション(MVC)を.NET Coreで開発するために環境を構築したときのメモ(2020/5時点)。

経緯

まかない用で古い.NET Framework+初期のMVCで作ったWebアプリケーションを使っていたが、そのアプリが居候していた古いサーバーを撤去することになり、別のサーバーに引っ越す必要が生じた。が、引っ越し先のサーバーに古い.NetFrameworkを入れるわけにもいかないので、.NET Core3.1で作り直すことにした。開発現場ではないのでVSはExpress版しかなかったが、.NET CoreはExpress版では開発できないので、VisualStudio Codeを使うことにした。VisualStudio Codeを本格的に使うのは初めてなので、いろいろ躓いた(これからも躓く)が、せっかくなので記録に残すことにした。(あくまで個人的なメモであり無保証です)

用意したもの(開発環境)

  • VisualStudio Code
  • DotNetCore3.1
  • SQLExpress2019
  • SSMS 18.5
  • IIS Express(有効化する)

(開発用の端末はWIndows10。SQLExpress2019とSSMSは、他のWindows10端末にすでに入っているものに接続して使うことにした。)

VisualStudioCodeの設定

追加するパッケージ

  • c#
  • 追加する都度書き足す

他の端末からSQLExpressに接続できるようにする設定

開発用端末に開発用DBを置くならこれらの設定は不要。

  • DBの設定(DBのある端末上のSSMSから設定した)
    • DBサーバーのプロパティで認証方法を混合認証に切り替える
    • DBサーバーのプロパティでリモートからのログインを許可するように変更する
  • DBのある端末上のSqlServerConfigurationManagerで以下を設定する
    • TCP/IPによる通信を有効にする
    • TCP/IPのポートを固定する(SQLExpressをインストールするときに「既定のインスタンス」として入れた場合は1433になるようだが、普通に入れると「端末名\SQLExpress」など名前付きのインスタンスになる。その場合は、TCP/IPでの通信は無効になっていてポートも「動的」になっている。そこで、49152–65535の範囲で任意の(他と被らない)ポートに固定する(「動的」のまま設定できるかもしれないが、調べてない)。IPAllについて通信を有効化する(使いたいIPアドレスだけ有効にしてもダメだった)。
  • F/Wの設定。上であけたTCPのポート番号について、外部からの通信を許可する。netshコマンドかコントロールパネルの「セキュリティが強化されたWIndows Defender Firewallの設定」の画面からおこなう。

dotnetコマンドでプロジェクトを作って必要なパッケージを追加する手順

  • まずプロジェクトを作る コマンドプロンプトからプロジェクトのフォルダを作りたい場所に移動して
dotnet new mvc -n myApp

とすると、カレントフォルダ内にmyAppというフォルダが作成されてその下にプロジェクトのひな形ができる

  • VSCodeを起動して拡張機能のボタンを押してc#を探して入れる。 直接インストールできない環境の場合は、いったんダウンロードして、拡張機能タブ上部の...を押して、「vsixのインストール」でダウンロードしたファイルを選択して入れる(そもそもダウンロード先までたどり着けないときは、プロキシの設定が必要かもしれないので確認して設定する)
  • 「ファイル」>「フォルダを開く」で先ほど作ったフォルダを選択する
  • とりあえずF5を押して実行してみる launch.jsonとtask.jsonが自動生成されればそのまま実行でき、ブラウザでlocalhost:5000にアクセスするとhttpsの5001にリダイレクトされてWelcomeページが表示される。自動生成されないときは、以下の手順(2つ環境を作ったが1台は自動生成されなかった、謎)。

    • 自動生成されない場合はエラーが出て設定しろと言われるので、launch.jsonを開いて、プルダウンで.Net Coreを選んで、生成されたConfig内容ののprogramキーの値として、作成するアプリのdllへのフルパスの部分を書く。
    • 再度実行すると今度はtask.jsonを設定しろと言われるので、ConfigureTasksを押してデフォルトのまま追加する。これでもう一度実行すると起動出来た。
  • EFのパッケージを追加する(プロジェクトごとに必要)参考リンク

   dotnet add package Microsoft.EntityFrameworkCore.SqlServer
   dotnet tool install --global dotnet-ef
//「すでに入っている」と言われたときは念のため以下のコマンドで最新版に更新する
   dotnet tool update --global dotnet-ef
  • dotnet ef コマンドを使えるようにする
dotnet add package Microsoft.EntityFrameworkCore.Design
  • これも入れるらしいが、「指定された検索条件とパッケージ名 'Microsoft.EntityFrameworkCore.Tools' と一致するものが見つかりませんでした。」と言われたので保留 nugetパッケージをVS Code上で追加するときはdotnet add package ...で入れる
//これはnugetパッケージをVisual Studio上でインストールする場合↓
Install-Package Microsoft.EntityFrameworkCore.Tools
//VS Code上でnugetパッケージを入れるときはこのコマンドを使う↓
 dotnet add package Microsoft.EntityFrameworkCore.Tools

ここまで入れてdotnet ef と入力してみてロゴが表示されたのでとりあえずOKとした

既存のDBからクラスを生成(DbContext,Entity)し、エンティティを使ってCRUD画面を生成する。

  • スキャフォールディング用のツールを入れる
dotnet tool install -g dotnet-aspnet-codegenerator

これも必要?Microsoft.VisualStudio.Web.CodeGeneration.Design

dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
  • DBコンテキスト用 > 上でインストールしたdotnet ef コマンドでおこなう

  • コマンド

    • スキーマからDbContext、EntityClassを生成するコマンド
dotnet ef dbcontext scaffold "server=x.x.x.x,port\sqlexpress;database=db名;Persist Security Info=True;User ID=xxx;Password=xxx" Microsoft.EntityFrameworkCore.Sqlserver -o Models 

これでプロジェクトにModelsフォルダが作られ、DbContextとエンティティクラスが追加される。 (DB側を更新した場合にちゃんと追随できるかは未検証)

dotnet aspnet-codegenerator controller -name XXXController -m XXX -dc XXXContext --relativeFolderPath Controllers --useDefaultLayout --referenceScriptLibraries

これでCRUDのコントローラーとビュー(cshtmlファイル)が生成される、が実行するとエラーになる。

error CS1061: 'TXXX' に 'Id' の定義が含まれておらず、型 'TXXX' の最初の引数 を受け付けるアクセス可能な拡張メソッド 'Id' が見つかりませんでした。

ジェネレータで生成されたエンティティクラスのIdに[Key]アトリビュートを追記したら解消した。

using System.ComponentModel.DataAnnotations;//←これを追加しないと[Key]が使えない
...
    public partial class TXXX
    {
        [Key]   //←これを追加
        public int Id { get; set; }
        ...

KeyAttributeを使うためにusingにusing System.ComponentModel.DataAnnotationsを書き足す必要がある。

  • サービスの登録と接続文字列の設定 DbContextをコントローラから使えるようにサービスへ登録する。startup.csに以下を書き足す
using Microsoft.EntityFrameworkCore;//これを追加
...
        public void ConfigureServices(IServiceCollection services){//この中に以下を追加
          ...
             services.AddDbContext<Models.TEST_DBContext>(optionsAction=>
                    optionsAction.UseSqlServer(Configuration.GetConnectionString("MyConnectionstring")));

スキャフォールディングした直後は接続文字列がDbContextに直書きなので、appsettings.jsonにConnectionStringsというセクションを追加してそこに移動する。たぶんここを読む必要あり(まだ読んでない)

{...//キーを追加して接続文字列を書く
  "ConnectionStrings":{
      "MyConnectionstring":"server=x.x.x.x,port\sqlexpress;database=db名;Persist Security Info=True;User ID=xxx;Password=xxx"  }
}

dotnet efのスキャフォールディングで生成されたDbContext内のOnConfiguringメソッド内のconnectionStringを設定している行(またはメソッドごと)を削除する。 たぶん入っているはずだけど、Configurationの参照がない場合は以下のパッケージをインストールする。

dotnet add package Microsoft.Extensions.Configuration

そろそろ編集が大変になってきたので続きは別エントリで