【问题标题】:Generate stored procedures automatically in Entity Framework code-first在实体框架代码优先中自动生成存储过程
【发布时间】:2016-08-09 14:51:19
【问题描述】:

我有一组类A[1..n],它们都继承自抽象类B。这些A 实例中的每一个都只会添加一个属性 - 每个实例的外键映射到单独的表。每个外键列都有名称ForeignKeyId,而不是表的名称,所以基本上我有一组表,除了名称之外几乎相同。

我想编写一个存储过程,它使用一些特定的 SQL 分组、排序和连接等从这些表中加载记录。重要的部分不是查询本身,而是自动创建具有特定名称的存储过程无需在迁移本身中逐行手动添加(这是该问题中评价最高的答案: Create Stored Procedures using Entity Framework Code First?)。

我尝试在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()
    {
    }
}

一旦我可以让生成器开始创建任何东西,我就可以从那里对其进行微调,但我不知道如何让它在迁移时创建存储过程。

【问题讨论】:

  • 为什么需要在迁移时创建存储过程 在迁移过程中是否需要它们?您可以在 OnModelCreating 上创建它们,并且在调用迁移时将执行该方法?
  • @BassamAlugili 我不需要在迁移时创建它们,但我认为这是确保在新表上创建存储过程的最简单方法。我会考虑在模型创建时创建它们 - 但这些不是简单的对象加载,所以我不确定如何使用 ModelBuilder 构建它。

标签: c# entity-framework


【解决方案1】:

因此,经过一些额外的挖掘,我能够弄清楚如何完成我需要的工作。

我的所有存储过程都在很大程度上基于表结构,因此我可以检查迁移过程中发生了什么样的变化并适当地修改过程。 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&lt;MigrationOperation&gt; procOps = new List&lt;MigrationOperation&gt;();

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 函数调用以吐出迁移。

【讨论】:

    猜你喜欢
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多