【问题标题】:Auto Create Database Tables from Objects, Entity Framework从对象、实体框架自动创建数据库表
【发布时间】:2012-03-26 14:19:07
【问题描述】:

我正在尝试完成本教程http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/getting-started-with-mvc3-part4-cs,但我没有使用 SQL Server 的精简版,而是在本地计算机上使用完整安装。我阅读本教程的方式是假设实体框架从我定义的对象创建表。我的问题是,当我运行项目时,我不断收到无效的对象名称 dbo.movi​​es。我终于通过自己创建表来运行它,所以我知道连接字符串并且一切都是正确的。

我的问题是,是否可以从 C# 中创建的对象生成表?如果可以,如何?

【问题讨论】:

    标签: c# sql asp.net-mvc entity-framework


    【解决方案1】:

    是否可以从 C# 中创建的对象生成表?

    是的,这是可能的。在运行代码之前,您是否碰巧在 Management Studio 中手动创建了数据库?那可能是你的问题。使用 Code First,默认约定是在数据库不存在时创建数据库。如果数据库已经存在(即使没有表),那么它将只使用现有数据库(但不会尝试创建表)。

    您可以删除数据库并尝试再次运行代码以查看它是否会为您创建它,或者将以下行放入 Global.asax:

    Database.SetInitializer(new DropCreateDatabaseAlways<YourDbContextHere>());
    

    一旦它运行,我建议将该行更改为:

    Database.SetInitializer(new DropCreateDatabaseIfModelChanges<YourDbContextHere>());
    

    这些命名空间在System.Data.Entity中定义

    DbContext 类还公开了一个定义以下有用方法的数据库属性:

    Delete()
    Create()
    CreateIfNotExists()
    

    如果你这样定义你的类:

    public class MyContext : DbContext {}
    

    你可以像这样构造一个实例:

    MyContext db = new MyContext();
    db.Database.Delete();
    db.Database.Create();
    

    【讨论】:

    • 嗯,如果没有可供连接的初始数据库,我应该将什么放入连接字符串?我只是从中删除了初始目录片段并收到了相同的 Invalid object name 'dbo.Movies' 错误。
    • 连接字符串告诉它在哪里创建数据库。它不必存在。它将检测到它不存在,然后在不存在时尝试创建它。只要它具有正确的权限,一切都会很好地创建。我认为如果您删除数据库并保留相同的连接字符串,那么一切最终都会按照您希望的方式工作。
    • 哦,太棒了,非常感谢!最后一个问题,您建议将 Database.SetInitializer 放入哪种方法。我收到一个错误,它无法删除数据库,因为它正在使用中。我会假设应用程序本身。再次感谢,我和我的朋友花了很多时间搜索试图找出问题所在,并且永远不会猜到不应该创建数据库。
    • 我现在可能会把它放在 Global.asax 中。如果您有一些特定于数据库的助推器,它可能会在那里,但对于小型项目 Global.asax 很好。确保您始终处置您的 DbContext 对象,否则您将在删除数据库时遇到问题。它可能认为您的数据库现在仍然存在活动连接。
    【解决方案2】:
    ModelContext.Database.EnsureCreated();
    

    【讨论】:

    • 请解释你的问题。
    • @DakshMiglani 这是一个答案。
    【解决方案3】:

    如果您创建一个 Linq-to-Sql DataContext,您可以将结构直接注入到您的数据库中:

    DbDataContext db = new DbDataContext(connectionString);
    db.CreateDatabase();
    

    【讨论】:

      【解决方案4】:

      我不知道这是否符合规定,但使用代码优先的 EF,当我使用 AddRange 时,EF 通常会创建我定义的所有表。我想保留数据库,因为我想在应用程序运行之间保留其他表。我发现如果我没有删除 EF 创建的名为 __MigrationHistory 的表,则在删除它们后不会重新创建这些表。

      删除此表后,EF 将重新创建表,而无需重新创建数据库。

      这在生产中可能不是一个可取的方法,但对于我的开发需要,这解决了我的问题。也许它会帮助别人。

      【讨论】:

        【解决方案5】:

        您可以使用FenixRepo 库(也可用作nuget package)创建特定的表,这是您Context 的一部分。首先,您应该在启动时调用一次staticInitialize 方法,其中第一个参数是工厂方法,它返回您的Context 的实例,第二个是Configuration 的实例class .它将为您在Context 注册的所有表准备 SQL 脚本。对于 ASP.NET MVC,最好将此代码粘贴到 Global.asax:

        FenixRepositoryScriptExtractor.Initialize(() => new Context(), new Configuration());
        

        然后您可以通过这种简单的方式创建所需类型的表MyTable

        var repo = new FenixRepositoryCreateTable<MyTable>();
        //or repo = new FenixRepository<MyTable>();
        
        repo.CreateTable();
        

        此外,如果您的表分布在多个迁移之间,并且它们没有与其他表对应的任何内容,您可以通过 FenixAttribute 指定这些迁移(即迁移文件夹中的类的名称),它们将被用作SQL 脚本,将用于创建表:

        [Fenix(nameof(Initial), nameof(MyTableFirstMigration), nameof(MyTableSecondMigration))]
        public class MyTable
        {
            //some stuff
        }
        

        如果没有这个属性,库将使用 default 脚本。指定迁移总是更好,因为否则不能保证所有索引都会被创建,并且您可以在迁移中包含一些自定义代码,这些代码在 default 解决方案的情况下不会执行。

        在 MS SQL 的情况下,库与 EF 6.1.3 兼容并经过测试。

        【讨论】:

          猜你喜欢
          • 2020-06-01
          • 2021-06-24
          • 2019-12-24
          • 2011-01-22
          • 2011-09-28
          • 1970-01-01
          • 2015-09-22
          • 1970-01-01
          相关资源
          最近更新 更多