首先在实体框架代码中自动生成存储过程

本文关键字:自动生成 存储过程 代码 框架 实体 | 更新日期: 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函数以生成迁移。