2016-08-09 489 views
0

Ich habe eine Reihe von Klassen, die alle A[1..n]B von einer abstrakten Klasse erben. Jede dieser A Instanzen würde nur eine einzige Eigenschaft hinzugefügt haben - eine Fremdschlüsselzuordnung zu einer separaten Tabelle für jede Instanz. Jede Fremdschlüsselspalte hat den Namen ForeignKeyId, nicht den Namen der Tabelle, also habe ich im Wesentlichen eine Reihe von Tabellen, die bis auf den Namen ziemlich identisch sind.gespeicherte Prozeduren generieren automatisch in Entity Framework Code-first

Ich möchte eine gespeicherte Prozedur schreiben, die Datensätze aus diesen Tabellen mit einigen spezifischen SQL Gruppierung und Bestellung und Verbinden und so weiter geladen wird. Der wichtigste Teil ist nicht die Abfrage selbst, sondern die gespeicherte Prozedur mit einem bestimmten Namen automatisch ohne Hinzufügen Zeile für Zeile manuell in der Migration selbst (was in dieser Frage ist die top-rated Antwort: Create Stored Procedures using Entity Framework Code First?) zu schaffen.

Ich habe versucht, die Schaffung zusätzlicher Operationen im 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); 
} 

Allerdings ist meine Migration vollständig leer:

public partial class TestMigration : DbMigration 
{ 
    public override void Up() 
    { 
    } 

    public override void Down() 
    { 
    } 
} 

Sobald ich den Generator bekommen zu schaffen, etwas zu beginnen, kann ich fine-tune es von dort aus, aber ich bin ratlos darüber, wie man es schafft, eine gespeicherte Prozedur bei einer Migration zu erstellen.

+0

warum müssen Sie eine gespeicherte Prozedur auf die Migration erstellen haben Sie sie für den Migrationsprozess benötigen? Sie können sie bei OnModelCreating erstellen und wenn die Migration aufgerufen wird, wird die Methode ausgeführt? –

+0

@BassamAlugili Ich muss sie nicht bei der Migration erstellen, obwohl ich denke, dass dies der einfachste Weg wäre, um sicherzustellen, dass die gespeicherten Prozeduren für neue Tabellen erstellt werden.Ich werde sie beim Erstellen von Modellen untersuchen - aber das sind keine einfachen Objektladungen, daher weiß ich nicht, wie ich das mit ModelBuilder erstellen soll. – Max

Antwort

1

Nach einigen zusätzlichen Graben, ich war in der Lage, herauszufinden, wie zu erreichen, was ich brauchte.

Alle meine gespeicherten Prozeduren werden die Tabellenstruktur basiert stark ab, ich kann so prüfen, welche Art von Veränderung während einer Migration auftritt und das proc gegebenenfalls ändern. Die ScaffoldMigration-Funktion enthält die Liste der Vorgänge für eine bestimmte Migration, jeweils vom Typ MigrationOperation. Diese Klasse hat zahlreiche Unterklassen, die hier gefunden werden: https://msdn.microsoft.com/en-us/library/system.data.entity.migrations.model.migrationoperation(v=vs.113).aspx

Da die gespeicherten Prozeduren mindestens die Tabellennamen zum Erstellen der gespeicherten Prozeduren benötigen (da ich einen gespeicherten proc pro Tabelle benötige), muss ich überprüfen, ob der Betrieb ist von der richtigen Art, und wenn ja, aus ihm den richtigen Wert ziehen:

foreach (MigrationOperation operation in operationsList) 
{ 
    if (operation is CreateTableOperation) 
    { 
     CreateTableOperation op = (CreateTableOperation) operation; 
     if (op.Name.Contains(ChangeTracker)) 
       procOps.Add(CreateLoadVersionProc(op.Name));    
    } 
} 

Wo procOps nur eine Liste von Migration Operationen ist: List<MigrationOperation> procOps = new List<MigrationOperation>();.

Die CreateLoadVersionProc gibt einfach ein neues CreateProcedureOperation Objekt:

private static CreateProcedureOperation CreateLoadVersionProc(string tableName) 
{ 
    string proc = [email protected]"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; 
} 

Dann zurück in meine ScaffoldMigration Funktion, habe ich einfach die Liste der gespeicherten Prozedur Operationen füge ich in die Liste der Operationen in die Funktion übergeben erstellt:

if (procOps.Any()) 
    operationsList.AddRange(procOps); 

Dann geht die Funktion zum CSharpMigrationGenerator Schöpfung und die Generate Funktionsaufruf eine Migration auszuspucken.