首先在实体框架代码中自动生成存储过程
本文关键字:自动生成 存储过程 代码 框架 实体 | 更新日期: 2023-09-27 18:01:25
我有一组从抽象类B
继承的类A[1..n]
。每个A
实例将只添加一个属性-一个外键映射到每个实例的单独表。每个外键列都有名称ForeignKeyId
,而不是表的名称,所以基本上我有一组表,除了名称之外,它们几乎完全相同。
我想写一个存储过程,使用一些特定的SQL分组、排序、连接和诸如此类的东西从这些表加载记录。重要的部分不是查询本身,而是自动创建具有特定名称的存储过程,而不需要在迁移过程中逐行手动添加(这是这个问题中最受欢迎的答案:首先使用实体框架代码创建存储过程?)
我已经尝试在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 );
}
但是,我的迁移是完全空的:
public partial class TestMigration : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
一旦我可以让生成器开始创建任何东西,我就可以从那里对它进行微调,但是我对如何让它在迁移中创建存储过程感到困惑。
因此,经过一些额外的挖掘,我能够弄清楚如何完成我所需要的。
我所有的存储过程都很大程度上基于表结构,所以我可以检查在迁移过程中发生了什么类型的更改,并酌情修改过程。ScaffoldMigration
函数包含给定迁移的操作列表,每个操作类型为MigrationOperation
。这个类有许多子类:https://msdn.microsoft.com/en-us/library/system.data.entity.migrations.model.migrationoperation(v=vs.113).aspx
由于存储过程至少需要表名来构建存储过程(因为每个表需要一个存储过程),因此需要检查操作的类型是否正确,如果是,则从中提取正确的值:
foreach (MigrationOperation operation in operationsList)
{
if (operation is CreateTableOperation)
{
CreateTableOperation op = (CreateTableOperation) operation;
if (op.Name.Contains( ChangeTracker ))
procOps.Add(CreateLoadVersionProc(op.Name));
}
}
其中procOps
只是迁移操作列表:List<MigrationOperation> procOps = new List<MigrationOperation>();
.
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;
}
然后,回到ScaffoldMigration
函数中,我只需将创建的存储过程操作列表添加到传递给函数的操作列表中:
if (procOps.Any())
operationsList.AddRange(procOps);
然后该函数继续创建CSharpMigrationGenerator
并调用Generate
函数以生成迁移。