简体   繁体   English

如何使用 Entity Framework Core 运行迁移 SQL 脚本

[英]How to run migration SQL script using Entity Framework Core

I faced with an issue, where I can't reach the SQL script to apply the migration.我遇到了一个问题,我无法访问 SQL 脚本来应用迁移。 Here is my migration code:这是我的迁移代码:

 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));
    }
}

So when I use the Package Manager Console on the local machine all works fine.因此,当我在本地机器上使用 Package 管理器控制台时,一切正常。 But when I deploy to the environment I get the discrepancy to the file.但是当我部署到环境时,我得到了文件的差异。

Can I run my static SQL scripts via EF migration automatically at all, or I should paste the SQL query inline in code?我可以通过 EF 迁移自动运行我的 static SQL 脚本,还是应该将 SQL 查询内联粘贴到代码中?

I faced with an issue, where I can't reach the SQL script to apply the migration.我遇到了一个问题,我无法访问 SQL 脚本来应用迁移。 Here is my migration code:这是我的迁移代码:

 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));
    }
}

So when I use the Package Manager Console on the local machine all works fine.所以当我在本地机器上使用包管理器控制台时一切正常。 But when I deploy to the environment I get the discrepancy to the file.但是当我部署到环境时,我得到了文件的差异。

Can I run my static SQL scripts via EF migration automatically at all, or I should paste the SQL query inline in code?我可以通过 EF 迁移自动运行我的静态 SQL 脚本,还是应该将 SQL 查询内联粘贴到代码中?

I faced with an issue, where I can't reach the SQL script to apply the migration.我遇到了一个问题,我无法访问 SQL 脚本来应用迁移。 Here is my migration code:这是我的迁移代码:

 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));
    }
}

So when I use the Package Manager Console on the local machine all works fine.所以当我在本地机器上使用包管理器控制台时一切正常。 But when I deploy to the environment I get the discrepancy to the file.但是当我部署到环境时,我得到了文件的差异。

Can I run my static SQL scripts via EF migration automatically at all, or I should paste the SQL query inline in code?我可以通过 EF 迁移自动运行我的静态 SQL 脚本,还是应该将 SQL 查询内联粘贴到代码中?

I faced with an issue, where I can't reach the SQL script to apply the migration.我遇到了一个问题,我无法访问 SQL 脚本来应用迁移。 Here is my migration code:这是我的迁移代码:

 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));
    }
}

So when I use the Package Manager Console on the local machine all works fine.所以当我在本地机器上使用包管理器控制台时一切正常。 But when I deploy to the environment I get the discrepancy to the file.但是当我部署到环境时,我得到了文件的差异。

Can I run my static SQL scripts via EF migration automatically at all, or I should paste the SQL query inline in code?我可以通过 EF 迁移自动运行我的静态 SQL 脚本,还是应该将 SQL 查询内联粘贴到代码中?

I created an extensions method based on 4lexKislitsyn 's answer.我根据4lexKislitsyn的回答创建了一个扩展方法。 This assumes that your files end with a .sql extension and that it's an embeded resource in whatever project your running the migrations from.这假设您的文件以.sql扩展名结尾,并且它是您运行迁移的任何项目中的嵌入资源。 You could of course move the .sql part to the Up of your migration but this seemed cleaner to me.您当然可以将.sql部分移动到迁移的Up部分,但这对我来说似乎更清晰。

public static class MigrationExtensions
{
    public static void RunSqlScript(this MigrationBuilder migrationBuilder, string script)
    {
        var assembly = Assembly.GetExecutingAssembly();
        var resourceName = assembly.GetManifestResourceNames().FirstOrDefault(x => x.EndsWith($"{script}.sql"));
        using var stream = assembly.GetManifestResourceStream(resourceName);
        using var reader = new StreamReader(stream);
        var sqlResult = reader.ReadToEnd();
        migrationBuilder.Sql(sqlResult);
    }
}

Used as用作

public partial class AddViews : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RunSqlScript("nameOfMyFile");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {

    }
}

I've found that evaluating the sql file name from the provided MigrationAttribute the best approach.我发现从提供的 MigrationAttribute 评估 sql 文件名是最好的方法。

  public class EmbeddedSqlFileMigration : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            var assembly = Assembly.GetExecutingAssembly();
            var type = GetType();
            var migrationAttribute = type.GetCustomAttribute<MigrationAttribute>();
            if (migrationAttribute == null)
                throw new InvalidOperationException("A migration requires a MigrationAttribute.");

            var sqlResourceFilename = $"{type.Namespace}.{migrationAttribute.Id}.sql";
            var resourceName = assembly.GetManifestResourceNames().FirstOrDefault(r => r == sqlResourceFilename);
            if (resourceName == null)
            {
                throw new FileNotFoundException(
                    $"Embedded resource '{sqlResourceFilename}' was not found in assembly '{assembly.FullName}'.");
            }

            using var stream = assembly.GetManifestResourceStream(resourceName);
            if (stream == null)
            {
                throw new InvalidOperationException(
                    $"Unable to get stream for embedded resource '{sqlResourceFilename}' in assembly '{assembly.FullName}'.");
            }

            using var reader = new StreamReader(stream);
            var sqlResult = reader.ReadToEnd();
            migrationBuilder.Sql(sqlResult);
        }
    }

my tech lead and I were trying to figure out why I hadn't found a simple answer to inserting statements yet.我的技术主管和我试图弄清楚为什么我还没有找到插入语句的简单答案。 Neither was frustrated at the other, both were frustrated at the lack of simplicity we ran into.双方都没有对对方感到沮丧,他们都对我们遇到的缺乏简单性感到沮丧。

We found:我们发现:

  1. https://www.learnentityframeworkcore.com/raw-sql https://www.learnentityframeworkcore.com/raw-sql
  2. https://mycodingtips.com/2021/9/20/how-to-run-sql-scripts-in-a-file-using-ef-core-migrations 3.https://www.codeproject.com/Articles/1173837/BulkInsert-with-the-Entity-Framework https://mycodingtips.com/2021/9/20/how-to-run-sql-scripts-in-a-file-using-ef-core-migrations 3.https://www.codeproject.com/Articles /1173837/BulkInsert-with-the-Entity-Framework
  3. https://www.yogihosting.com/insert-records-entity-framework-core/ https://www.yogihosting.com/insert-records-entity-framework-core/

All are valid or a good start, NONE are as simple as this:所有都是有效的或一个好的开始,NONE 就是这么简单:

  1. Generate the insert statements needed生成所需的插入语句
  2. Use a GO separator between each在每个之间使用 GO 分隔符
  3. Parse the file in a Console Project, count up to 500 Go Separators to make blocks of 500 statements在控制台项目中解析文件,最多计算 500 个 Go 分隔符以生成 500 个语句块
  4. Run each of the blocks making a string of each block and use DbSet.FromRawSQL(block of inserts)运行每个块制作每个块的字符串并使用 DbSet.FromRawSQL(block of inserts)

I'll write the approach and post the code once I'm done.完成后,我将编写方法并发布代码。

You can create a helper method in same project first:您可以先在同一个项目中创建一个辅助方法:

public static string GetRawSql(string sqlFileName)
{
    var baseDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Migrations");
    var path = Path.Combine(baseDirectory, sqlFileName);
    return File.ReadAllText(path);
}

And then add your migration.然后添加您的迁移。 Let's say you added as: add-migration AddDefaultUser and then it generated as below:假设您添加为: add-migration AddDefaultUser然后生成如下:

在此处输入图像描述

now add 2 sql files (incuding the SQL statement you want to run like an insert record etc..) with same name with postfix of _Up and _Down.现在添加 2 个 sql 文件(包括您想像插入记录一样运行的 SQL 语句等),名称相同,后缀为 _Up 和 _Down。 So it will be like:所以它会像:

在此处输入图像描述

Then in your migration file UP and DOWN methods, call them by using MigrationBuilder object.然后在您的迁移文件 UP 和 DOWN 方法中,使用 MigrationBuilder object 调用它们。 So your migration file will look like below:因此,您的迁移文件将如下所示:

public partial class AddDefaultUser : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    { 
        migrationBuilder.Sql(SqlFileTrigger.GetRawSql("20220918043843_AddDefaultUser_Up.sql")); 
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {  
        migrationBuilder.Sql(SqlFileTrigger.GetRawSql("20220918043843_AddDefaultUser_Down.sql"));
    }
}

PS: MAKE SURE YOU SET YOUR SQL FILE PROPERTIES AS COPY ALWAYS TO ENSURE THEY ARE DEPLOYED. PS:请确保将COPY ALWAYS文件属性设置为始终以确保它们被部署。

在此处输入图像描述

Hope it helps..希望能帮助到你..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在.NET Core 1.0中使用Entity Framework运行sql脚本? - How to run sql script with Entity Framework in .NET Core 1.0? 如何使用 Entity Framework Core 从 sql 脚本创建数据库? - How to create a database from sql script using Entity Framework Core? Entity Framework Core:无法在生产服务器上运行迁移脚本,聚集索引的最大键长度为 900 字节 - Entity Framework Core: Unable to run migration script on production server, The maximum key length for a clustered index is 900 bytes 在运行时在 .Net Core 中创建和应用迁移 - Entity Framework Core - Create and Apply Migration at run time in .Net Core - Entity Framework Core 如何设置 Entity Framework Core 迁移超时? - How to set Entity Framework Core migration timeout? 如何在 Entity Framework Core 中生成空迁移? - How to generate empty migration in Entity Framework Core? 无法使用Entity Framework创建迁移脚本 - Cannot create migration script using Entity Framework “脚本迁移”可以在 .NET Entity Framework Core 中创建数据库吗? - Can "Script-Migration" create the database in .NET Entity Framework Core? Entity Framework Core 中的种子脚本正在破坏我的迁移 - Seed script in Entity Framework Core is breaking my migration 如何使用 Entity Framework Core 在加密的 SQLite 数据库上运行迁移? - How can I run a migration with Entity Framework Core on an encrypted SQLite database?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM