so che questa domanda è un po 'vecchio, ma mi sono imbattuto nella mia ricerca e si avvicinò con una soluzione che può beneficiare gli altri, e hanno discusso privatamente con @ppumkin.
Il nome dello schema può essere passato come una stringa al metodo ToTable(), quindi essenzialmente utilizzando un membro della classe contenitore anziché un valore codificato consente di specificare dinamicamente il nome dello schema al momento della creazione del contesto.
Questa è una versione dumbed giù di ciò che ho:
public class FooDbContext : DbContext
{
public string SchemaName { get; set; }
static FooDbContext()
{
Database.SetInitializer<FooDbContext>(null);
}
public FooDbContext(string schemaName)
: base("name=connString1")
{
this.SchemaName = schemaName;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new City_Map(this.SchemaName));
modelBuilder.Configurations.Add(new Customer_Map(this.SchemaName));
modelBuilder.Configurations.Add(new CustomerSecurity_Map(this.SchemaName));
base.OnModelCreating(modelBuilder);
}
public DbSet<Customer> Customers { get; set; }
public DbSet<City> Cities { get; set; }
}
E la mappatura classe astratta:
public abstract class SchemaNameEntityTypeConfiguration<TEntityType> : EntityTypeConfiguration<TEntityType> where TEntityType : class
{
public string SchemaName { get; set; }
public SchemaNameEntityTypeConfiguration(string schemaName)
: base()
{
this.SchemaName = schemaName;
}
public new void ToTable(string tableName)
{
base.ToTable(tableName, SchemaName);
}
}
Implementazione:
public class City_Map : SchemaNameEntityTypeConfiguration<City>
{
public City_Map(string schemaName)
: base(schemaName)
{
ToTable("City");
HasKey(t => t.Code);
Property(t => t.Code)
.HasColumnType("integer")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
Property(t => t.CityName)
.HasColumnName("City")
.HasMaxLength(50);
Property(t => t.State)
.HasMaxLength(2);
}
}
La cosa fondamentale da notare qui è il metodo ToTable()
in SchemaNameEntityConfiguration
. Sostituisce il metodo della superclasse, quindi quando le implementazioni chiamano ToTable(tableName)
, fornisce anche il nome dello schema.
Importante: EntityTypeConfiguration.ToTable()
è non virtuale, e l'astratto SchemaNameEntityTypeConfiguration
nasconde tale metodo con una propria e quindi non si chiamerà praticamente se l'oggetto è _Map
tipo EntityTypeConfiguration
.
E 'stata una mia preoccupazione, ma c'è un facile (e solo un po' fastidioso) aggirare: invece di attuare una classe di base che fornisce automaticamente, basta garantire nei _Map
classi si passa il schemaName
-ToTable()
.
Usage:
using (FooDbContext context = new FooDbContext("theSchemaName"))
{
foreach (
var customer in context.Customers
.Include(c => c.City)
.Where(c => c.CustomerName.StartsWith("AA"))
.OrderBy(c => c.CustomerCode)
)
{
Console.WriteLine(string.Format(
"{0:20}: {1} - {2}, {3}",
customer.CustomerCode,
customer.CustomerName,
customer.City.CityName,
customer.City.State));
}
}
Disclaimer: non ho ancora testato l'utilizzo di più contexes all'interno dello stesso programma. Non dovrebbe avere un problema, ma se DbContext memorizza nella cache il modello a livello di classe statico (piuttosto che a livello di istanza), potrebbe essere un problema. Ciò può essere risolto creando sottoclassi separate del contesto, ognuna specificando un nome di schema diverso.
Signore, sei un genio! Si sa, questa è in realtà una risposta molto migliore di quella fornita per questa domanda: http://stackoverflow.com/questions/6399443/entityframework-using-wrong-tablename –
La soluzione 'OnModelCreating' /' ToTable' è utile per scenari di mapping più avanzati, ma poiché si conosce il nome dello schema in fase di compilazione, l'opzione semplice dovrebbe funzionare correttamente. –
C'è un modo per impostarlo globalmente? EF usa dbo by deafult senza che lo specifichiamo .. così fastidioso cambiando tutte le mie classi – ppumkin