Укажите имя пользователя SQL, отличное от dbo, в Code First Entity Framework (C # ASP.NET MVC 3) - PullRequest
14 голосов
/ 25 августа 2011

Я пытаюсь подключиться к базе данных SQL Server 2008 в среде общего хостинга из C # из приложения ASP.NET MVC 3, подключающегося через EF (сначала код).

Моя проблема в том, что сгенерированный оператор SELECT выглядит так:

SELECT ... FROM [dbo].[TableName]

, который выдает ошибку Invalid object name, но работает нормально, когда я делаю:

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

Как указать имя пользователя, отличное от dbo (например, mySQLUserName)?


EDIT:

Самые близкие статьи, которые я нашел, которые имеют отношение к этой проблеме:

с особым акцентом на вторую статью, однако в нем не указано, как задать имя пользователя, отличное от dbo

Ответы [ 5 ]

13 голосов
/ 25 августа 2011

Вы можете указать схему, используя свойство TableAttribute, которое украшает ваши классы сущностей.

[Table("TableName", Schema = "mySQLUserName")]
7 голосов
/ 24 октября 2014

Теперь с EF6 вы можете сделать это.

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("logs");  //set default schema
        modelBuilder.Configurations.Add(new LogMap());
        ...
    }
7 голосов
/ 25 августа 2011

Вы не говорите, какую версию EF вы используете. Если вы используете Code First (4.1), вы можете указать схему для атрибута таблицы:

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

В качестве основы можно использовать статью Скотта (вторую), но вы добавляете дополнительный параметр. ie.:

modelBuilder.Entity<YourType>().ToTable("TableName", "SchemaName"); 
4 голосов
/ 09 февраля 2013

Я знаю, что этот вопрос немного стар, но я наткнулся на него в своем исследовании и нашел решение, которое может принести пользу другим, и обсудил его в частном порядке с @ 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);
    }
}

Ключевым моментом, на который следует обратить внимание, является метод ToTable() в SchemaNameEntityConfiguration. Он переопределяет метод суперкласса, поэтому, когда реализации вызывают ToTable(tableName), он также предоставляет имя схемы.

* Важное примечание: EntityTypeConfiguration.ToTable() не является виртуальным, и абстрактный SchemaNameEntityTypeConfiguration скрывает этот метод своим собственным и, следовательно, не будет вызываться виртуально, если объект _Map имеет тип EntityTypeConfiguration.

Это была моя проблема, но есть простой (и немного раздражающий) обходной путь: вместо реализации базового класса, который предоставляет его автоматически, просто убедитесь, что в _Map классах вы передаете schemaName в ToTable().

Использование:

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

Отказ от ответственности: я не тестировал использование нескольких контекстов в одной программе. Это не должно иметь проблемы, но если DbContext кэширует модель на статическом уровне класса (а не на уровне экземпляра), это может быть проблемой. Это может быть решено путем создания отдельных подклассов контекста, каждый из которых указывает свое имя схемы.

3 голосов
/ 25 августа 2011

Вы можете либо украсить свой класс с помощью TableAttribute и указать схему, либо вы можете попробовать то, что описывает этот пост .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...