我一直在使用这样的连接字符串将我的网站连接到我的数据库:
<add name="MyDb"
connectionString="Data Source=MyDb;
Initial Catalog=Staging;
User Id=website_staging;
Password=secret;"
providerName="System.Data.SqlClient" />
Run Code Online (Sandbox Code Playgroud)
该website_staging用户是该角色的成员db_ddladmin,因此当我发布并且我的MigrateDatabaseToLatestVersion初始化程序运行时,它具有自动将数据库迁移到最新版本所需的权限。
我想减少标准用户的权限(通过仅将其添加到db_datareader和db_datawriter角色)并在迁移期间与不同的用户(在db_ddladmin角色中)连接。
所以我添加了另一个具有不同名称和用户的连接字符串:
<add name="Migrations"
connectionString="Data Source=MyDb;
Initial Catalog=Staging;
User Id=website_staging_migrations;
Password=secret;"
providerName="System.Data.SqlClient" />
Run Code Online (Sandbox Code Playgroud)
我更改了类中初始化的上下文所使用的连接字符串的名称DatabaseMigrationConfig:
public class DatabaseMigrationConfig
{
internal static void Register()
{
using (var context = new MyDbContext(Name="Migrations"))
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext,
Migrations.Configuration>());
context.Database.Initialize(false);
}
}
}
Run Code Online (Sandbox Code Playgroud)
在我的类的构造函数中,Migrations.Configuration我还更改了连接字符串:
internal sealed class Configuration : DbMigrationsConfiguration<SID2013Context>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
AutomaticMigrationDataLossAllowed = false;
string cs = ConfigurationManager.ConnectionStrings["Migrations"].ConnectionString;
TargetDatabase = new DbConnectionInfo(cs, "System.Data.SqlClient");
}
}
Run Code Online (Sandbox Code Playgroud)
然后我尝试发布该网站。它似乎正确选择了具有较高权限的连接字符串,但它尝试运行迁移Initial。我怎样才能阻止它这样做呢?
我最终通过将website_staging_migrations用户添加到角色以及db_datareader角色中来解决这个问题。db_datawriterdb_ddladmin
用户显然需要读取表中的数据__MigrationHistory。令我困惑的是 EF 不会将访问表失败报告为错误,而是在尝试运行初始迁移时收到此错误:
There is already an object named '----' in the database.
Run Code Online (Sandbox Code Playgroud)
并且用户还需要写入表__MigrationHistory。在将用户添加到角色之前,我收到此错误db_datawriter:
The INSERT permission was denied on the object '__MigrationHistory',
database 'Staging', schema 'dbo'.
Run Code Online (Sandbox Code Playgroud)