dotnet script ではEntityFrameworkCoreは動かない？などなど（更新:検証完了）

## dotnet script でNugetライブラリ等のエラーを回避する（追記）

> v1.2.1 以降では dotnet script のコマンドライン引数に --isolated-load-context というオプションが追加されているようですね。

コメントでいただいたとおり
以下のようにすることで競合回避できました。ありがとうございます。

```
dotnet script --isolated-load-context [hogehoge].csx
```

## dotnet script とは？
dotnet core に、拡張ツールを追加することで、C#言語をスクリプトとして実行することができるようになるものです（インタプリタではなくコンパイルされるみたいなので実行されるまでが遅いです。実行は早いですが。書き換えがなければ２回目以降は早めです）。
簡単なスクリプトとして書きたい場合や、テストを書きたい場合に便利です。
最近知りました。

```bash
dotnet tool install -g dotnet-script
```

dotnet core 3.1 以降が入ってる環境で利用するのがおすすめです。
なお使うときは、VSCodeに、C#拡張を入れておくとよいかと。

使い方は

```bash
dotnet script [filename].csx
```

## パラメータ

スクリプトで動作させるとはいえ、パッケージがないと動かないのですが、nugetを呼び出せます

```c#
#r "nuget: [パッケージ名], [バージョン]"
```

例えば、今回動いてない問題があるパッケージを入れたい場合は

```c#
#r "nuget: Pomelo.EntityFramworkCore.MySql, 3.2.4"
```

とコードより先に書いておくことでパッケージをインストールして利用してくれます。
あと、dotnetのバージョンを指定する場合は、１行目に

```c#
#! "netcoreapp3.1"
```

のように書くこともできます。
ほかにも

```c#
#load "nuget:[パッケージ名],[バージョン]"
```

なるものもあるのですが、ちょっとまだわからないです。

## とりあえず、書き方だけ

今回、試してみようとしたのは、WPのDBからちょこちょこってデータ取り出したり書き出したりをLINQで書きたいなとおもって、EntityFramworkCoreを使おうとしたところエラーになったので、そのサンプル。

```C#
#! "netcoreapp3.1"
#r "nuget: Pomelo.EntityFrameworkCore.MySql, 3.2.4"

using System.Linq;
using System.IO;
using System.Collections.Generic;

using MySql.Data.MySqlClient;
using Microsoft.EntityFrameworkCore;

class TestDb : DbContext
{
    MySqlConnectionStringBuilder Config;

    public TestDb(){
        Config = new MySqlConnectionStringBuilder();
        Config.Server = "localhost";
        Config.Port = 3306;
        Config.UserID = "develop";
        Config.Password = "develop";
        Config.Database = "nekoblog_test";
        Config.CharacterSet = "utf8mb4";
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => 
        optionsBuilder.UseMySql(Config.ConnectionString);
}

var db = new TestDb();
```

というテストを書いてみたところ

```
System.IO.FileLoadException: Could not load file or assembly 'Microsoft.Extensions.DependencyInjection.Abstractions, Version=3.1.8.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. Could not find or load a specific file. (0x80131621)
```

どうやら、アセンブリが見つからなくて読み込めないようです？

```c#
#r "nuget: Microsoft.Extensions.DependencyInjection, 3.1.8"
#r "nuget: Microsoft.Extensions.DependencyInjection.Abstractions, 3.1.8"
```
を追加してもだめなので、ちょっと？？？？
*追記: どちらを入れてもだめでした（どちらもパッケージとして存在してます）

あまり利用している方いないのか、いろいろ試したり、同じように悩んでる人いないか探し回ってますが、今のところ解決策を見いだせず状態であります。ほかの件もあるので、ここにちょっと時間をかけられないという状況で（汗

## 別件メモ（using で IDisposableを使う場合)

dotnet script （C#9.0からエントリーになるファイルにMainメソッドを置かなくてもかけるよう、トップレベルステートメント対応になりましたので、C#9.0でその書き方をしたときも対象かもしれませんが）でリソース解放を書くときに、トップレベルステートで以下のようにコードを書いちゃうと...

```c#
using System.Linq;
using System.IO;
using System.Collections.Generic;

...

using var buffer = new System.IO.MemoryStream();

...

```

以下のようにエラーになります。

```
/Users/***/Desktop/test/test.csx(31,11): error CS1002: ; が必要です。
/Users/***/Desktop/test/test.csx(31,11): error CS0103: 現在のコンテキストに 'buffer' という名前は存在しません。
/Users/***/Desktop/test/test.csx(31,34): error CS0234: 型または名前空間の名前 'MemotyStream' が名前空間 'System.IO' に存在しません (アセンブリ参照があることを確認してください)。
```

まぁ、アセンブリ参照とと見分けがつかないからなのか、C#言語のバグなのかは、今のところ不明ですが。
なお、以下のようにメソッドを用意してあげる場合は問題ないです。

```c#
void test() {
    using var buffer = new System.IO.MemoryStream();
}
test();
```

あと、以前の通りはトップステートでも大丈夫です。

```C#
using(var buffer = new System.IO.MemoryStream()){
   ...
}
```

こちらはメモ程度に。


## 解決

~~以下のように書き直したら、MySqlでEntityFrameworkCoreを使って動作しました。nugetの呼び出し順があるのか、バージョン指定に問題があるのかはこれから調査しておこうかと思います。~~
バージョンの依存関係っぽいかなとは思っているんですが、ちょっと原因が謎すぎです。
Pomelo.EntityFrameworkCore.MySql は、現在(2021.02/16現在)、3.2.4が最新版なのですが、3.2.x系統は全部だめでした。やはり同じエラーが発生していましたが、3.1.2や3.1.1、3.1.0 は問題なく動作したことと、MicrosoftのEntityFrameworkCoreパッケージを入れなくても動作した関係から、何かのバージョン関係依存やらが起こったのかなと。ただ、IDE(VS2019)でコンソールなどを作ったときにPomelo.EntityFrameworkCore.MySql 3.2.4 等を入れて作ったときは問題なかった気がするので、ちょっと謎です。

```c#
#! "netcoreapp3.1"
#r "nuget: Pomelo.EntityFrameworkCore.MySql, 3.1.2"

using System.Linq;
using System.IO;
using System.Collections.Generic;

using MySql.Data.MySqlClient;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;

[Table("wp_posts")]
class WPPosts{
    public long ID {set;get;}
    public string post_title{set;get;}
    public string post_content{set;get;}
    public string post_type{set;get;}
}

class TestDb : DbContext
{
    MySqlConnectionStringBuilder Config;
    public DbSet<WPPosts> Posts{set;get;}
    public TestDb(){
        Config = new MySqlConnectionStringBuilder();
        Config.Server = "localhost";
        Config.Port = 3306;
        Config.UserID = "develop";
        Config.Password = "develop";
        Config.Database = "nekono_blog";
        Config.CharacterSet = "utf8mb4";
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => 
        optionsBuilder.UseMySql(Config.ConnectionString);

    public string ConnectionString() => Config.ConnectionString;
}

using(var db = new TestDb()){
    Console.WriteLine(db.ConnectionString());
    var id = db.Posts.Where( g => g.post_title.Contains("c#")).Select(g => g.ID);
    foreach( var i in id ) {
        Console.WriteLine(i.ToString());
    }
}
```

~~ちなみに、上記では、nugetのバージョン参照の関係でエラーが出ます...。~~