2012-06-21 6 views
5

Ich muss eine C# -Anwendung schreiben, die mit einer SQL-Server-Datenbank arbeitet, die von einer alten Anwendung erstellt und verwaltet wird. Die Anwendung erstellt jedes Jahr neue Tabellen, und die "Jahr-Eigenschaft" befindet sich im Tabellennamen. Die Anzahl der erstellten Tabellen hängt von der Anzahl der "Abschnitte" ab, die der Benutzer innerhalb der Anwendung erstellt hat. Also muss ich mit Tabellen wie Cwx_DRyz arbeiten (ziemlich selbsterklärend ...), wobei "wx" der Abschnitt sein kann und "yz" das Jahr wäre. Ein Beispiel für eine Gruppe von Tabellen könnte sein:Ändern der Entitätszuordnung in eine andere "unbekannte" Tabelle zur Laufzeit

C01_DR07

C01_DR08

C01_DR09

C02_DR08

C02_DR09

C03_DR06

C04_DR12

Und alle diese Tabellen könnten zum Beispiel Clients darstellen. Sie wären Kunden aus verschiedenen Bereichen und Jahren, aber Kunden mit der gleichen Struktur.

Meine Frage ist: Kann ich eine Client-Entität haben, um alle diese Tabellen zu behandeln und die Zuordnung von einer zur anderen zur Laufzeit zu ändern? Der Titel sagt "unbekannt", weil ich die Tabellen vor der Laufzeit nicht kenne.

Die ähnlichste Frage, die ich gefunden habe, ist Entity Framework map multiple tables to one entity und die Antwort ist die "Tabelle Per Concrete Type Vererbung", aber es ist nicht nützlich für meinen Fall.

PS: EF-Version 4.3.1 und VS2010

EDIT: Die Tabellen haben keine Primärschlüssel ... Die meisten von ihnen Spalten haben, die supossed eindeutige Werte haben (integer oder string).

Antwort

4

Wenn Sie "Code zuerst" verwenden, können Sie ein Mapping erstellen, wie Sie möchten. Dies funktioniert auch mit vorhandenen Datenbanken, wenn das von Ihnen erstellte Mapping mit der Datenbank übereinstimmt.

Wenn Sie also einen Kontext erstellen, können Sie die Zeichenfolge (Tabellenname) erstellen, der Sie zuordnen möchten.

Einige codesamples für „Code zuerst“, und wie könnten Sie beginnen:

Die DbContext:

public DbSet<YourEntity> YourEntities { get; set; } 
... 

// this is called when the db gets created and does the configuration for you => maybe not needed in your case 
protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    ConfigurationRegistrar configurationRegistrar = modelBuilder.Configurations; 

    new GeneralEntitiesConfiguration(configurationRegistrar); 
} 

GeneralEntitiesConfiguration ist eine Klasse im Konfigurationen, nicht mehr als ein Helfer zu handhaben verwendet, die wie folgt aussieht :

public class GeneralEntitiesConfiguration 
{ 
    public GeneralEntitiesConfiguration(ConfigurationRegistrar configurationRegistrar) 
    { 
     configurationRegistrar.Add(new YourEntityConfiguration()); 
     //and additional configurations for each entity, just to splitt it a bit and have it more read and maintenance able 
    } 
} 

YourEntityConfiguration ist eine Klasse, wo ich die Konfigurationen alle für diese Entität haben:

public class YourEntityConfiguration : EntityTypeConfiguration<YourEntity> 
{ 
    public YourEntityConfiguration() 
    { 
     ToTable("WhatEverYouLike"); // here you can do any magic to map this entity to a table, just make sure that your properties are mapped to the correct colums 
     Property(entity => entity.Id).HasColumnName("YouColumnName"); 

     //and here you also have to do the other configurations 
    } 
} 

Beim Start der Anwendung (oder vor dem ersten Initialisieren des Kontexts) müssen Sie die Datenbank initialisieren. Daher können Sie einen Initialisierer verwenden, der die Datenbank prüft und Unterschiede behandelt. Build-in dort sind Dinge wie "DropCreateDatabaseAlways" oder "DropCreateDatabaseIfModelChanges" => Sie müssten Ihre eigenen erstellen, die nur Unterschiede ignoriert.In meinem Beispiel habe ich eine erstellen, die nur eine Ausnahme auslöst, wenn das Modell unterscheidet sich (i Modelländerungen mit scipts für den ersten Versuch zu handhaben wollte):

//before using the context the first time i'm calling, you can ignore the connection string 
DbContextInitializer.Init(conString); 

public static class DbContextInitializer 
{ 
    public static void Init (string connectionString) 
    { 
     Database.SetInitializer(new CreateDbThrowExceptionIfModelDiffersInitializer<SMDbContext>()); 

     using(var dbContenxt = new MyDbContext(connectionString)) 
     { 
      try 
      { 
       dbContenxt.Database.Initialize(true); 
      } 
      catch(DatabaseModelDiffersException diffException) 
      { 
       // some magic... 
      } 
      catch(Exception ex) 
      { 
       // TODO: log 
       throw; 
      } 
     } 
    } 

    public class CreateDbThrowExceptionIfModelDiffersInitializer<TContext> : IDatabaseInitializer<TContext> where TContext : DbContext 
    { 
     public void InitializeDatabase(TContext context) 
     { 
      using (new TransactionScope(TransactionScopeOption.Suppress)) 
      { 
       if (!context.Database.Exists()) 
        context.Database.Create(); 
      } 

      if (!context.Database.CompatibleWithModel(true)) 
      { 
       throw new DatabaseModelDiffersException("Database Model differs!"); 
      } 
     } 

     protected virtual void Seed(TContext context) 
     { 
      // create data if you like 
     } 
    } 

    // just an exception i'm using for later useage 
    public class DatabaseModelDiffersException : Exception 
    { 
     public DatabaseModelDiffersException(string msg) : base(msg) 
     {} 
    } 
} 

Hoffnung, die Sie eine Idee von Ihnen haben können dynamische Tabelle behandeln Namen mit Entity Framework! Wenn es mehr Fragen gibt, fragen Sie einfach;)

+0

Das Mapping muss nicht mit der Datenbank übereinstimmen, da nicht alle Benutzer alle "entities" (Tabellensätze) erstellt haben. Ist es zwingend ein komplettes Spiel? Jedenfalls würde ich diese Proben zu schätzen wissen. – CarlosJ

+0

Ich poste es am Wochenende! –

+0

Ok, vielen Dank. – CarlosJ

Verwandte Themen