0

理論的には、次のような名前の不明な数のテーブルを持つデータベースがあるとしましょう。

MyTable1
MyTable2
MyTable3
..

等々。これらの各テーブルには、まったく同じスキーマがあります。これらのテーブルがデータベースにいくつ存在するかはわかりません。

EF5.0 とコード ファーストを使用して、パラメーターを渡すことで、1 つの DbContext を介してこれらのテーブルのいずれかを参照できるようにしたいと考えています。

using (var db = new MyContext())
{
    db.GetMyTable(2).ForEach(e => Console.WriteLine("Table 2 entry: " + e.MyField));
    db.GetMyTable(5).ForEach(e => Console.WriteLine("Table 5 entry: " + e.MyField));
}

これは可能ですか?

.ToTable()これを行う別の方法は、完全に異なるコンテキストを作成し、マッピングで正しいものを提供することです。

public class MyContext : DbContext
{
    private int _tableNumber;

    static MyContext()
    {
        Database.SetInitializer<MyContext>(null);
    }

    public MyContext(int tableNumber) : base("Name=TheContextName")
    {
        _tableNumber = tableNumber;
    }

    public DbSet<MyTable> MyTableEntries { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        System.Data.Entity.ModelConfiguration.Conventions.
        modelBuilder.Configurations.Add(new MyTableMap(_tableNumber));
    }
}


 public class MyTableMap : EntityTypeConfiguration<MyTable>
 {
    public MyTableMap(int tableNumber)
    {
        // Primary Key
        this.HasKey(t => t.id);

        // Table & Column Mappings
        this.ToTable("MyTable" + tableNumber);
        this.Property(t => t.id).HasColumnName("id");
        this.Property(t => t.n).HasColumnName("MyField");

    }
 }

そして、処理したいテーブルに基づいて、別のコンテキストで操作できます。

Console.WriteLine("Contents of MyTable1:");
using (var db = new MyContext(1))
{
    db.MyTableEntries.ToList().ForEach(n => Console.WriteLine(n.MyField));
}

Console.WriteLine("Contents of MyTable2:");
using (var db = new MyContext(2))
{
    db.MyTableEntries.ToList().ForEach(n => Console.WriteLine(n.MyField));
}

ただし、OnModelCreating()コンテキスト内では最初のインスタンス化で 1 回しか呼び出されないため、そのテーブルは常に MyTable1 にマップされます。OnModelCreating()毎回呼び出されるようにオフにできるある種のキャッシュはありますか?もしそうなら、これは良い考えですか? これを行うよりエレガントな方法はありますか?

4

1 に答える 1

1

これらのテーブルがデータベースにいくつ存在するかはわかりません。

したがって、単一のコンテキストでは不可能であり、特に最初にコードを使用する場合は不可能です。EDMX はこのケースをサポートしますが (EDMX デザイナーはサポートしません)、設計時にすべてのテーブルを定義できる場合に限ります。それはMESTと呼ばれます。

ただし、コンテキスト内の OnModelCreating() は最初のインスタンス化で 1 回しか呼び出されないため、そのテーブルは常に MyTable1 にマップされます。

はい、まさにそれが起こります。モデルの作成は非常にコストのかかる操作であり、モデルはアプリケーションの存続期間全体にわたって再利用されるため、一度だけ実行されます。

これを行うよりエレガントな方法はありますか?

方法はありますが、エレガントとはかけ離れています。

  • DbModelBuilder のインスタンスを手動で作成し、必要なすべてのマッピングを入力します
  • そのインスタンスでビルドを呼び出してインスタンスを取得しDbModelます
  • DbModelインスタンスでCompile を呼び出して取得DbCompiledModel(これをキャッシュ)
  • DbCompiledModelインスタンスをDbContextコンストラクタに渡す

洗練された方法は、そのアプローチを使用せず、代わりにcontext.Database.SqlQuery動的クエリを実行して型のインスタンスを返すことです-クエリが型のプロパティと同じ名前の列を返す場合、EFはマッピングなしでもそれを処理しますが、読み取り専用ソリューション。

于 2012-09-08T21:46:31.700 に答える