简体   繁体   English

先在Entity Framework代码中自动生成存储过程

[英]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.

相关问题 是否可以使用代码优先实体框架在数据库上生成基本的CRUD存储过程? - Is it possible to generate basic CRUD stored procedures on database with code-first entity framework? 如何基于Entity Framework代码优先模型自动生成.mdf db(如果不存在) - How to automatically generate .mdf db if it does not exist based on Entity Framework code-first model 使用代码优先的存储过程? - Using stored procedures in code-first approach? 首先从Entity Framework 6.1.3调用存储过程 - Call stored procedure from Entity Framework 6.1.3 code-first 如何使用Entity Framework代码优先调用存储过程? - How to call stored procedure using Entity Framework code-first? 实体框架6代码优先的存储过程映射到复杂对象 - Entity Framework 6 code-first stored procedure map to complex objects 如何在实体框架 6(代码优先)中调用存储过程? - How to call Stored Procedure in Entity Framework 6 (Code-First)? Entity Framework Code First是否支持存储过程? - Does Entity Framework Code First support stored procedures? 首先在实体框架代码中更改CUD存储过程的命名约定 - Change naming convention of CUD stored procedures in entity framework code first 实体框架代码首先使用复合主键映射存储过程 - Entity framework code first map stored procedures with composite primary keys
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM