2013-02-15 20 views
15

Ich versuche, meine dbContext einzurichten, so dass es mehrere Schemas in einer einzigen Oracle-Datenbank behandeln kann. Ich wollte nicht eine monolithische DbContext Datei, damit ich mit den folgenden habe kommen:Entity Framework und mehrere Schemas

public class oraDbContext : DbContext 
{ 
    static oraDbContext() { 
     Database.SetInitializer<oraDbContext>(null); 
    } 

    public oraDbContext(string connName) 
     : base("Name=" + connName) { } 

    public _schema1 schema1 = _schema1.Instance; 
    public _schema2 schema2 = _schema2.Instance; 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
     schema1.OnModelCreating(modelBuilder); 
     schema2.OnModelCreating(modelBuilder); 
    } 
} 

Die Schemadatei sieht wie folgt aus:

public sealed class _schema1 
{ 
    private static readonly _schema1 instance = new _schema1(); 

    static _schema1() { } 
    private _schema1() { } 

    public static _schema1 Instance { 
     get { 
      return instance; 
     } 
    } 

    public DbSet<someTable> someTable { get; set; } 

    internal void OnModelCreating(DbModelBuilder modelBuilder) { 
     modelBuilder.Configurations.Add(new someTableMap()); 
    } 
} 

Allerdings, wenn ich versuchen, eine Abfrage, die ich ausführen Erhalten Sie den Fehler: Value cannot be null. Der Wert, auf den es sich bezieht, ist die someTable-Eigenschaft in _schema1.

A. Wie kann ich das beheben?

B. Gibt es eine bessere Lösung?

Edit: Was ich hier will, ist die Möglichkeit, Code zu schreiben, wie die folgenden -

var query1 = from p in db.schema1.someTable 
      select p; 
var query2 = from p in db.schema2.someTable 
      select p; 

Wo sometable das gleiche in beiden Schemata ist. In unserer Datenbank haben wir mehrere Schemata mit genau denselben Tabellen, die identische oder fast identische Spalten haben. Ich möchte keinen separaten dbContext für jedes Schema erstellen, da dies möglicherweise 5 verschiedene Verbindungen bedeuten kann, wenn ich eine Abfrage erstelle, die aus 5 Schemas zieht. Wenn ich dieselbe Abfrage in SQL schreiben würde, könnte ich die Daten aus 5 verschiedenen Schemas mit einer einzigen Verbindung abrufen, und das möchte ich hier erreichen.

Antwort

10

Während einige der Forschung über Entity Framework ich über die folgenden Post kam:

http://romiller.com/2011/05/23/ef-4-1-multi-tenant-with-code-first/

Es ist nicht ganz geben Sie mir einen einzigen DbContext zu arbeiten mit, aber es verwendet nur eine einzige Verbindung (was mein Grund dafür war, dass ich nicht mehrere dbContexte verwenden wollte). Nach dem Setzen Sie den folgenden Code auf:

public class oraDbContext : DbContext 
{ 
    static oraDbContext() { 
     Database.SetInitializer<oraDbContext>(null); 
    } 

    private oraDbContext(DbConnection connection, DbCompiledModel model) 
     : base(connection, model, contextOwnsConnection: false) { } 

    public DbSet<SomeTable1> SomeTable1 { get; set; } 
    public DbSet<SomeTable2> SomeTable2 { get; set; } 

    private static ConcurrentDictionary<Tuple<string, string>, DbCompiledModel> modelCache = new ConcurrentDictionary<Tuple<string, string>, DbCompiledModel>(); 

    public static oraDbContext Create(string schemaName, DbConnection connection) { 
     var compiledModel = modelCache.GetOrAdd(
      Tuple.Create(connection.ConnectionString, schemaName), 
      t => 
      { 
       var builder = new DbModelBuilder(); 
       builder.Configurations.Add<SomeTable1>(new SomeTable1Map(schemaName)); 
       builder.Configurations.Add<SomeTable2>(new SomeTable2Map(schemaName)); 

       var model = builder.Build(connection); 
       return model.Compile(); 
      }); 

     return new oraDbContext(connection, compiledModel); 
    } 
} 

Dies ist natürlich, dass wie Dateien eingerichtet werden, meine Mapping erfordert so:

public class DailyDependencyTableMap : EntityTypeConfiguration<DailyDependencyTable> 
{ 
    public SomeTableMap(string schemaName) { 
     this.ToTable("SOME_TABLE_1", schemaName.ToUpper()); 

     //Map other properties and stuff 
    } 
} 

Schreiben von Abfragen, die mehrere Schemata verwenden ist etwas ärgerlich, aber für den Moment, es tut, was ich tun muss:

using (var connection = new OracleConnection("a connection string")) { 
    using (var schema1 = oraDbContext.Create("SCHEMA1", connection)) 
    using (var schema2 = oraDbContext.Create("SCHEMA2", connection)) { 

     var query = ((from a in schema1.SomeTable1 select new { a.Field1 }).ToList()) 
      .Concat((from b in schema2.SomeTable1 select new { b.Field1 }).ToList()) 
    } 
} 

 

+0

+1 für die Verwendung von GetOrAdd(), um Code lesbar zu verdichten. Ich möchte nur betonen, dass die Verwendung.ToList(), um Ergebnisse in den beiden Komponenten der Abfrage zusammenzuführen, ist entscheidend, da wir versuchen, Abfragen aus verschiedenen Kontexten zu kombinieren (<- mit Entitätsframework und wahrscheinlich auch anderen Orms, solche Operationen können nicht direkt auf die Datenbank angewendet werden). – xDisruptor

1

Versuchen Teilklassen anstelle

public partial class oraDbContext : DbContext 
{ 
    static oraDbContext() { 
     Database.SetInitializer<oraDbContext>(null); 
    } 

    public oraDbContext(string connName) 
     : base("Name=" + connName) { } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
     schema1(modelBuilder); 
     schema2(modelBuilder); 
    } 
} 

public partial class oraDbContext : DbContext 
{ 
    public DbSet<someTable> someTable { get; set; } 
    void schema1(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Configurations.Add(new someTableMap()); 
    } 
} 
+0

Endlich habe ich eine Chance bekommen, dies zu testen und bekomme einen Fehler: 'oraDbContext enthält bereits eine Definition für 'someTable'. Bearbeitete Frage, um besser zu reflektieren, wonach ich suche. – Kittoes0124

0

Sie können das Schema pro Tabelle über das Attribut Table angeben.

[Table(nameof(MyTable1), Schema = "Schema1")] 
public class MyTable1 { } 

[Table(nameof(MyTable2), Schema = "Schema2")] 
public class MyTable2 { }