我喜欢将SQL脚本作为资源嵌入程序集中,这样程序集就不依赖于任何外部文件。我已经在Visual Studio Community 2019 16.4.2中测试过这种方法。
在我的情况下,
DbContext
保存在.NET Standard 2.0库中,我的Web应用程序运行在.NET Core 2.2上。
首先,您需要创建一个迁移文件:
- 在Visual Studio中,确保将Web应用程序设置为启动项目。
- 在Visual Studio中打开PMC:View->Other Windows->Package Manager Console (PMC)
- 在PMC中将默认项目设置为保存DbContext的项目(在我的情况下是.NET标准2.2库)
添加新的迁移:
Add-Migration RunSqlScript
在迁移文件夹中添加一个Sql脚本(为了方便,我将其命名为与迁移文件相同的前缀)。
![Migration folder in the Solution Explorer](https://istack.dev59.com/zKruj.webp)
在文件属性窗口中,确保生成操作为"嵌入的资源"。请注意,我们不需要复制到输出文件夹,因为SQL脚本将被嵌入程序集中。
更新
RunSqlScript
迁移中的Up方法。
var assembly = Assembly.GetExecutingAssembly();
string resourceName = typeof(RunSqlScript).Namespace + ".20191220105024_RunSqlScript.sql";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
using (StreamReader reader = new StreamReader(stream))
{
string sqlResult = reader.ReadToEnd();
migrationBuilder.Sql(sqlResult);
}
}
我在我的应用程序中将此代码重构为一个实用方法。出于简洁性的考虑,我已经发布了没有这个重构的版本。
更新:
上述我提到的重构代码:
public static class MigrationUtility
{
public static string ReadSql(Type migrationType, string sqlFileName)
{
var assembly = migrationType.Assembly;
string resourceName = $"{migrationType.Namespace}.{sqlFileName}";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
if (stream == null)
{
throw new FileNotFoundException("Unable to find the SQL file from an embedded resource", resourceName);
}
using (var reader = new StreamReader(stream))
{
string content = reader.ReadToEnd();
return content;
}
}
}
}
使用示例:
string sql = MigrationUtility.ReadSql(typeof(RunSqlScript), "20191220105024_RunSqlScript.sql");
migrationBuilder.Sql(sql);