我想在通过Entity Framework创建的每个新表之后运行一个SQL脚本。
我为'CreateTableOperation'创建了一个覆盖:
protected override void Generate(CreateTableOperation createTableOperation)
{
string tenantID = "tenantID";
base.Generate(createTableOperation);
//If the table contain the column "tenantID",
if ((from x in createTableOperation.Columns
where x.Name == tenantID
select x).Any()
)
{
//Add the Security Policies for this table
using (var writer = Writer())
{
writer.WriteLine("ALTER SECURITY POLICY rls.tenantAccessPolicy ");
//Note: dbo. is already part of the .Name, don't add it manually before .Name
writer.WriteLine($"ADD FILTER PREDICATE rls.fn_tenantAccessPredicateWithSuperUser([{tenantID}]) ON [{createTableOperation.Name}], ");
writer.WriteLine($"ADD BLOCK PREDICATE rls.fn_tenantAccessPredicateWithSuperUser([{tenantID}]) ON [{createTableOperation.Name}] ");
Statement(writer);
}
}
}
假设我创建了一个新类'TEST'。 问题是当我在软件包管理器控制台中运行更新数据库时,SQL在一个大块中执行并创建一个错误,因为该表尚未创建,我正在尝试获取table.name Update-Database后的Package Manager结果:
CREATE TABLE [dbo].[TEST] (
[ID] [int] NOT NULL IDENTITY,
[NameTEST] [nvarchar](max),
[TenantID] [int] NOT NULL,
CONSTRAINT [PK_dbo.TEST] PRIMARY KEY ([ID])
)
ALTER SECURITY POLICY rls.tenantAccessPolicy
ADD FILTER PREDICATE rls.fn_tenantAccessPredicateWithSuperUser([tenantID]) ON [dbo.TEST],
ADD BLOCK PREDICATE rls.fn_tenantAccessPredicateWithSuperUser([tenantID]) ON [dbo.TEST]
无法找到对象“dbo.TEST”,因为它不存在或您没有权限。 有没有办法在 base.Generate(createTableOperation); 和我的声明(作家); 之间打破? (我已经用“GO”尝试过多次没有太大成功的事情)。或者是我不应该在该方法中加入代码?
答案 0 :(得分:0)
我找不到解决方案/文档来分隔Generate(CreateTableOperation createTableOperation).
我做的是
在Generate(CreateTableOperation createTableOperation)
方法
/// <summary>
/// Generate dynamically named .sql file for CREATE and DROP Security Policies (Row-Level Security (Company can't see/insert data of another company))
/// </summary>
/// <param name="createTableOperation">Default parameter that comes with the override method.</param>
protected override void Generate(CreateTableOperation createTableOperation)
{
base.Generate(createTableOperation);
string fullFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\Migrations\\SQLscripts\\SecurityPolicies");
//Remove the schema for the dynamic creation of the .sql filename else it throw an exception:
int indexOfDot = createTableOperation.Name.IndexOf(".");
indexOfDot++; //Because it's 0 base, add 1 char
string tableNameWithoutSchema = (indexOfDot < 0) ? createTableOperation.Name : createTableOperation.Name.Remove(0, indexOfDot);
string filePathCreate = Path.Combine(fullFolderPath, $"CreateSecurityPolicies_{tableNameWithoutSchema}.sql");
string filePathDrop = Path.Combine(fullFolderPath, $"DropSecurityPolicies_{tableNameWithoutSchema}.sql");
//If .sql files doesn't exists, create them
if (!File.Exists(filePathCreate))
{
using (StreamWriter sw = new StreamWriter(filePathCreate, true))
{
sw.WriteLine("ALTER SECURITY POLICY rls.tenantAccessPolicy");
//Note: Don't concatenate 'dbo.{}' because 'createTableOperation.Name' already include 'dbo'
sw.WriteLine($" ADD FILTER PREDICATE rls.fn_tenantAccessPredicateWithSuperUser(CompanyID) ON {createTableOperation.Name},");
sw.WriteLine($" ADD BLOCK PREDICATE rls.fn_tenantAccessPredicateWithSuperUser(CompanyID) ON {createTableOperation.Name}");
sw.WriteLine("GO");
sw.Close();
}
}
if (!File.Exists(filePathDrop))
{
using (StreamWriter sw = new StreamWriter(filePathDrop, true))
{
sw.WriteLine("ALTER SECURITY POLICY rls.tenantAccessPolicy");
sw.WriteLine($" DROP FILTER PREDICATE ON {createTableOperation.Name},");
sw.WriteLine($" DROP BLOCK PREDICATE ON {createTableOperation.Name}");
sw.WriteLine("GO");
sw.Close();
}
}
}
然后,将我的SQL脚本放在一个文件夹中,手动将其添加到我的解决方案中。
Add-Migration只是为了运行我的SQL脚本,方法是将代码添加到空的(最新的)迁移类中。
public override void Up()
{
string sqlFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\Migrations\\SQLscripts\\CreateSecurityPolicies_Client.sql");
string sqlText = System.IO.File.ReadAllText(sqlFilePath);
Sql(sqlText);
}
public override void Down()
{
string sqlFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\Migrations\\SQLscripts\\DropSecurityPolicies_Client.sql");
string sqlText = System.IO.File.ReadAllText(sqlFilePath);
Sql(sqlText);
}
这是我现在能想到的最好的。我希望它可以帮助其他EntityFramework程序员!