EF 首先使用现有 table 的代码
EF using code first with existing table
我正在使用 MVC5 和 EF6。我正在做代码优先的方法。我有一些需要使用迁移(有效)生成的 tables 和一些我需要从现有数据库使用的 tables - tables.
在 DbContext class 我有
'new table that is created in the DB (works)
public DbSet<Subscription> Subscriptions { get; set; }
public DbSet<Memeber> Members { get; set; }
'existing table.
public DbSet<CodeTable> CodeTable { get; set; }
在配置中-(迁移文件夹)
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
它现在做什么,它创建了一个新的 table 称为 CodeTables
- 变成了复数,这是为什么呢?- 可以关掉吗?
- 如何使用代码Table而不生成新的table?
- 当我手动删除使用 codefirst 生成的 table,即成员 table。那我运行
Update-Database -Verbose -Force(没有任何作用)
使用启动项目 'Test'.
使用 NuGet 项目 'Test'.
指定“-Verbose”标志以查看应用于目标数据库的 SQL 语句。
目标数据库是:'TESTDB'(数据源:10.10.50.89,提供者:
System.Data.SqlClient,来源:配置)。
没有挂起的显式迁移。
运行种子方法。
然后运行应用程序,我得到一个异常
System.Data.SqlClient.SqlException (0x80131904): 对象名称无效 'dbo.Members'。在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常
因为table没有找到。 Table 不会生成。
如果 table 没有找到,我如何让它知道。创建它?
我注意到如果删除 __MigrationHistory 然后 运行 更新数据库。然后它抱怨我存在的其他 tables
数据库中已经有一个名为 'Subscriptions' 的对象。
而且只有当我删除所有 table 时它才有效。但这似乎很傻,删除所有table。我希望有另一种方法。
要对现有数据库使用代码优先,您需要做两件事:1) 指定连接字符串和 2) 关闭数据库初始化策略。这两件事可以通过以下上下文示例来实现:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext()
: base("ConnectionStringName")
{
Database.SetInitializer<ApplicationDbContext>(null);
}
// DbSets here
}
现在,按照惯例,Entity Framework 假定您的 table 名称是实体 class 名称的复数形式。如果 table 名称不是复数 and/or 它与实体 class 名称不同,那么您可以使用 Table
属性来准确指定它应该是什么:
[Table("foo_table")]
public class Foo
{
// properties
}
同样,如果您的列名称与您的 属性 名称不匹配,您可以使用 Column
属性来指定那些:
[Column("strFoo")]
public string Foo { get; set; }
更新
初读时,我没有注意到您试图将现有 table 与代码优先生成的 table 混合搭配。你不能做这个。由于使用现有的 database/existing tables 需要禁用初始化策略,因此该数据库中的所有 tables 必须存在或 Entity Framework 必须生成所有 tables。不能半途而废。
如果您需要利用一些现有的 table 并让 EF 创建一些,您需要两个数据库和两个上下文,一个是 EF 将首先通过代码生成所有内容,另一个是关闭初始化策略并且您负责数据库和 tables。重要的是,这意味着您可以 而不是 混合搭配这些。您所有的代码优先实体都不能通过导航属性引用任何现有的数据库实体,否则它们将被隐式添加到代码优先上下文中,EF 将生成 tables.
您能做的最好的事情是拥有一个包含相关实体 ID 的常规 属性,然后手动使用此 ID 从现有数据库上下文中查找实体。换句话说,它不是真正的外键,你将无法使用延迟加载等
我的做法有所不同 - 我创建了一个包含我将永远需要的所有表的大型上下文 - 并在该上下文上进行 migrations/DB 更新。然后创建几个 "read-only" 上下文 - 在我称之为 Database.SetInitializer(null)
的意义上 - 意味着它们不会有迁移等 - 并且只添加必要的 DbSet
。这样我就可以准确地实现你所描述的。
我正在使用 MVC5 和 EF6。我正在做代码优先的方法。我有一些需要使用迁移(有效)生成的 tables 和一些我需要从现有数据库使用的 tables - tables.
在 DbContext class 我有
'new table that is created in the DB (works)
public DbSet<Subscription> Subscriptions { get; set; }
public DbSet<Memeber> Members { get; set; }
'existing table.
public DbSet<CodeTable> CodeTable { get; set; }
在配置中-(迁移文件夹)
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
它现在做什么,它创建了一个新的 table 称为 CodeTables
- 变成了复数,这是为什么呢?- 可以关掉吗?
- 如何使用代码Table而不生成新的table?
- 当我手动删除使用 codefirst 生成的 table,即成员 table。那我运行
Update-Database -Verbose -Force(没有任何作用)
使用启动项目 'Test'.
使用 NuGet 项目 'Test'.
指定“-Verbose”标志以查看应用于目标数据库的 SQL 语句。
目标数据库是:'TESTDB'(数据源:10.10.50.89,提供者:
System.Data.SqlClient,来源:配置)。
没有挂起的显式迁移。
运行种子方法。
然后运行应用程序,我得到一个异常
System.Data.SqlClient.SqlException (0x80131904): 对象名称无效 'dbo.Members'。在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常
因为table没有找到。 Table 不会生成。
如果 table 没有找到,我如何让它知道。创建它?
我注意到如果删除 __MigrationHistory 然后 运行 更新数据库。然后它抱怨我存在的其他 tables
数据库中已经有一个名为 'Subscriptions' 的对象。
而且只有当我删除所有 table 时它才有效。但这似乎很傻,删除所有table。我希望有另一种方法。
要对现有数据库使用代码优先,您需要做两件事:1) 指定连接字符串和 2) 关闭数据库初始化策略。这两件事可以通过以下上下文示例来实现:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext()
: base("ConnectionStringName")
{
Database.SetInitializer<ApplicationDbContext>(null);
}
// DbSets here
}
现在,按照惯例,Entity Framework 假定您的 table 名称是实体 class 名称的复数形式。如果 table 名称不是复数 and/or 它与实体 class 名称不同,那么您可以使用 Table
属性来准确指定它应该是什么:
[Table("foo_table")]
public class Foo
{
// properties
}
同样,如果您的列名称与您的 属性 名称不匹配,您可以使用 Column
属性来指定那些:
[Column("strFoo")]
public string Foo { get; set; }
更新
初读时,我没有注意到您试图将现有 table 与代码优先生成的 table 混合搭配。你不能做这个。由于使用现有的 database/existing tables 需要禁用初始化策略,因此该数据库中的所有 tables 必须存在或 Entity Framework 必须生成所有 tables。不能半途而废。
如果您需要利用一些现有的 table 并让 EF 创建一些,您需要两个数据库和两个上下文,一个是 EF 将首先通过代码生成所有内容,另一个是关闭初始化策略并且您负责数据库和 tables。重要的是,这意味着您可以 而不是 混合搭配这些。您所有的代码优先实体都不能通过导航属性引用任何现有的数据库实体,否则它们将被隐式添加到代码优先上下文中,EF 将生成 tables.
您能做的最好的事情是拥有一个包含相关实体 ID 的常规 属性,然后手动使用此 ID 从现有数据库上下文中查找实体。换句话说,它不是真正的外键,你将无法使用延迟加载等
我的做法有所不同 - 我创建了一个包含我将永远需要的所有表的大型上下文 - 并在该上下文上进行 migrations/DB 更新。然后创建几个 "read-only" 上下文 - 在我称之为 Database.SetInitializer(null)
的意义上 - 意味着它们不会有迁移等 - 并且只添加必要的 DbSet
。这样我就可以准确地实现你所描述的。