簡體   English   中英

先在Entity Framework代碼中自動生成存儲過程

[英]Generate stored procedures automatically in Entity Framework code-first

我有一組類A[1..n] ,它們都從抽象類B繼承。 這些A實例中的每個實例都只會添加一個屬性-外鍵映射到每個實例的單獨表。 每個外鍵列的名稱都是ForeignKeyId ,而不是表的名稱,因此從本質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()
    {
    }
}

一旦讓生成器開始創建任何東西,就可以從那里進行微調,但是我對如何獲取它以在遷移中創建存儲過程感到困惑。

因此,經過一些額外的挖掘,我能夠弄清楚如何完成我所需要的。

我所有的存儲過程都高度依賴於表結構,因此我可以檢查遷移過程中發生的更改,並適當地修改proc。 ScaffoldMigration函數包含給定遷移的操作列表,每個操作類型均為MigrationOperation 此類具有許多子類,可以在這里找到: https : //msdn.microsoft.com/zh-cn/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函數的調用以吐出遷移。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM