移行を適用するSQLスクリプトにアクセスできないという問題に直面しました。これが私の移行コードです:
public partial class AddSomethingMigration : Migration
{
private const string MIGRATION_SQL_SCRIPT_FILE_NAME = @"Migrations\Scripts\20170710123314_AddSomethingMigration.sql";
protected override void Up(MigrationBuilder migrationBuilder)
{
string sql = Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).FullName, MIGRATION_SQL_SCRIPT_FILE_NAME));
migrationBuilder.Sql(File.ReadAllText(sql));
}
}
したがって、ローカルマシンでパッケージマネージャコンソールを使用すると、すべて正常に動作します。しかし、環境にデプロイすると、ファイルに不一致が生じます。
EF移行を介して静的SQLスクリプトを自動的に実行することはできますか、それともSQLクエリをコードにインラインで貼り付ける必要がありますか?
この質問に対するいくつかの回答が見つかりました。
スクリプトをプロジェクトリソースとして追加し、次のように使用します。
string sql = Resources._20170630085940_AddMigration;
migrationBuilder.Sql(sql);
.sqlがアセンブリに埋め込まれるため、このオプションはあまり良くありません。
.csproj構造のNet Coreプロジェクトを使用する場合、itemgroupをxmlに追加できます。
<ItemGroup> <Content Include="Migrations\**\*.sql" CopyToPublishDirectory="PreserveNewest" /><!-- CopyToPublishDirectory = { Always, PreserveNewest, Never } --></ItemGroup>
そして、次のようにファイルへのパスを指定します:
Path.Combine(AppContext.BaseDirectory, relativePath)
これは、EmbeddedResourceを使用するメソッドのアップグレードです。主なアイデアは、マイグレーションと同じ名前の抽象クラスとSQLファイルを使用することです。
public abstract class SqlMigration : Migration
{
protected sealed override void Up(MigrationBuilder migrationBuilder)
{
var Assembly = Assembly.GetExecutingAssembly();
var type = GetType();
var regex = new Regex($@"{Regex.Escape(type.Namespace)}\.\d{{14}}_{Regex.Escape(type.Name)}\.sql");
var resourceName = Assembly.GetManifestResourceNames().FirstOrDefault(x => regex.IsMatch(x));
using var stream = Assembly.GetManifestResourceStream(resourceName);
using var reader = new StreamReader(stream);
var sqlResult = reader.ReadToEnd();
migrationBuilder.Sql(sqlResult);
}
}
正規表現には、実際のタイプの名前と名前空間を使用します。継承クラスは次のようになります。
public partial class RunSqlScript : SqlMigration
{
protected override void Down(MigrationBuilder migrationBuilder)
{
// Down code here
}
}
プロジェクトは次のようになります。