[英]Generate stored procedures automatically in Entity Framework code-first
I have a set of classes A[1..n]
that all inherit from an abstract class B
. 我有一组类
A[1..n]
,它们都从抽象类B
继承。 Each of these A
instances would only have a single property added - a foreign key mapping to a separate table for each instance. 这些
A
实例中的每个实例都只会添加一个属性-外键映射到每个实例的单独表。 Each foreign key column has the name ForeignKeyId
, not the name of the table, so essentially I have a set of tables that are pretty much identical except for the name. 每个外键列的名称都是
ForeignKeyId
,而不是表的名称,因此从本质ForeignKeyId
,我有一组表,除了名称外,它们几乎相同。
I want to write a stored procedure that loads records from these tables using some specific SQL grouping and ordering and joining and whatnot. 我想编写一个存储过程,以使用某些特定的SQL分组,排序和联接等方式从这些表中加载记录。 The important part isn't the query itself, but creating the stored procedure with a specific name automatically without adding it line by line manually in the migration itself (which is the top-rated answer in this question: Create Stored Procedures using Entity Framework Code First? ).
重要的部分不是查询本身,而是自动创建具有特定名称的存储过程, 而无需在迁移本身中逐行手动添加它(这是此问题中评分最高的答案: 使用实体框架代码创建存储过程首先? )。
I've tried creating additional operations in the MigrationCodeGenerator
: 我试图在
MigrationCodeGenerator
创建其他操作:
public override ScaffoldedMigration Generate( string migrationId,
IEnumerable<MigrationOperation> operations, string sourceModel,
string targetModel, string @namespace, string className )
{
IList<MigrationOperation> operationsList = operations as IList<MigrationOperation> ?? operations.ToList();
var drop = new DropProcedureOperation($"{className}_LoadVersion");
var create = new CreateProcedureOperation($"{className}_LoadVersion", $"select * from {className}");
operationsList.Add( drop );
operationsList.Add(create);
CSharpMigrationCodeGenerator generator = new CSharpMigrationCodeGenerator();
return generator.Generate( migrationId, operationsList, sourceModel, targetModel, @namespace, className );
}
However, my migration is completely empty: 但是,我的迁移完全是空的:
public partial class TestMigration : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
Once I can get the generator to start creating anything, I can fine-tune it from there, but I'm stumped on how to get it to create a stored procedure on a migration. 一旦让生成器开始创建任何东西,就可以从那里进行微调,但是我对如何获取它以在迁移中创建存储过程感到困惑。
So after some additional digging, I was able to figure out how to accomplish what I needed. 因此,经过一些额外的挖掘,我能够弄清楚如何完成我所需要的。
All of my stored procedures are heavily based off the table structure, so I can check what kind of change is occurring during a migration and modify the proc as appropriate. 我所有的存储过程都高度依赖于表结构,因此我可以检查迁移过程中发生的更改,并适当地修改proc。 The
ScaffoldMigration
function contains the list of operations for a given migration, each of type MigrationOperation
. ScaffoldMigration
函数包含给定迁移的操作列表,每个操作类型均为MigrationOperation
。 This class has numerous sub-classes found here: https://msdn.microsoft.com/en-us/library/system.data.entity.migrations.model.migrationoperation(v=vs.113).aspx 此类具有许多子类,可以在这里找到: https : //msdn.microsoft.com/zh-cn/library/system.data.entity.migrations.model.migrationoperation(v=vs.113).aspx
As the stored procedures need, at the very least, the table names to build the stored procedures (as I need one stored proc per table), I need to check if the operation is of the right type, and if so, pull the correct value out of it: 由于存储过程至少需要表名称来构建存储过程(因为我需要每个表一个存储过程),所以我需要检查操作的类型是否正确,如果是,请拉正确的操作。从中获得价值:
foreach (MigrationOperation operation in operationsList)
{
if (operation is CreateTableOperation)
{
CreateTableOperation op = (CreateTableOperation) operation;
if (op.Name.Contains( ChangeTracker ))
procOps.Add(CreateLoadVersionProc(op.Name));
}
}
Where procOps
is just a list of Migration Operations: List<MigrationOperation> procOps = new List<MigrationOperation>();
其中
procOps
只是迁移操作的列表: List<MigrationOperation> procOps = new List<MigrationOperation>();
. 。
The CreateLoadVersionProc
simply returns a new CreateProcedureOperation
object: CreateLoadVersionProc
仅返回一个新的CreateProcedureOperation
对象:
private static CreateProcedureOperation CreateLoadVersionProc(string tableName)
{
string proc = $@"select x.*
from {tableName} x
where x.CreatedTimeStamp >= @target";
var op = new CreateProcedureOperation($"{tableName}_LoadVersion", proc);
var dateParam = new ParameterModel(PrimitiveTypeKind.DateTime) {Name = "@target"};
op.Parameters.Add(dateParam);
return op;
}
Then, back in my ScaffoldMigration
function, I simply add the list of stored procedure operations I created to the list of operations passed into the function: 然后,回到我的
ScaffoldMigration
函数中,我只需将我创建的存储过程操作列表添加到传递给该函数的操作列表中:
if (procOps.Any())
operationsList.AddRange(procOps);
Then the function proceeds to the CSharpMigrationGenerator
creation and the Generate
function call to spit out a migration. 然后,函数继续进行
CSharpMigrationGenerator
创建和Generate
函数的调用以吐出迁移。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.