2013-02-15 83 views
15

1つのOracleデータベースで複数のスキーマを処理できるようにdbContextを設定しようとしています。私は、次のを作ってみたので、私は1つのモノリシックdbContextファイルを望んでいませんでした:Entity Frameworkと複数のスキーマ

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); 
    } 
} 

スキーマファイルは次のようになります。しかし

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()); 
    } 
} 

、私はクエリを実行しようとすると、エラー:Value cannot be nullを取得します。それが参照している値は_schema1のsomeTableプロパティです。

aどうすればこの問題を解決できますか?

B.もっと良い解決策はありますか?

編集:私はここにしたいことは次のようなコードを書くための能力である - someTableは両方のスキーマで同じである

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

。私たちのデータベースでは、同一またはほぼ同じ列を持つ全く同じテーブルを持ついくつかのスキーマがあります。 5つのスキーマからプルするクエリを作成している場合、5つの異なる接続を意味する可能性があるため、各スキーマごとに個別のdbContextを作成する必要はありません。この同じクエリをまっすぐなSQLで書いていたら、1つの接続で5つの異なるスキーマからデータを取り出すことができました。これが私がここで達成したいことです。私は、次の記事に出くわした

答えて

10

を部分クラスを使用してみてください:

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

それは非常に私に単一dbContextを与えるものではありませんそれは複数のdbContextsを使いたくないという背反的な理由でした。

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); 
    } 
} 

もちろんこれは私のマッピングファイルがそのようにように設定されている必要があります:次のコードを設定した後しばらくの間、複数のスキーマを使用

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

     //Map other properties and stuff 
    } 
} 

ライティングクエリ多少面倒ですが、が、それは、私はそれが何をする必要があるかを行います。

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

GetOrAdd()を使用してコードを読み取り可能に縮退する場合は+1。それを使用するという事実に下線を引いてみたいですか?クエリの2つのコンポーネントの結果を結合するToList()は、異なるコンテキスト(< - エンティティ・フレームワーク、おそらくは他のormsも含む)からのクエリを組み合わせようとするため、非常に重要です。 – xDisruptor

1

Entity Frameworkのに関するいくつかの研究を行っている間代わり

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

私はついにこれをテストする機会を得ました。「oraDbContextには既に 'someTable'の定義が含まれています。私が探しているものをよりよく反映するように編集された質問。 – Kittoes0124

0

Table属性を使用してテーブルごとにスキーマを指定できます。

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

[Table(nameof(MyTable2), Schema = "Schema2")] 
public class MyTable2 { } 
関連する問題