在DbMigration中访问Up中的数据库名称

时间:2013-11-21 10:17:42

标签: .net sql sql-server entity-framework ef-code-first

我在代码优先迁移中有以下代码:

public partial class RunSQLInit : DbMigration
{
    public override void Up()
    {
        this.Sql(SqlFiles.Create_Job_ClearExpiredData);
    }

    [...]
}

其中SqlFiles.Create_Job_ClearExpiredData是一个resx文件,将SQL文件作为字符串返回。 SQL在SQL Server中创建并计划服务器代理作业。

现在,SQL有两个“变量”我需要能够在数据库上运行迁移之前进行更改:作业应该运行的数据库的名称,以及实际作业的名称。如果我只有一个环境,那就没问题,但我将这个代码优先项目部署到许多环境中,这些环境在数据库名称和我应该称之为Job的方面有所不同。

我看到三种可能性:

  1. 获取当前在Up()方法中使用的连接字符串,并使用它来解析数据库名称,并在运行之前将其替换为SQL字符串。但是我如何才能获得“当前正在使用的连接字符串”?
  2. 在程序包管理器控制台中运行Update-Database时,以某种方式将变量传递给迁移,这可以在迁移中访问。我该怎么办呢?
  3. 使用其他解决方案来创建作业。我们在很大程度上依赖于从代码优先模型到所有环境的部署,因此在更新数据库和生成部署脚本(使用Update-Database -script
  4. 时,应该可以轻松实现自动化,而无需额外的人工

    有问题的SQL脚本有一个小问题:

    EXEC msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Run SP', 
        @step_id=1,
        @subsystem=N'TSQL',
        @command=N'exec sp_ClearExpiredData;', 
        @database_name=@databaseName, --This is where I need the varying database name!
        @flags=0
    

3 个答案:

答案 0 :(得分:2)

我的问题的答案是在SQL文件中使用它:

set @databaseName = db_name()

由于当前上下文已经是我将用于工作的数据库,它已经存在。太容易了。

答案 1 :(得分:2)

我必须声明我的@DBName变量才能设置它。否则出错:

  

必须声明标量变量" @ DBName"。

完整代码:

Sql("DECLARE @DBName nvarchar(50), @SQLString nvarchar(200)\r\n" +
    "SET @DBName = db_name();\r\n" +
    "SET @SQLString = \'ALTER DATABASE [\' + @DBName + \'] COLLATE Latin1_General_100_CI_AS\'\r\n" +
    "EXEC( @SQLString )", suppressTransaction: true);

答案 2 :(得分:1)

选项1适用于您的数据库名称。见Is there any connection string parser in C#?

Job可能需要来自配置文件。将名称放在AppSettings中,然后就可以了

string jobName = ConfigurationManager.AppSettings["jobName"]

当然,你也可以为dbName做同样的事情:

string dbName = ConfigurationManager.AppSettings["dbName"]

我有一个如下所示的配置类:

public class Config
{
    public static string ConnectionStringName
    {
        get { return GetValue("ConnectionStringName", "SID_2013Context"); }
    }    

    private static string GetValue(string key, string defaultValue)
    {
        return ConfigurationManager.AppSettings[key] ?? defaultValue;
    }
}

我的DBContext类构造函数如下所示:

    public SID2013Context()
        : base("Name=" + Config.ConnectionStringName)
    {
    }

我的web.config有一个连接字符串:

  <connectionStrings>
    <add name="SID_2013Context" connectionString="etc" providerName="System.Data.SqlClient" />
  </connectionStrings>

所以我可以在配置类中添加几个属性:

public static string ConnectionString
{
    get { return ConfigurationManager.ConnectionStrings[ConnectionStringName]
                                     .ConnectionString; }
}

public static string DatabaseName
{
    get
    {
        var builder = new System.Data.SqlClient
                      .SqlConnectionStringBuilder(ConnectionString);
        return builder.DataSource;
    }
}

然后在我的Up()迁移中:

   public override void Up()
   {
         string databaseName = Config.DatabaseName;
   }