[英]Specify an SQL username other than dbo in Code First Entity Framework ( C# ASP.NET MVC 3 )
我正在尝试从通过EF(代码优先)连接的ASP.NET MVC 3应用程序中的C#连接到共享托管环境中的SQL Server 2008数据库。
我的问题是生成的SELECT
语句如下所示:
SELECT ... FROM [dbo].[TableName]
抛出错误Invalid object name
,但在我这样做时工作正常:
SELECT ... FROM [mySQLUserName].[TableName]
如何指定dbo
以外的用户名(例如mySQLUserName
)?
编辑:
我发现的与此问题相关的最接近的文章是:
特别强调第二篇文章,但它没有指定如何设置除dbo
之外的用户名
您可以使用TableAttribute
用于装饰实体类的属性来指定架构。
[Table("TableName", Schema = "mySQLUserName")]
使用EF6,您现在可以执行此操作。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("logs"); //set default schema
modelBuilder.Configurations.Add(new LogMap());
...
}
您没有说您正在使用哪个版本的EF。 如果您使用Code First(4.1),则可以在表属性上指定架构:
[Table("Users", Schema = "myschema")]
public class User { .. }
您可以使用Scott的文章(第二篇)作为基础,但您添加了一个额外的参数。 即:
modelBuilder.Entity<YourType>().ToTable("TableName", "SchemaName");
我知道这个问题有点陈旧,但我在研究中遇到了这个问题,想出了一个可能使其他人受益的解决方案,并与@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)
它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将模型缓存在静态类级别(而不是在实例级别),则可能是一个问题。 这可以通过创建上下文的单独子类来解决,每个子类指定不同的模式名称。
您可以装饰你的类与TableAttribute并指定模式,或者你可以尝试一下这个职位描述。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.