2011-08-25 12 views
14

ASP.NET MVC 3のC#から共有ホスティング環境のSQL Server 2008データベースに接続しようとしていますEF経由で接続するアプリケーション(コードが最初にあります)。Code First Entity Framework(C#ASP.NET MVC 3)でdbo以外のSQLユーザー名を指定する

エラー Invalid object nameがスローされますが、私がやる時に正常に動作
SELECT ... FROM [dbo].[TableName] 

SELECT ... FROM [mySQLUserName].[TableName] 

がどのように私は他のユーザー名を指定してください

私の問題は、生成されたSELECT文はそうのように見えるということですdbo(例:mySQLUserName)?


EDIT:

私は、この問題に関連していることを発見した最も近いの記事は以下のとおりです。

上の特定の重点を置いて

セただし、ユーザー名をdbo以外に設定する方法は指定していません。

答えて

13

エンティティクラスを修飾するTableAttributeのプロパティを使用してスキーマを指定できます。

[Table("TableName", Schema = "mySQLUserName")] 
+0

あなたは、天才です! これは実際には、この質問に提供されているものよりもはるかに良い答えです:http://stackoverflow.com/questions/6399443/entityframework-using-wrong-tablename –

+0

'OnModelCreating' /' ToTable'ソリューションはより高度なマッピングシナリオには向いていますが、コンパイル時にスキーマ名を知っているので、単純なオプションはうまくいくはずです。 –

+5

これをグローバルに設定する方法はありますか? EFは、私たちがそれを指定しているときには、嫌な言葉でdboを使用しています。私のクラスをすべて変えるのは面倒です。 – ppumkin

3

あなたはTableAttributeであなたのクラスを飾ると、スキーマを指定するか、このpostが記述する何を試みることができることができます。

+0

デコレータは美しく動作します! –

7

使用しているEFのバージョンは表示されません。あなたは、コードファースト(4.1)を使用している場合は、テーブルの属性にスキーマを指定することができます。

[Table("Users", Schema = "myschema")] 
public class User { .. } 

をあなたは基礎としてスコットの記事(1秒)を使用することはできますが、追加のパラメータを追加します。すなわち:

modelBuilder.Entity<YourType>().ToTable("TableName", "SchemaName"); 
+0

ありがとう!私は 'ToTable'メソッドがスキーマ名の指定を可能にするためにオーバーロードされていることに気づいていませんでした。非常に便利! –

+0

これは複数形を破壊します。 – ANeves

4

私はこの質問は少し古いですけど、私は私の研究では、それに出くわしたと他の人に利益をもたらすことができ、@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); 
    } 
} 

ここで注意すべき重要なことSchemaNameEntityConfigurationToTable()メソッドです。これはスーパークラスのメソッドをオーバーライドし、実装が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が(インスタンスレベルではなく)静的なクラスレベルでモデルをキャッシュすると、問題になる可能性があります。それはコンテキストの別々のサブクラスを作成することで解決されるかもしれません。それぞれ異なるスキーマ名を指定します。

+1

ありがとう! +1 +ビールという壮大な答え – ppumkin

7

これでEF6を使用できるようになりました。

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.HasDefaultSchema("logs"); //set default schema 
     modelBuilder.Configurations.Add(new LogMap()); 
     ... 
    } 
関連する問題