使用Azure Managed Identity运行EF Code First迁移时,如何解决“ CREATE SCHEMA”失败的错误

时间:2019-04-08 16:44:52

标签: entity-framework entity-framework-6 azure-sql-database ef-migrations

我正在尝试对通过Azure托管身份连接的Azure SQL数据库运行EF6 Code First迁移。有几个迁移要运行。上一次迁移失败。此迁移与其他迁移不同,因为它在新架构中创建表。

这是在运行创建新架构的Entity Framework Code First迁移时返回的错误:

System.Data.SqlClient.SqlException: The specified schema name "uuid@uuid" either does not exist or you do not have permission to use it.
CREATE SCHEMA failed due to previous errors.

我已将SQL命令记录在数据库中,而似乎失败的命令是

IF schema_id('MyNewSchema') IS NULL
EXECUTE('CREATE SCHEMA [MyNewSchema]')

出现错误:

<batch_information><failure_reason>Err 2759, Level 16, Server mysqldbname
CREATE SCHEMA failed due to previous errors.</failure_reason></batch_information>

以下是有关系统的一些详细信息:

我尝试过的事情

1。添加角色

我尝试过的主要方法是使用Microsoft权限文档确定所需的权限。到目前为止,我已经将以下角色添加到了所包含的用户中,运行迁移的App Service以以下角色连接:

db_ddladmin
db_datareader
db_datawriter
db_securityadmin
db_owner
db_accessadmin

(请注意,其他迁移仅适用于db_ddladmin,db_datareader和db_datawriter)

2。以服务器管理员身份运行迁移

我尝试以SQL Server管理员用户身份运行迁移。这可行,但是我们不允许以生产系统的SQL Server管理员用户身份进行连接。

2 个答案:

答案 0 :(得分:1)

我刚刚遇到了使用asp.net core 2.2和EF core的同一问题。我试图使用托管身份来创建架构,并得到相同的错误。我发现这篇文章表明它是一个错误-https://techcommunity.microsoft.com/t5/Azure-Database-Support-Blog/Lesson-Learned-54-The-specified-schema-name-name-domain-com/ba-p/369152

我唯一的解决方法是用服务器admin创建架构,这并不理想。

答案 1 :(得分:0)

如果将 AUTHORIZATION 添加到 CREATE SCHEMA 命令,它会起作用。

所以实体框架创建的语句需要看起来像这样:

IF schema_id('MyNewSchema') IS NULL
EXECUTE('CREATE SCHEMA [MyNewSchema] AUTHORIZATION [dbo]')

您可以通过覆盖 ApplicationSqlServerMigrationsSqlGenerator

    protected override void Generate(EnsureSchemaOperation operation, IModel model, MigrationCommandListBuilder builder)
    {
        if (operation is null)
            throw new ArgumentNullException(nameof(operation));
        if (builder is null)
            throw new ArgumentNullException(nameof(builder));
        if (string.Equals(operation.Name, "dbo", StringComparison.OrdinalIgnoreCase))
        {
            return;
        }
        var stringTypeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(string));
        builder
            .Append("IF SCHEMA_ID(")
            .Append(stringTypeMapping.GenerateSqlLiteral(operation.Name))
            .Append(") IS NULL EXEC(")
            .Append(
                stringTypeMapping.GenerateSqlLiteral(
                    "CREATE SCHEMA "
                    + Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)
                    + " AUTHORIZATION "
                    + Dependencies.SqlGenerationHelper.DelimitIdentifier("dbo")
                    + Dependencies.SqlGenerationHelper.StatementTerminator))
            .Append(")")
            .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator)
            .EndCommand();
    }

然后注册:

        services.AddDbContextPool<ApplicationDbContext>(options =>
        {
            options.UseSqlServer("Your connection string");
            options.ReplaceService<IMigrationsSqlGenerator, ApplicationSqlServerMigrationsSqlGenerator>();
        });

(上面的代码适用于 EF Core,因为我在那里遇到了问题)