Jiro Laboratory

C#、ASP.NET、JavaScript、Androidとか

LocalDB から SQL Server (Express) へのデータ移行

LocalDB、SQL Server Express は SSMS*1 からデータをエクスポートすることができません。
LocalDB/SQL Server Express から SQL ServerSQL Server Express にデータを移行するにはデタッチ/アタッチを使用します。

デタッチ

あらかじめデータファイル(*.mdf)の場所を確認しておきます。
SSMS からデータベース名を右クリック > プロパティ > File(ページの選択) で *.mdf と *_log.ldf のパスがわかります。
LocalDB であれば c:\Users\ユーザー名 の直下にあるはず。
SSMS からデータベース名を右クリック > タスク > デタッチ を選択します。

アタッチ

*.mdf と *_log.ldf を任意のフォルダにコピーします。
SSMS から移行先インスタンスの「データベース」フォルダを右クリック > アタッチ を選択します。
「データベースのインポート」ダイアログが表示されるので「追加」ボタンからコピーした *.mdf ファイルを選択。
(*_log.ldf は自動的に選ばれるので選択する必要はありません)
「OK」ボタンを押せば移行完了です。

SQL Server のバージョンが 移行元 > 移行先 の場合、移行できませんので、その場合はあらかじめ移行先の SQL Server (Express) のバージョンを上げておきましょう。バージョンは SSMS でインスタンスの右に表示されている数字から分かります。(SQL Server XX.0.xxxx の XX に該当する数字です)

*1:SQL Server Management System

HttpClientFactory 経由で HttpClient を生成する(.NET Core コンソールアプリの場合)

NET Core 2.1 から使用できるようになった HttpClientFactory ですが、ASP.NET Core 関連の情報が多く、コンソールアプリでのサンプルが見受けられなかったので、最小限で動作するコードを作成してみました。
以下のパッケージが必要となります。

Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Http


.NET Core コンソールアプリでの SQLServer LocalDB の使用

docs.microsoft.com

上記は dotnet コマンド を使って SQLite を使用するサンプルです。
以下に、Visual Studio を使って SQL Server(LocalDB) を使用する場合の手順を残しておきます。

Entity Framework Core のインストール、DB作成

Entity Framework Core をインストール

パッケージマネージャーコンソールから以下を実行

PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer
PM> Install-Package Microsoft.EntityFrameworkCore.Tools
モデルを作成

Models.cs

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=blogging;Trusted_Connection=True;MultipleActiveResultSets=true");
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}
データベースの作成

パッケージマネージャーコンソールから以下を実行

PM> Add-Migration InitialCreate
PM> Update-Database

この時点で Local DB が作成されます。

データベースへのアクセス

以降は通常の Entity Framework の作法でアクセスが可能です。
Program.cs

public static void Main()
{
    using (var db = new BloggingContext())
    {
        db.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/adonet" });
        var count = db.SaveChanges();
        Console.WriteLine("{0} records saved to database", count);

        Console.WriteLine();
        Console.WriteLine("All blogs in database:");
        foreach (var blog in db.Blogs)
        {
            Console.WriteLine(" - {0}", blog.Url);
        }
    }
}

Linux(Ubuntu)での .NET Core 開発環境の構築

以下のシェルをダウンロード
https://dot.net/v1/dotnet-install.sh

ターミナルで以下のコマンドを実行

$ chmod u+x ./dotnet-install.sh
$ ./dotnet-install.sh -c Current
$ sudo snap install dotnet-sdk --classic

プロファイルにパスを追加

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

PATH="$HOME/.dotnet:$PATH"

ターミナルでプロファイルの変更を反映

$ source ./.profile

ターミナルで dotnet コマンドを実行してバージョンを確認

$ dotnet --version
2.2.100

ビューのパス指定

コントローラー名とは異なるフォルダの View を使用することができます。

ルートからのパス指定

ルートからのパスを使用する場合は、.cshtml 拡張子を指定する必要があります。

return View("Views/Home2/About2.cshtml");

相対パス指定

相対パスを使用する場合は、.cshtml 拡張子を指定しません。

return View("../Home2/About3");

ASP.NET MVC Core 「HTTPS 用の構成」の有無による生成ソースの違い

HTTPS 用の構成」の選択有無による生成ソースの違いを調べました。
違いがあったのは
・launchSettings.json
・Startup.cs
のみです。

gist.github.com

launchSettings.json

HTTPS 用の構成」なし

"applicationUrl": "http://localhost:5000",

HTTPS 用の構成」あり

"applicationUrl": "https://localhost:5001;http://localhost:5000",
Startup.cs

HTTPS 用の構成」ありの場合、app.UseHsts()、app.UseHttpsRedirection() が追加されます。

HTTPS 用の構成」なし

else
{
    app.UseExceptionHandler("/Home/Error");
}

app.UseStaticFiles();
app.UseCookiePolicy();

app.UseMvc(routes =>

HTTPS 用の構成」あり

else
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseMvc(routes =>

ajax を並列に実行する

同一セッションのリクエストは並列で処理されない

セッションを使用している場合、ASP.NET のデフォルト動作では同一セッションのリクエストは並列で処理されません。

function test(value) {
    $.ajax({
        url: "Page1/Test",
        data: value
    });
}

test(1);
test(2);
test(3);
test(4);

このようなスクリプトを書いても、サーバーサイドの ajax 処理は直列で実行されます。*1
そのため、複数の ajax を同時に呼び出しても並列実行されないためパフォーマンスが出ません。
こういう場合、コントローラーにセッションの読取専用属性(SessionState(SessionStateBehavior.ReadOnly)) を付与することで並列実行が可能になります。
ただし、このコントローラーは Session に書き込むことが出来なくなります。*2

もう少し柔軟に処理したい場合

コントローラー ファクトリを自作することで、静的な属性設定ではなく、動的に SessionState 属性を制御することが可能です。
以下では、リクエストが ajax の場合のみセッションを読み取り専用にしています。

*1:順序は保証されません

*2:Sessionに書き込んでもエラーにはならないが、値は設定されない