私はこの質問は少し古いですけど、私は私の研究では、それに出くわしたと他の人に利益をもたらすことができ、@ppumkinと個人的にそれを議論してきた解決策を考え出しました。
スキーマ名は文字列としてToTable()メソッドに渡すことができるため、基本的にハードコードされた値の代わりにそのクラスを含むメンバーを使用すると、コンテキスト作成時にスキーマ名を動的に指定できます。
これは私が持っているもののダウン易しく書き直さバージョンです:
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; }
}
とマッピング抽象クラス:
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);
}
}
実装:
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);
}
}
ここで注意すべき重要なことSchemaNameEntityConfiguration
のToTable()
メソッドです。これはスーパークラスのメソッドをオーバーライドし、実装がToTable(tableName)
を呼び出すときにスキーマ名も提供します。
*重要な注意:EntityTypeConfiguration.ToTable()
は非仮想あり、かつ抽象SchemaNameEntityTypeConfiguration
は、独自でその方法を隠し、_Map
オブジェクトのタイプがEntityTypeConfiguration
ようであればこのように事実と呼ばれることはありません。
は、それは私の1件の心配でしたが、簡単に(とわずかに迷惑が)あります回避:代わりに自動的に供給する基本クラスを実装するので、ちょうどあなたがToTable()
にschemaName
を渡す_Map
クラスで確認してください。
使用法:
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));
}
}
免責事項:私は、同じプログラム内で複数のcontexesを使用してテストしていません。それは問題はないはずですが、DbContextが(インスタンスレベルではなく)静的なクラスレベルでモデルをキャッシュすると、問題になる可能性があります。それはコンテキストの別々のサブクラスを作成することで解決されるかもしれません。それぞれ異なるスキーマ名を指定します。
あなたは、天才です! これは実際には、この質問に提供されているものよりもはるかに良い答えです:http://stackoverflow.com/questions/6399443/entityframework-using-wrong-tablename –
'OnModelCreating' /' ToTable'ソリューションはより高度なマッピングシナリオには向いていますが、コンパイル時にスキーマ名を知っているので、単純なオプションはうまくいくはずです。 –
これをグローバルに設定する方法はありますか? EFは、私たちがそれを指定しているときには、嫌な言葉でdboを使用しています。私のクラスをすべて変えるのは面倒です。 – ppumkin